1da0c48c4Sopenharmony_ci/* S390-specific core note handling.
2da0c48c4Sopenharmony_ci   Copyright (C) 2012 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   This file is part of elfutils.
4da0c48c4Sopenharmony_ci
5da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
6da0c48c4Sopenharmony_ci   it under the terms of either
7da0c48c4Sopenharmony_ci
8da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
9da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
10da0c48c4Sopenharmony_ci       your option) any later version
11da0c48c4Sopenharmony_ci
12da0c48c4Sopenharmony_ci   or
13da0c48c4Sopenharmony_ci
14da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
15da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
16da0c48c4Sopenharmony_ci       your option) any later version
17da0c48c4Sopenharmony_ci
18da0c48c4Sopenharmony_ci   or both in parallel, as here.
19da0c48c4Sopenharmony_ci
20da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
21da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
22da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23da0c48c4Sopenharmony_ci   General Public License for more details.
24da0c48c4Sopenharmony_ci
25da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
26da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
27da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
28da0c48c4Sopenharmony_ci
29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H
30da0c48c4Sopenharmony_ci# include <config.h>
31da0c48c4Sopenharmony_ci#endif
32da0c48c4Sopenharmony_ci
33da0c48c4Sopenharmony_ci#include <elf.h>
34da0c48c4Sopenharmony_ci#include <inttypes.h>
35da0c48c4Sopenharmony_ci#include <stddef.h>
36da0c48c4Sopenharmony_ci#include <stdio.h>
37da0c48c4Sopenharmony_ci#include <sys/time.h>
38da0c48c4Sopenharmony_ci
39da0c48c4Sopenharmony_ci#ifndef BITS
40da0c48c4Sopenharmony_ci# define BITS 		32
41da0c48c4Sopenharmony_ci# define BACKEND	s390_
42da0c48c4Sopenharmony_ci#else
43da0c48c4Sopenharmony_ci# define BITS 		64
44da0c48c4Sopenharmony_ci# define BACKEND	s390x_
45da0c48c4Sopenharmony_ci#endif
46da0c48c4Sopenharmony_ci#include "libebl_CPU.h"
47da0c48c4Sopenharmony_ci
48da0c48c4Sopenharmony_cistatic const Ebl_Register_Location prstatus_regs[] =
49da0c48c4Sopenharmony_ci  {
50da0c48c4Sopenharmony_ci#define GR(at, n, dwreg, b...)						\
51da0c48c4Sopenharmony_ci    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = b }
52da0c48c4Sopenharmony_ci
53da0c48c4Sopenharmony_ci    GR ( 0,  1, 64, BITS),				/* pswm */
54da0c48c4Sopenharmony_ci    GR ( 1,  1, 65, BITS, .pc_register = true ),	/* pswa */
55da0c48c4Sopenharmony_ci    GR ( 2, 16,  0, BITS),				/* r0-r15 */
56da0c48c4Sopenharmony_ci    GR (18, 16, 48,   32),				/* ar0-ar15 */
57da0c48c4Sopenharmony_ci
58da0c48c4Sopenharmony_ci#undef	GR
59da0c48c4Sopenharmony_ci  };
60da0c48c4Sopenharmony_ci
61da0c48c4Sopenharmony_ci  /* orig_r2 is at offset (BITS == 32 ? 34 * 4 : 26 * 8).  */
62da0c48c4Sopenharmony_ci#define PRSTATUS_REGS_SIZE	(BITS / 8 * (BITS == 32 ? 35 : 27))
63da0c48c4Sopenharmony_ci
64da0c48c4Sopenharmony_cistatic const Ebl_Register_Location fpregset_regs[] =
65da0c48c4Sopenharmony_ci  {
66da0c48c4Sopenharmony_ci#define FPR(at, n, dwreg)						\
67da0c48c4Sopenharmony_ci    { .offset = at * 64/8, .regno = dwreg, .count = n, .bits = 64 }
68da0c48c4Sopenharmony_ci
69da0c48c4Sopenharmony_ci    /* fpc is at offset 0, see fpregset_items, it has no assigned DWARF regno.
70da0c48c4Sopenharmony_ci       Bytes at offsets 4 to 7 are unused.  */
71da0c48c4Sopenharmony_ci    FPR (1 +  0, 1, 16),	/* f0 */
72da0c48c4Sopenharmony_ci    FPR (1 +  1, 1, 20),	/* f1 */
73da0c48c4Sopenharmony_ci    FPR (1 +  2, 1, 17),	/* f2 */
74da0c48c4Sopenharmony_ci    FPR (1 +  3, 1, 21),	/* f3 */
75da0c48c4Sopenharmony_ci    FPR (1 +  4, 1, 18),	/* f4 */
76da0c48c4Sopenharmony_ci    FPR (1 +  5, 1, 22),	/* f5 */
77da0c48c4Sopenharmony_ci    FPR (1 +  6, 1, 19),	/* f6 */
78da0c48c4Sopenharmony_ci    FPR (1 +  7, 1, 23),	/* f7 */
79da0c48c4Sopenharmony_ci    FPR (1 +  8, 1, 24),	/* f8 */
80da0c48c4Sopenharmony_ci    FPR (1 +  9, 1, 28),	/* f9 */
81da0c48c4Sopenharmony_ci    FPR (1 + 10, 1, 25),	/* f10 */
82da0c48c4Sopenharmony_ci    FPR (1 + 11, 1, 29),	/* f11 */
83da0c48c4Sopenharmony_ci    FPR (1 + 12, 1, 26),	/* f12 */
84da0c48c4Sopenharmony_ci    FPR (1 + 13, 1, 30),	/* f13 */
85da0c48c4Sopenharmony_ci    FPR (1 + 14, 1, 27),	/* f14 */
86da0c48c4Sopenharmony_ci    FPR (1 + 15, 1, 31),	/* f15 */
87da0c48c4Sopenharmony_ci
88da0c48c4Sopenharmony_ci#undef	FPR
89da0c48c4Sopenharmony_ci  };
90da0c48c4Sopenharmony_ci
91da0c48c4Sopenharmony_cistatic const Ebl_Core_Item fpregset_items[] =
92da0c48c4Sopenharmony_ci  {
93da0c48c4Sopenharmony_ci    {
94da0c48c4Sopenharmony_ci      .name = "fpc", .group = "register", .offset = 0, .type = ELF_T_WORD,
95da0c48c4Sopenharmony_ci      .format = 'x',
96da0c48c4Sopenharmony_ci    },
97da0c48c4Sopenharmony_ci  };
98da0c48c4Sopenharmony_ci
99da0c48c4Sopenharmony_ci/* Do not set FPREGSET_SIZE so that we can supply fpregset_items.  */
100da0c48c4Sopenharmony_ci#define EXTRA_NOTES_FPREGSET \
101da0c48c4Sopenharmony_ci    EXTRA_REGSET_ITEMS (NT_FPREGSET, 17 * 8, fpregset_regs, fpregset_items)
102da0c48c4Sopenharmony_ci
103da0c48c4Sopenharmony_ci#if BITS == 32
104da0c48c4Sopenharmony_ci# define ULONG			uint32_t
105da0c48c4Sopenharmony_ci# define ALIGN_ULONG		4
106da0c48c4Sopenharmony_ci# define TYPE_ULONG		ELF_T_WORD
107da0c48c4Sopenharmony_ci# define TYPE_LONG		ELF_T_SWORD
108da0c48c4Sopenharmony_ci# define UID_T			uint16_t
109da0c48c4Sopenharmony_ci# define GID_T			uint16_t
110da0c48c4Sopenharmony_ci# define ALIGN_UID_T		2
111da0c48c4Sopenharmony_ci# define ALIGN_GID_T		2
112da0c48c4Sopenharmony_ci# define TYPE_UID_T		ELF_T_HALF
113da0c48c4Sopenharmony_ci# define TYPE_GID_T		ELF_T_HALF
114da0c48c4Sopenharmony_ci#else
115da0c48c4Sopenharmony_ci# define ULONG			uint64_t
116da0c48c4Sopenharmony_ci# define ALIGN_ULONG		8
117da0c48c4Sopenharmony_ci# define TYPE_ULONG		ELF_T_XWORD
118da0c48c4Sopenharmony_ci# define TYPE_LONG		ELF_T_SXWORD
119da0c48c4Sopenharmony_ci# define UID_T			uint32_t
120da0c48c4Sopenharmony_ci# define GID_T			uint32_t
121da0c48c4Sopenharmony_ci# define ALIGN_UID_T		4
122da0c48c4Sopenharmony_ci# define ALIGN_GID_T		4
123da0c48c4Sopenharmony_ci# define TYPE_UID_T		ELF_T_WORD
124da0c48c4Sopenharmony_ci# define TYPE_GID_T		ELF_T_WORD
125da0c48c4Sopenharmony_ci#endif
126da0c48c4Sopenharmony_ci#define PID_T			int32_t
127da0c48c4Sopenharmony_ci#define ALIGN_PID_T		4
128da0c48c4Sopenharmony_ci#define TYPE_PID_T		ELF_T_SWORD
129da0c48c4Sopenharmony_ci/* s390 psw_compat_t has alignment 8 bytes where it is inherited from.  */
130da0c48c4Sopenharmony_ci#define ALIGN_PR_REG		8
131da0c48c4Sopenharmony_ci
132da0c48c4Sopenharmony_ci#define PRSTATUS_REGSET_ITEMS					\
133da0c48c4Sopenharmony_ci  {								\
134da0c48c4Sopenharmony_ci    .name = "orig_r2", .type = TYPE_LONG, .format = 'd',	\
135da0c48c4Sopenharmony_ci    .offset = offsetof (struct EBLHOOK(prstatus),		\
136da0c48c4Sopenharmony_ci			pr_reg[BITS == 32 ? 34 : 26]),		\
137da0c48c4Sopenharmony_ci    .group = "register"						\
138da0c48c4Sopenharmony_ci  }
139da0c48c4Sopenharmony_ci
140da0c48c4Sopenharmony_ci#if BITS == 32
141da0c48c4Sopenharmony_ci
142da0c48c4Sopenharmony_cistatic const Ebl_Core_Item high_regs_items[] =
143da0c48c4Sopenharmony_ci  {
144da0c48c4Sopenharmony_ci#define HR(n)								\
145da0c48c4Sopenharmony_ci    {									\
146da0c48c4Sopenharmony_ci      .name = "high_r" #n , .group = "register", .offset = (n) * 4,	\
147da0c48c4Sopenharmony_ci      .type = ELF_T_WORD, .format = 'x',				\
148da0c48c4Sopenharmony_ci    }
149da0c48c4Sopenharmony_ci
150da0c48c4Sopenharmony_ci    /* Upper halves of r0-r15 are stored here.
151da0c48c4Sopenharmony_ci       FIXME: They are currently not combined with the r0-r15 lower halves.  */
152da0c48c4Sopenharmony_ci    HR (0), HR (1), HR (2), HR (3), HR (4), HR (5), HR (6), HR (7),
153da0c48c4Sopenharmony_ci    HR (8), HR (9), HR (10), HR (11), HR (12), HR (13), HR (14), HR (15)
154da0c48c4Sopenharmony_ci
155da0c48c4Sopenharmony_ci#undef HR
156da0c48c4Sopenharmony_ci  };
157da0c48c4Sopenharmony_ci
158da0c48c4Sopenharmony_ci#define EXTRA_NOTES_HIGH_GPRS \
159da0c48c4Sopenharmony_ci  EXTRA_ITEMS (NT_S390_HIGH_GPRS, 16 * 4, high_regs_items)
160da0c48c4Sopenharmony_ci
161da0c48c4Sopenharmony_ci#else /* BITS == 64 */
162da0c48c4Sopenharmony_ci
163da0c48c4Sopenharmony_ci#define EXTRA_NOTES_HIGH_GPRS
164da0c48c4Sopenharmony_ci
165da0c48c4Sopenharmony_ci#endif /* BITS == 64 */
166da0c48c4Sopenharmony_ci
167da0c48c4Sopenharmony_cistatic const Ebl_Core_Item last_break_items[] =
168da0c48c4Sopenharmony_ci  {
169da0c48c4Sopenharmony_ci    {
170da0c48c4Sopenharmony_ci      .name = "last_break", .group = "system", .offset = BITS == 32 ? 4 : 0,
171da0c48c4Sopenharmony_ci      .type = BITS == 32 ? ELF_T_WORD : ELF_T_XWORD, .format = 'x',
172da0c48c4Sopenharmony_ci    },
173da0c48c4Sopenharmony_ci  };
174da0c48c4Sopenharmony_ci
175da0c48c4Sopenharmony_cistatic const Ebl_Core_Item system_call_items[] =
176da0c48c4Sopenharmony_ci  {
177da0c48c4Sopenharmony_ci    {
178da0c48c4Sopenharmony_ci      .name = "system_call", .group = "system", .offset = 0, .type = ELF_T_WORD,
179da0c48c4Sopenharmony_ci      .format = 'd',
180da0c48c4Sopenharmony_ci    },
181da0c48c4Sopenharmony_ci  };
182da0c48c4Sopenharmony_ci
183da0c48c4Sopenharmony_ci#define	EXTRA_NOTES							  \
184da0c48c4Sopenharmony_ci  EXTRA_NOTES_FPREGSET							  \
185da0c48c4Sopenharmony_ci  EXTRA_NOTES_HIGH_GPRS							  \
186da0c48c4Sopenharmony_ci  EXTRA_ITEMS (NT_S390_LAST_BREAK, 8, last_break_items)	  \
187da0c48c4Sopenharmony_ci  EXTRA_ITEMS (NT_S390_SYSTEM_CALL, 4, system_call_items)
188da0c48c4Sopenharmony_ci
189da0c48c4Sopenharmony_ci#include "linux-core-note.c"
190