Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Disassemble s390 instructions.
  4 *
  5 * Copyright IBM Corp. 2007
  6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  7 */
  8
  9#include <linux/sched.h>
 10#include <linux/kernel.h>
 11#include <linux/string.h>
 12#include <linux/errno.h>
 13#include <linux/ptrace.h>
 14#include <linux/timer.h>
 15#include <linux/mm.h>
 16#include <linux/smp.h>
 17#include <linux/init.h>
 18#include <linux/interrupt.h>
 19#include <linux/delay.h>
 20#include <linux/export.h>
 21#include <linux/kallsyms.h>
 22#include <linux/reboot.h>
 23#include <linux/kprobes.h>
 24#include <linux/kdebug.h>
 25#include <linux/uaccess.h>
 26#include <linux/atomic.h>
 
 27#include <asm/dis.h>
 28#include <asm/io.h>
 29#include <asm/cpcmd.h>
 30#include <asm/lowcore.h>
 31#include <asm/debug.h>
 32#include <asm/irq.h>
 33
 34/* Type of operand */
 35#define OPERAND_GPR	0x1	/* Operand printed as %rx */
 36#define OPERAND_FPR	0x2	/* Operand printed as %fx */
 37#define OPERAND_AR	0x4	/* Operand printed as %ax */
 38#define OPERAND_CR	0x8	/* Operand printed as %cx */
 39#define OPERAND_VR	0x10	/* Operand printed as %vx */
 40#define OPERAND_DISP	0x20	/* Operand printed as displacement */
 41#define OPERAND_BASE	0x40	/* Operand printed as base register */
 42#define OPERAND_INDEX	0x80	/* Operand printed as index register */
 43#define OPERAND_PCREL	0x100	/* Operand printed as pc-relative symbol */
 44#define OPERAND_SIGNED	0x200	/* Operand printed as signed value */
 45#define OPERAND_LENGTH	0x400	/* Operand printed as length (+1) */
 46
 47struct s390_operand {
 48	unsigned char bits;	/* The number of bits in the operand. */
 49	unsigned char shift;	/* The number of bits to shift. */
 50	unsigned short flags;	/* One bit syntax flags. */
 51};
 52
 53struct s390_insn {
 54	union {
 55		const char name[5];
 56		struct {
 57			unsigned char zero;
 58			unsigned int offset;
 59		} __packed;
 60	};
 61	unsigned char opfrag;
 62	unsigned char format;
 63};
 64
 65struct s390_opcode_offset {
 66	unsigned char opcode;
 67	unsigned char mask;
 68	unsigned char byte;
 69	unsigned short offset;
 70	unsigned short count;
 71} __packed;
 72
 73enum {
 74	UNUSED,
 75	A_8,	/* Access reg. starting at position 8 */
 76	A_12,	/* Access reg. starting at position 12 */
 77	A_24,	/* Access reg. starting at position 24 */
 78	A_28,	/* Access reg. starting at position 28 */
 79	B_16,	/* Base register starting at position 16 */
 80	B_32,	/* Base register starting at position 32 */
 81	C_8,	/* Control reg. starting at position 8 */
 82	C_12,	/* Control reg. starting at position 12 */
 83	D20_20, /* 20 bit displacement starting at 20 */
 84	D_20,	/* Displacement starting at position 20 */
 85	D_36,	/* Displacement starting at position 36 */
 86	F_8,	/* FPR starting at position 8 */
 87	F_12,	/* FPR starting at position 12 */
 88	F_16,	/* FPR starting at position 16 */
 89	F_24,	/* FPR starting at position 24 */
 90	F_28,	/* FPR starting at position 28 */
 91	F_32,	/* FPR starting at position 32 */
 92	I8_8,	/* 8 bit signed value starting at 8 */
 93	I8_32,	/* 8 bit signed value starting at 32 */
 94	I16_16, /* 16 bit signed value starting at 16 */
 95	I16_32, /* 16 bit signed value starting at 32 */
 96	I32_16, /* 32 bit signed value starting at 16 */
 97	J12_12, /* 12 bit PC relative offset at 12 */
 98	J16_16, /* 16 bit PC relative offset at 16 */
 99	J16_32, /* 16 bit PC relative offset at 32 */
100	J24_24, /* 24 bit PC relative offset at 24 */
101	J32_16, /* 32 bit PC relative offset at 16 */
102	L4_8,	/* 4 bit length starting at position 8 */
103	L4_12,	/* 4 bit length starting at position 12 */
104	L8_8,	/* 8 bit length starting at position 8 */
105	R_8,	/* GPR starting at position 8 */
106	R_12,	/* GPR starting at position 12 */
107	R_16,	/* GPR starting at position 16 */
108	R_24,	/* GPR starting at position 24 */
109	R_28,	/* GPR starting at position 28 */
110	U4_8,	/* 4 bit unsigned value starting at 8 */
111	U4_12,	/* 4 bit unsigned value starting at 12 */
112	U4_16,	/* 4 bit unsigned value starting at 16 */
113	U4_20,	/* 4 bit unsigned value starting at 20 */
114	U4_24,	/* 4 bit unsigned value starting at 24 */
115	U4_28,	/* 4 bit unsigned value starting at 28 */
116	U4_32,	/* 4 bit unsigned value starting at 32 */
117	U4_36,	/* 4 bit unsigned value starting at 36 */
118	U8_8,	/* 8 bit unsigned value starting at 8 */
119	U8_16,	/* 8 bit unsigned value starting at 16 */
120	U8_24,	/* 8 bit unsigned value starting at 24 */
121	U8_28,	/* 8 bit unsigned value starting at 28 */
122	U8_32,	/* 8 bit unsigned value starting at 32 */
123	U12_16, /* 12 bit unsigned value starting at 16 */
124	U16_16, /* 16 bit unsigned value starting at 16 */
 
125	U16_32, /* 16 bit unsigned value starting at 32 */
126	U32_16, /* 32 bit unsigned value starting at 16 */
127	VX_12,	/* Vector index register starting at position 12 */
128	V_8,	/* Vector reg. starting at position 8 */
129	V_12,	/* Vector reg. starting at position 12 */
130	V_16,	/* Vector reg. starting at position 16 */
131	V_32,	/* Vector reg. starting at position 32 */
132	X_12,	/* Index register starting at position 12 */
133};
134
135static const struct s390_operand operands[] = {
136	[UNUSED] = {  0,  0, 0 },
137	[A_8]	 = {  4,  8, OPERAND_AR },
138	[A_12]	 = {  4, 12, OPERAND_AR },
139	[A_24]	 = {  4, 24, OPERAND_AR },
140	[A_28]	 = {  4, 28, OPERAND_AR },
141	[B_16]	 = {  4, 16, OPERAND_BASE | OPERAND_GPR },
142	[B_32]	 = {  4, 32, OPERAND_BASE | OPERAND_GPR },
143	[C_8]	 = {  4,  8, OPERAND_CR },
144	[C_12]	 = {  4, 12, OPERAND_CR },
145	[D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED },
146	[D_20]	 = { 12, 20, OPERAND_DISP },
147	[D_36]	 = { 12, 36, OPERAND_DISP },
148	[F_8]	 = {  4,  8, OPERAND_FPR },
149	[F_12]	 = {  4, 12, OPERAND_FPR },
150	[F_16]	 = {  4, 16, OPERAND_FPR },
151	[F_24]	 = {  4, 24, OPERAND_FPR },
152	[F_28]	 = {  4, 28, OPERAND_FPR },
153	[F_32]	 = {  4, 32, OPERAND_FPR },
154	[I8_8]	 = {  8,  8, OPERAND_SIGNED },
155	[I8_32]	 = {  8, 32, OPERAND_SIGNED },
156	[I16_16] = { 16, 16, OPERAND_SIGNED },
157	[I16_32] = { 16, 32, OPERAND_SIGNED },
158	[I32_16] = { 32, 16, OPERAND_SIGNED },
159	[J12_12] = { 12, 12, OPERAND_PCREL },
160	[J16_16] = { 16, 16, OPERAND_PCREL },
161	[J16_32] = { 16, 32, OPERAND_PCREL },
162	[J24_24] = { 24, 24, OPERAND_PCREL },
163	[J32_16] = { 32, 16, OPERAND_PCREL },
164	[L4_8]	 = {  4,  8, OPERAND_LENGTH },
165	[L4_12]	 = {  4, 12, OPERAND_LENGTH },
166	[L8_8]	 = {  8,  8, OPERAND_LENGTH },
167	[R_8]	 = {  4,  8, OPERAND_GPR },
168	[R_12]	 = {  4, 12, OPERAND_GPR },
169	[R_16]	 = {  4, 16, OPERAND_GPR },
170	[R_24]	 = {  4, 24, OPERAND_GPR },
171	[R_28]	 = {  4, 28, OPERAND_GPR },
172	[U4_8]	 = {  4,  8, 0 },
173	[U4_12]	 = {  4, 12, 0 },
174	[U4_16]	 = {  4, 16, 0 },
175	[U4_20]	 = {  4, 20, 0 },
176	[U4_24]	 = {  4, 24, 0 },
177	[U4_28]	 = {  4, 28, 0 },
178	[U4_32]	 = {  4, 32, 0 },
179	[U4_36]	 = {  4, 36, 0 },
180	[U8_8]	 = {  8,  8, 0 },
181	[U8_16]	 = {  8, 16, 0 },
182	[U8_24]	 = {  8, 24, 0 },
183	[U8_28]	 = {  8, 28, 0 },
184	[U8_32]	 = {  8, 32, 0 },
185	[U12_16] = { 12, 16, 0 },
186	[U16_16] = { 16, 16, 0 },
 
187	[U16_32] = { 16, 32, 0 },
188	[U32_16] = { 32, 16, 0 },
189	[VX_12]	 = {  4, 12, OPERAND_INDEX | OPERAND_VR },
190	[V_8]	 = {  4,  8, OPERAND_VR },
191	[V_12]	 = {  4, 12, OPERAND_VR },
192	[V_16]	 = {  4, 16, OPERAND_VR },
193	[V_32]	 = {  4, 32, OPERAND_VR },
194	[X_12]	 = {  4, 12, OPERAND_INDEX | OPERAND_GPR },
195};
196
197static const unsigned char formats[][6] = {
198	[INSTR_E]	     = { 0, 0, 0, 0, 0, 0 },
199	[INSTR_IE_UU]	     = { U4_24, U4_28, 0, 0, 0, 0 },
200	[INSTR_MII_UPP]	     = { U4_8, J12_12, J24_24 },
201	[INSTR_RIE_R0IU]     = { R_8, I16_16, U4_32, 0, 0, 0 },
202	[INSTR_RIE_R0UU]     = { R_8, U16_16, U4_32, 0, 0, 0 },
203	[INSTR_RIE_RRI0]     = { R_8, R_12, I16_16, 0, 0, 0 },
204	[INSTR_RIE_RRP]	     = { R_8, R_12, J16_16, 0, 0, 0 },
205	[INSTR_RIE_RRPU]     = { R_8, R_12, U4_32, J16_16, 0, 0 },
206	[INSTR_RIE_RRUUU]    = { R_8, R_12, U8_16, U8_24, U8_32, 0 },
207	[INSTR_RIE_RUI0]     = { R_8, I16_16, U4_12, 0, 0, 0 },
208	[INSTR_RIE_RUPI]     = { R_8, I8_32, U4_12, J16_16, 0, 0 },
209	[INSTR_RIE_RUPU]     = { R_8, U8_32, U4_12, J16_16, 0, 0 },
210	[INSTR_RIL_RI]	     = { R_8, I32_16, 0, 0, 0, 0 },
211	[INSTR_RIL_RP]	     = { R_8, J32_16, 0, 0, 0, 0 },
212	[INSTR_RIL_RU]	     = { R_8, U32_16, 0, 0, 0, 0 },
213	[INSTR_RIL_UP]	     = { U4_8, J32_16, 0, 0, 0, 0 },
214	[INSTR_RIS_RURDI]    = { R_8, I8_32, U4_12, D_20, B_16, 0 },
215	[INSTR_RIS_RURDU]    = { R_8, U8_32, U4_12, D_20, B_16, 0 },
216	[INSTR_RI_RI]	     = { R_8, I16_16, 0, 0, 0, 0 },
217	[INSTR_RI_RP]	     = { R_8, J16_16, 0, 0, 0, 0 },
218	[INSTR_RI_RU]	     = { R_8, U16_16, 0, 0, 0, 0 },
219	[INSTR_RI_UP]	     = { U4_8, J16_16, 0, 0, 0, 0 },
220	[INSTR_RRE_00]	     = { 0, 0, 0, 0, 0, 0 },
221	[INSTR_RRE_AA]	     = { A_24, A_28, 0, 0, 0, 0 },
222	[INSTR_RRE_AR]	     = { A_24, R_28, 0, 0, 0, 0 },
223	[INSTR_RRE_F0]	     = { F_24, 0, 0, 0, 0, 0 },
224	[INSTR_RRE_FF]	     = { F_24, F_28, 0, 0, 0, 0 },
225	[INSTR_RRE_FR]	     = { F_24, R_28, 0, 0, 0, 0 },
226	[INSTR_RRE_R0]	     = { R_24, 0, 0, 0, 0, 0 },
227	[INSTR_RRE_RA]	     = { R_24, A_28, 0, 0, 0, 0 },
228	[INSTR_RRE_RF]	     = { R_24, F_28, 0, 0, 0, 0 },
229	[INSTR_RRE_RR]	     = { R_24, R_28, 0, 0, 0, 0 },
230	[INSTR_RRF_0UFF]     = { F_24, F_28, U4_20, 0, 0, 0 },
231	[INSTR_RRF_0URF]     = { R_24, F_28, U4_20, 0, 0, 0 },
232	[INSTR_RRF_F0FF]     = { F_16, F_24, F_28, 0, 0, 0 },
233	[INSTR_RRF_F0FF2]    = { F_24, F_16, F_28, 0, 0, 0 },
234	[INSTR_RRF_F0FR]     = { F_24, F_16, R_28, 0, 0, 0 },
235	[INSTR_RRF_FFRU]     = { F_24, F_16, R_28, U4_20, 0, 0 },
236	[INSTR_RRF_FUFF]     = { F_24, F_16, F_28, U4_20, 0, 0 },
237	[INSTR_RRF_FUFF2]    = { F_24, F_28, F_16, U4_20, 0, 0 },
238	[INSTR_RRF_R0RR]     = { R_24, R_16, R_28, 0, 0, 0 },
239	[INSTR_RRF_R0RR2]    = { R_24, R_28, R_16, 0, 0, 0 },
240	[INSTR_RRF_RURR]     = { R_24, R_28, R_16, U4_20, 0, 0 },
241	[INSTR_RRF_RURR2]    = { R_24, R_16, R_28, U4_20, 0, 0 },
242	[INSTR_RRF_U0FF]     = { F_24, U4_16, F_28, 0, 0, 0 },
243	[INSTR_RRF_U0RF]     = { R_24, U4_16, F_28, 0, 0, 0 },
244	[INSTR_RRF_U0RR]     = { R_24, R_28, U4_16, 0, 0, 0 },
245	[INSTR_RRF_URR]	     = { R_24, R_28, U8_16, 0, 0, 0 },
246	[INSTR_RRF_UUFF]     = { F_24, U4_16, F_28, U4_20, 0, 0 },
247	[INSTR_RRF_UUFR]     = { F_24, U4_16, R_28, U4_20, 0, 0 },
248	[INSTR_RRF_UURF]     = { R_24, U4_16, F_28, U4_20, 0, 0 },
249	[INSTR_RRS_RRRDU]    = { R_8, R_12, U4_32, D_20, B_16 },
250	[INSTR_RR_FF]	     = { F_8, F_12, 0, 0, 0, 0 },
251	[INSTR_RR_R0]	     = { R_8,  0, 0, 0, 0, 0 },
252	[INSTR_RR_RR]	     = { R_8, R_12, 0, 0, 0, 0 },
253	[INSTR_RR_U0]	     = { U8_8,	0, 0, 0, 0, 0 },
254	[INSTR_RR_UR]	     = { U4_8, R_12, 0, 0, 0, 0 },
255	[INSTR_RSI_RRP]	     = { R_8, R_12, J16_16, 0, 0, 0 },
256	[INSTR_RSL_LRDFU]    = { F_32, D_20, L8_8, B_16, U4_36, 0 },
257	[INSTR_RSL_R0RD]     = { D_20, L4_8, B_16, 0, 0, 0 },
258	[INSTR_RSY_AARD]     = { A_8, A_12, D20_20, B_16, 0, 0 },
259	[INSTR_RSY_CCRD]     = { C_8, C_12, D20_20, B_16, 0, 0 },
260	[INSTR_RSY_RDRU]     = { R_8, D20_20, B_16, U4_12, 0, 0 },
261	[INSTR_RSY_RRRD]     = { R_8, R_12, D20_20, B_16, 0, 0 },
262	[INSTR_RSY_RURD]     = { R_8, U4_12, D20_20, B_16, 0, 0 },
263	[INSTR_RSY_RURD2]    = { R_8, D20_20, B_16, U4_12, 0, 0 },
264	[INSTR_RS_AARD]	     = { A_8, A_12, D_20, B_16, 0, 0 },
265	[INSTR_RS_CCRD]	     = { C_8, C_12, D_20, B_16, 0, 0 },
266	[INSTR_RS_R0RD]	     = { R_8, D_20, B_16, 0, 0, 0 },
267	[INSTR_RS_RRRD]	     = { R_8, R_12, D_20, B_16, 0, 0 },
268	[INSTR_RS_RURD]	     = { R_8, U4_12, D_20, B_16, 0, 0 },
269	[INSTR_RXE_FRRD]     = { F_8, D_20, X_12, B_16, 0, 0 },
270	[INSTR_RXE_RRRDU]    = { R_8, D_20, X_12, B_16, U4_32, 0 },
271	[INSTR_RXF_FRRDF]    = { F_32, F_8, D_20, X_12, B_16, 0 },
272	[INSTR_RXY_FRRD]     = { F_8, D20_20, X_12, B_16, 0, 0 },
273	[INSTR_RXY_RRRD]     = { R_8, D20_20, X_12, B_16, 0, 0 },
274	[INSTR_RXY_URRD]     = { U4_8, D20_20, X_12, B_16, 0, 0 },
275	[INSTR_RX_FRRD]	     = { F_8, D_20, X_12, B_16, 0, 0 },
276	[INSTR_RX_RRRD]	     = { R_8, D_20, X_12, B_16, 0, 0 },
277	[INSTR_RX_URRD]	     = { U4_8, D_20, X_12, B_16, 0, 0 },
278	[INSTR_SIL_RDI]	     = { D_20, B_16, I16_32, 0, 0, 0 },
279	[INSTR_SIL_RDU]	     = { D_20, B_16, U16_32, 0, 0, 0 },
280	[INSTR_SIY_IRD]	     = { D20_20, B_16, I8_8, 0, 0, 0 },
 
281	[INSTR_SIY_URD]	     = { D20_20, B_16, U8_8, 0, 0, 0 },
282	[INSTR_SI_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
283	[INSTR_SI_URD]	     = { D_20, B_16, U8_8, 0, 0, 0 },
284	[INSTR_SMI_U0RDP]    = { U4_8, J16_32, D_20, B_16, 0, 0 },
285	[INSTR_SSE_RDRD]     = { D_20, B_16, D_36, B_32, 0, 0 },
286	[INSTR_SSF_RRDRD]    = { D_20, B_16, D_36, B_32, R_8, 0 },
287	[INSTR_SSF_RRDRD2]   = { R_8, D_20, B_16, D_36, B_32, 0 },
288	[INSTR_SS_L0RDRD]    = { D_20, L8_8, B_16, D_36, B_32, 0 },
289	[INSTR_SS_L2RDRD]    = { D_20, B_16, D_36, L8_8, B_32, 0 },
290	[INSTR_SS_LIRDRD]    = { D_20, L4_8, B_16, D_36, B_32, U4_12 },
291	[INSTR_SS_LLRDRD]    = { D_20, L4_8, B_16, D_36, L4_12, B_32 },
292	[INSTR_SS_RRRDRD]    = { D_20, R_8, B_16, D_36, B_32, R_12 },
293	[INSTR_SS_RRRDRD2]   = { R_8, D_20, B_16, R_12, D_36, B_32 },
294	[INSTR_SS_RRRDRD3]   = { R_8, R_12, D_20, B_16, D_36, B_32 },
295	[INSTR_S_00]	     = { 0, 0, 0, 0, 0, 0 },
296	[INSTR_S_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
297	[INSTR_VRI_V0IU]     = { V_8, I16_16, U4_32, 0, 0, 0 },
298	[INSTR_VRI_V0U]	     = { V_8, U16_16, 0, 0, 0, 0 },
299	[INSTR_VRI_V0UU2]    = { V_8, U16_16, U4_32, 0, 0, 0 },
300	[INSTR_VRI_V0UUU]    = { V_8, U8_16, U8_24, U4_32, 0, 0 },
301	[INSTR_VRI_VR0UU]    = { V_8, R_12, U8_28, U4_24, 0, 0 },
 
302	[INSTR_VRI_VVUU]     = { V_8, V_12, U16_16, U4_32, 0, 0 },
303	[INSTR_VRI_VVUUU]    = { V_8, V_12, U12_16, U4_32, U4_28, 0 },
304	[INSTR_VRI_VVUUU2]   = { V_8, V_12, U8_28, U8_16, U4_24, 0 },
305	[INSTR_VRI_VVV0U]    = { V_8, V_12, V_16, U8_24, 0, 0 },
306	[INSTR_VRI_VVV0UU]   = { V_8, V_12, V_16, U8_24, U4_32, 0 },
307	[INSTR_VRI_VVV0UU2]  = { V_8, V_12, V_16, U8_28, U4_24, 0 },
308	[INSTR_VRR_0V]	     = { V_12, 0, 0, 0, 0, 0 },
 
309	[INSTR_VRR_0VV0U]    = { V_12, V_16, U4_24, 0, 0, 0 },
 
310	[INSTR_VRR_RV0UU]    = { R_8, V_12, U4_24, U4_28, 0, 0 },
311	[INSTR_VRR_VRR]	     = { V_8, R_12, R_16, 0, 0, 0 },
312	[INSTR_VRR_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
313	[INSTR_VRR_VV0U]     = { V_8, V_12, U4_32, 0, 0, 0 },
314	[INSTR_VRR_VV0U0U]   = { V_8, V_12, U4_32, U4_24, 0, 0 },
 
315	[INSTR_VRR_VV0UU2]   = { V_8, V_12, U4_32, U4_28, 0, 0 },
316	[INSTR_VRR_VV0UUU]   = { V_8, V_12, U4_32, U4_28, U4_24, 0 },
317	[INSTR_VRR_VVV]	     = { V_8, V_12, V_16, 0, 0, 0 },
318	[INSTR_VRR_VVV0U]    = { V_8, V_12, V_16, U4_32, 0, 0 },
 
319	[INSTR_VRR_VVV0U0U]  = { V_8, V_12, V_16, U4_32, U4_24, 0 },
320	[INSTR_VRR_VVV0UU]   = { V_8, V_12, V_16, U4_32, U4_28, 0 },
321	[INSTR_VRR_VVV0UUU]  = { V_8, V_12, V_16, U4_32, U4_28, U4_24 },
322	[INSTR_VRR_VVV0V]    = { V_8, V_12, V_16, V_32, 0, 0 },
323	[INSTR_VRR_VVVU0UV]  = { V_8, V_12, V_16, V_32, U4_28, U4_20 },
324	[INSTR_VRR_VVVU0V]   = { V_8, V_12, V_16, V_32, U4_20, 0 },
325	[INSTR_VRR_VVVUU0V]  = { V_8, V_12, V_16, V_32, U4_20, U4_24 },
326	[INSTR_VRS_RRDV]     = { V_32, R_12, D_20, B_16, 0, 0 },
327	[INSTR_VRS_RVRDU]    = { R_8, V_12, D_20, B_16, U4_32, 0 },
328	[INSTR_VRS_VRRD]     = { V_8, R_12, D_20, B_16, 0, 0 },
329	[INSTR_VRS_VRRDU]    = { V_8, R_12, D_20, B_16, U4_32, 0 },
330	[INSTR_VRS_VVRDU]    = { V_8, V_12, D_20, B_16, U4_32, 0 },
331	[INSTR_VRV_VVXRDU]   = { V_8, D_20, VX_12, B_16, U4_32, 0 },
332	[INSTR_VRX_VRRDU]    = { V_8, D_20, X_12, B_16, U4_32, 0 },
333	[INSTR_VRX_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
334	[INSTR_VSI_URDV]     = { V_32, D_20, B_16, U8_8, 0, 0 },
335};
336
337static char long_insn_name[][7] = LONG_INSN_INITIALIZER;
338static struct s390_insn opcode[] = OPCODE_TABLE_INITIALIZER;
339static struct s390_opcode_offset opcode_offset[] = OPCODE_OFFSET_INITIALIZER;
340
341/* Extracts an operand value from an instruction.  */
342static unsigned int extract_operand(unsigned char *code,
343				    const struct s390_operand *operand)
344{
345	unsigned char *cp;
346	unsigned int val;
347	int bits;
348
349	/* Extract fragments of the operand byte for byte.  */
350	cp = code + operand->shift / 8;
351	bits = (operand->shift & 7) + operand->bits;
352	val = 0;
353	do {
354		val <<= 8;
355		val |= (unsigned int) *cp++;
356		bits -= 8;
357	} while (bits > 0);
358	val >>= -bits;
359	val &= ((1U << (operand->bits - 1)) << 1) - 1;
360
361	/* Check for special long displacement case.  */
362	if (operand->bits == 20 && operand->shift == 20)
363		val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
364
365	/* Check for register extensions bits for vector registers. */
366	if (operand->flags & OPERAND_VR) {
367		if (operand->shift == 8)
368			val |= (code[4] & 8) << 1;
369		else if (operand->shift == 12)
370			val |= (code[4] & 4) << 2;
371		else if (operand->shift == 16)
372			val |= (code[4] & 2) << 3;
373		else if (operand->shift == 32)
374			val |= (code[4] & 1) << 4;
375	}
376
377	/* Sign extend value if the operand is signed or pc relative.  */
378	if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
379	    (val & (1U << (operand->bits - 1))))
380		val |= (-1U << (operand->bits - 1)) << 1;
381
382	/* Double value if the operand is pc relative.	*/
383	if (operand->flags & OPERAND_PCREL)
384		val <<= 1;
385
386	/* Length x in an instructions has real length x + 1.  */
387	if (operand->flags & OPERAND_LENGTH)
388		val++;
389	return val;
390}
391
392struct s390_insn *find_insn(unsigned char *code)
393{
394	struct s390_opcode_offset *entry;
395	struct s390_insn *insn;
396	unsigned char opfrag;
397	int i;
398
399	/* Search the opcode offset table to find an entry which
400	 * matches the beginning of the opcode. If there is no match
401	 * the last entry will be used, which is the default entry for
402	 * unknown instructions as well as 1-byte opcode instructions.
403	 */
404	for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
405		entry = &opcode_offset[i];
406		if (entry->opcode == code[0])
407			break;
408	}
409
410	opfrag = *(code + entry->byte) & entry->mask;
411
412	insn = &opcode[entry->offset];
413	for (i = 0; i < entry->count; i++) {
414		if (insn->opfrag == opfrag)
415			return insn;
416		insn++;
417	}
418	return NULL;
419}
420
421static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
422{
423	struct s390_insn *insn;
424	const unsigned char *ops;
425	const struct s390_operand *operand;
426	unsigned int value;
427	char separator;
428	char *ptr;
429	int i;
430
431	ptr = buffer;
432	insn = find_insn(code);
433	if (insn) {
434		if (insn->zero == 0)
435			ptr += sprintf(ptr, "%.7s\t",
436				       long_insn_name[insn->offset]);
437		else
438			ptr += sprintf(ptr, "%.5s\t", insn->name);
439		/* Extract the operands. */
440		separator = 0;
441		for (ops = formats[insn->format], i = 0;
442		     *ops != 0 && i < 6; ops++, i++) {
443			operand = operands + *ops;
444			value = extract_operand(code, operand);
445			if ((operand->flags & OPERAND_INDEX)  && value == 0)
446				continue;
447			if ((operand->flags & OPERAND_BASE) &&
448			    value == 0 && separator == '(') {
449				separator = ',';
450				continue;
451			}
452			if (separator)
453				ptr += sprintf(ptr, "%c", separator);
454			if (operand->flags & OPERAND_GPR)
455				ptr += sprintf(ptr, "%%r%i", value);
456			else if (operand->flags & OPERAND_FPR)
457				ptr += sprintf(ptr, "%%f%i", value);
458			else if (operand->flags & OPERAND_AR)
459				ptr += sprintf(ptr, "%%a%i", value);
460			else if (operand->flags & OPERAND_CR)
461				ptr += sprintf(ptr, "%%c%i", value);
462			else if (operand->flags & OPERAND_VR)
463				ptr += sprintf(ptr, "%%v%i", value);
464			else if (operand->flags & OPERAND_PCREL)
465				ptr += sprintf(ptr, "%lx", (signed int) value
466								      + addr);
467			else if (operand->flags & OPERAND_SIGNED)
468				ptr += sprintf(ptr, "%i", value);
 
469			else
470				ptr += sprintf(ptr, "%u", value);
471			if (operand->flags & OPERAND_DISP)
472				separator = '(';
473			else if (operand->flags & OPERAND_BASE) {
474				ptr += sprintf(ptr, ")");
475				separator = ',';
476			} else
477				separator = ',';
478		}
479	} else
480		ptr += sprintf(ptr, "unknown");
481	return (int) (ptr - buffer);
482}
483
 
 
 
 
 
 
 
 
 
 
 
 
484void show_code(struct pt_regs *regs)
485{
486	char *mode = user_mode(regs) ? "User" : "Krnl";
487	unsigned char code[64];
488	char buffer[128], *ptr;
489	mm_segment_t old_fs;
490	unsigned long addr;
491	int start, end, opsize, hops, i;
492
493	/* Get a snapshot of the 64 bytes surrounding the fault address. */
494	old_fs = get_fs();
495	set_fs(user_mode(regs) ? USER_DS : KERNEL_DS);
496	for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
497		addr = regs->psw.addr - 34 + start;
498		if (__copy_from_user(code + start - 2,
499				     (char __user *) addr, 2))
500			break;
501	}
502	for (end = 32; end < 64; end += 2) {
503		addr = regs->psw.addr + end - 32;
504		if (__copy_from_user(code + end,
505				     (char __user *) addr, 2))
506			break;
507	}
508	set_fs(old_fs);
509	/* Code snapshot useable ? */
510	if ((regs->psw.addr & 1) || start >= end) {
511		printk("%s Code: Bad PSW.\n", mode);
512		return;
513	}
514	/* Find a starting point for the disassembly. */
515	while (start < 32) {
516		for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
517			if (!find_insn(code + start + i))
518				break;
519			i += insn_length(code[start + i]);
520		}
521		if (start + i == 32)
522			/* Looks good, sequence ends at PSW. */
523			break;
524		start += 2;
525	}
526	/* Decode the instructions. */
527	ptr = buffer;
528	ptr += sprintf(ptr, "%s Code:", mode);
529	hops = 0;
530	while (start < end && hops < 8) {
531		opsize = insn_length(code[start]);
532		if  (start + opsize == 32)
533			*ptr++ = '#';
534		else if (start == 32)
535			*ptr++ = '>';
536		else
537			*ptr++ = ' ';
538		addr = regs->psw.addr + start - 32;
539		ptr += sprintf(ptr, "%016lx: ", addr);
540		if (start + opsize >= end)
541			break;
542		for (i = 0; i < opsize; i++)
543			ptr += sprintf(ptr, "%02x", code[start + i]);
544		*ptr++ = '\t';
545		if (i < 6)
546			*ptr++ = '\t';
547		ptr += print_insn(ptr, code + start, addr);
548		start += opsize;
549		pr_cont("%s", buffer);
550		ptr = buffer;
551		ptr += sprintf(ptr, "\n          ");
552		hops++;
553	}
554	pr_cont("\n");
555}
556
557void print_fn_code(unsigned char *code, unsigned long len)
558{
559	char buffer[64], *ptr;
560	int opsize, i;
561
562	while (len) {
563		ptr = buffer;
564		opsize = insn_length(*code);
565		if (opsize > len)
566			break;
567		ptr += sprintf(ptr, "%p: ", code);
568		for (i = 0; i < opsize; i++)
569			ptr += sprintf(ptr, "%02x", code[i]);
570		*ptr++ = '\t';
571		if (i < 4)
572			*ptr++ = '\t';
573		ptr += print_insn(ptr, code, (unsigned long) code);
574		*ptr++ = '\n';
575		*ptr++ = 0;
576		printk("%s", buffer);
577		code += opsize;
578		len -= opsize;
579	}
580}
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Disassemble s390 instructions.
  4 *
  5 * Copyright IBM Corp. 2007
  6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  7 */
  8
  9#include <linux/sched.h>
 10#include <linux/kernel.h>
 11#include <linux/string.h>
 12#include <linux/errno.h>
 13#include <linux/ptrace.h>
 14#include <linux/timer.h>
 15#include <linux/mm.h>
 16#include <linux/smp.h>
 17#include <linux/init.h>
 18#include <linux/interrupt.h>
 19#include <linux/delay.h>
 20#include <linux/export.h>
 21#include <linux/kallsyms.h>
 22#include <linux/reboot.h>
 23#include <linux/kprobes.h>
 24#include <linux/kdebug.h>
 25#include <linux/uaccess.h>
 26#include <linux/atomic.h>
 27#include <linux/io.h>
 28#include <asm/dis.h>
 
 29#include <asm/cpcmd.h>
 30#include <asm/lowcore.h>
 31#include <asm/debug.h>
 32#include <asm/irq.h>
 33
 34/* Type of operand */
 35#define OPERAND_GPR	0x1	/* Operand printed as %rx */
 36#define OPERAND_FPR	0x2	/* Operand printed as %fx */
 37#define OPERAND_AR	0x4	/* Operand printed as %ax */
 38#define OPERAND_CR	0x8	/* Operand printed as %cx */
 39#define OPERAND_VR	0x10	/* Operand printed as %vx */
 40#define OPERAND_DISP	0x20	/* Operand printed as displacement */
 41#define OPERAND_BASE	0x40	/* Operand printed as base register */
 42#define OPERAND_INDEX	0x80	/* Operand printed as index register */
 43#define OPERAND_PCREL	0x100	/* Operand printed as pc-relative symbol */
 44#define OPERAND_SIGNED	0x200	/* Operand printed as signed value */
 45#define OPERAND_LENGTH	0x400	/* Operand printed as length (+1) */
 46
 47struct s390_operand {
 48	unsigned char bits;	/* The number of bits in the operand. */
 49	unsigned char shift;	/* The number of bits to shift. */
 50	unsigned short flags;	/* One bit syntax flags. */
 51};
 52
 53struct s390_insn {
 54	union {
 55		const char name[5];
 56		struct {
 57			unsigned char zero;
 58			unsigned int offset;
 59		} __packed;
 60	};
 61	unsigned char opfrag;
 62	unsigned char format;
 63};
 64
 65struct s390_opcode_offset {
 66	unsigned char opcode;
 67	unsigned char mask;
 68	unsigned char byte;
 69	unsigned short offset;
 70	unsigned short count;
 71} __packed;
 72
 73enum {
 74	UNUSED,
 75	A_8,	/* Access reg. starting at position 8 */
 76	A_12,	/* Access reg. starting at position 12 */
 77	A_24,	/* Access reg. starting at position 24 */
 78	A_28,	/* Access reg. starting at position 28 */
 79	B_16,	/* Base register starting at position 16 */
 80	B_32,	/* Base register starting at position 32 */
 81	C_8,	/* Control reg. starting at position 8 */
 82	C_12,	/* Control reg. starting at position 12 */
 83	D20_20, /* 20 bit displacement starting at 20 */
 84	D_20,	/* Displacement starting at position 20 */
 85	D_36,	/* Displacement starting at position 36 */
 86	F_8,	/* FPR starting at position 8 */
 87	F_12,	/* FPR starting at position 12 */
 88	F_16,	/* FPR starting at position 16 */
 89	F_24,	/* FPR starting at position 24 */
 90	F_28,	/* FPR starting at position 28 */
 91	F_32,	/* FPR starting at position 32 */
 92	I8_8,	/* 8 bit signed value starting at 8 */
 93	I8_32,	/* 8 bit signed value starting at 32 */
 94	I16_16, /* 16 bit signed value starting at 16 */
 95	I16_32, /* 16 bit signed value starting at 32 */
 96	I32_16, /* 32 bit signed value starting at 16 */
 97	J12_12, /* 12 bit PC relative offset at 12 */
 98	J16_16, /* 16 bit PC relative offset at 16 */
 99	J16_32, /* 16 bit PC relative offset at 32 */
100	J24_24, /* 24 bit PC relative offset at 24 */
101	J32_16, /* 32 bit PC relative offset at 16 */
102	L4_8,	/* 4 bit length starting at position 8 */
103	L4_12,	/* 4 bit length starting at position 12 */
104	L8_8,	/* 8 bit length starting at position 8 */
105	R_8,	/* GPR starting at position 8 */
106	R_12,	/* GPR starting at position 12 */
107	R_16,	/* GPR starting at position 16 */
108	R_24,	/* GPR starting at position 24 */
109	R_28,	/* GPR starting at position 28 */
110	U4_8,	/* 4 bit unsigned value starting at 8 */
111	U4_12,	/* 4 bit unsigned value starting at 12 */
112	U4_16,	/* 4 bit unsigned value starting at 16 */
113	U4_20,	/* 4 bit unsigned value starting at 20 */
114	U4_24,	/* 4 bit unsigned value starting at 24 */
115	U4_28,	/* 4 bit unsigned value starting at 28 */
116	U4_32,	/* 4 bit unsigned value starting at 32 */
117	U4_36,	/* 4 bit unsigned value starting at 36 */
118	U8_8,	/* 8 bit unsigned value starting at 8 */
119	U8_16,	/* 8 bit unsigned value starting at 16 */
120	U8_24,	/* 8 bit unsigned value starting at 24 */
121	U8_28,	/* 8 bit unsigned value starting at 28 */
122	U8_32,	/* 8 bit unsigned value starting at 32 */
123	U12_16, /* 12 bit unsigned value starting at 16 */
124	U16_16, /* 16 bit unsigned value starting at 16 */
125	U16_20, /* 16 bit unsigned value starting at 20 */
126	U16_32, /* 16 bit unsigned value starting at 32 */
127	U32_16, /* 32 bit unsigned value starting at 16 */
128	VX_12,	/* Vector index register starting at position 12 */
129	V_8,	/* Vector reg. starting at position 8 */
130	V_12,	/* Vector reg. starting at position 12 */
131	V_16,	/* Vector reg. starting at position 16 */
132	V_32,	/* Vector reg. starting at position 32 */
133	X_12,	/* Index register starting at position 12 */
134};
135
136static const struct s390_operand operands[] = {
137	[UNUSED] = {  0,  0, 0 },
138	[A_8]	 = {  4,  8, OPERAND_AR },
139	[A_12]	 = {  4, 12, OPERAND_AR },
140	[A_24]	 = {  4, 24, OPERAND_AR },
141	[A_28]	 = {  4, 28, OPERAND_AR },
142	[B_16]	 = {  4, 16, OPERAND_BASE | OPERAND_GPR },
143	[B_32]	 = {  4, 32, OPERAND_BASE | OPERAND_GPR },
144	[C_8]	 = {  4,  8, OPERAND_CR },
145	[C_12]	 = {  4, 12, OPERAND_CR },
146	[D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED },
147	[D_20]	 = { 12, 20, OPERAND_DISP },
148	[D_36]	 = { 12, 36, OPERAND_DISP },
149	[F_8]	 = {  4,  8, OPERAND_FPR },
150	[F_12]	 = {  4, 12, OPERAND_FPR },
151	[F_16]	 = {  4, 16, OPERAND_FPR },
152	[F_24]	 = {  4, 24, OPERAND_FPR },
153	[F_28]	 = {  4, 28, OPERAND_FPR },
154	[F_32]	 = {  4, 32, OPERAND_FPR },
155	[I8_8]	 = {  8,  8, OPERAND_SIGNED },
156	[I8_32]	 = {  8, 32, OPERAND_SIGNED },
157	[I16_16] = { 16, 16, OPERAND_SIGNED },
158	[I16_32] = { 16, 32, OPERAND_SIGNED },
159	[I32_16] = { 32, 16, OPERAND_SIGNED },
160	[J12_12] = { 12, 12, OPERAND_PCREL },
161	[J16_16] = { 16, 16, OPERAND_PCREL },
162	[J16_32] = { 16, 32, OPERAND_PCREL },
163	[J24_24] = { 24, 24, OPERAND_PCREL },
164	[J32_16] = { 32, 16, OPERAND_PCREL },
165	[L4_8]	 = {  4,  8, OPERAND_LENGTH },
166	[L4_12]	 = {  4, 12, OPERAND_LENGTH },
167	[L8_8]	 = {  8,  8, OPERAND_LENGTH },
168	[R_8]	 = {  4,  8, OPERAND_GPR },
169	[R_12]	 = {  4, 12, OPERAND_GPR },
170	[R_16]	 = {  4, 16, OPERAND_GPR },
171	[R_24]	 = {  4, 24, OPERAND_GPR },
172	[R_28]	 = {  4, 28, OPERAND_GPR },
173	[U4_8]	 = {  4,  8, 0 },
174	[U4_12]	 = {  4, 12, 0 },
175	[U4_16]	 = {  4, 16, 0 },
176	[U4_20]	 = {  4, 20, 0 },
177	[U4_24]	 = {  4, 24, 0 },
178	[U4_28]	 = {  4, 28, 0 },
179	[U4_32]	 = {  4, 32, 0 },
180	[U4_36]	 = {  4, 36, 0 },
181	[U8_8]	 = {  8,  8, 0 },
182	[U8_16]	 = {  8, 16, 0 },
183	[U8_24]	 = {  8, 24, 0 },
184	[U8_28]	 = {  8, 28, 0 },
185	[U8_32]	 = {  8, 32, 0 },
186	[U12_16] = { 12, 16, 0 },
187	[U16_16] = { 16, 16, 0 },
188	[U16_20] = { 16, 20, 0 },
189	[U16_32] = { 16, 32, 0 },
190	[U32_16] = { 32, 16, 0 },
191	[VX_12]	 = {  4, 12, OPERAND_INDEX | OPERAND_VR },
192	[V_8]	 = {  4,  8, OPERAND_VR },
193	[V_12]	 = {  4, 12, OPERAND_VR },
194	[V_16]	 = {  4, 16, OPERAND_VR },
195	[V_32]	 = {  4, 32, OPERAND_VR },
196	[X_12]	 = {  4, 12, OPERAND_INDEX | OPERAND_GPR },
197};
198
199static const unsigned char formats[][6] = {
200	[INSTR_E]	     = { 0, 0, 0, 0, 0, 0 },
201	[INSTR_IE_UU]	     = { U4_24, U4_28, 0, 0, 0, 0 },
202	[INSTR_MII_UPP]	     = { U4_8, J12_12, J24_24 },
203	[INSTR_RIE_R0IU]     = { R_8, I16_16, U4_32, 0, 0, 0 },
204	[INSTR_RIE_R0UU]     = { R_8, U16_16, U4_32, 0, 0, 0 },
205	[INSTR_RIE_RRI0]     = { R_8, R_12, I16_16, 0, 0, 0 },
206	[INSTR_RIE_RRP]	     = { R_8, R_12, J16_16, 0, 0, 0 },
207	[INSTR_RIE_RRPU]     = { R_8, R_12, U4_32, J16_16, 0, 0 },
208	[INSTR_RIE_RRUUU]    = { R_8, R_12, U8_16, U8_24, U8_32, 0 },
209	[INSTR_RIE_RUI0]     = { R_8, I16_16, U4_12, 0, 0, 0 },
210	[INSTR_RIE_RUPI]     = { R_8, I8_32, U4_12, J16_16, 0, 0 },
211	[INSTR_RIE_RUPU]     = { R_8, U8_32, U4_12, J16_16, 0, 0 },
212	[INSTR_RIL_RI]	     = { R_8, I32_16, 0, 0, 0, 0 },
213	[INSTR_RIL_RP]	     = { R_8, J32_16, 0, 0, 0, 0 },
214	[INSTR_RIL_RU]	     = { R_8, U32_16, 0, 0, 0, 0 },
215	[INSTR_RIL_UP]	     = { U4_8, J32_16, 0, 0, 0, 0 },
216	[INSTR_RIS_RURDI]    = { R_8, I8_32, U4_12, D_20, B_16, 0 },
217	[INSTR_RIS_RURDU]    = { R_8, U8_32, U4_12, D_20, B_16, 0 },
218	[INSTR_RI_RI]	     = { R_8, I16_16, 0, 0, 0, 0 },
219	[INSTR_RI_RP]	     = { R_8, J16_16, 0, 0, 0, 0 },
220	[INSTR_RI_RU]	     = { R_8, U16_16, 0, 0, 0, 0 },
221	[INSTR_RI_UP]	     = { U4_8, J16_16, 0, 0, 0, 0 },
222	[INSTR_RRE_00]	     = { 0, 0, 0, 0, 0, 0 },
223	[INSTR_RRE_AA]	     = { A_24, A_28, 0, 0, 0, 0 },
224	[INSTR_RRE_AR]	     = { A_24, R_28, 0, 0, 0, 0 },
225	[INSTR_RRE_F0]	     = { F_24, 0, 0, 0, 0, 0 },
226	[INSTR_RRE_FF]	     = { F_24, F_28, 0, 0, 0, 0 },
227	[INSTR_RRE_FR]	     = { F_24, R_28, 0, 0, 0, 0 },
228	[INSTR_RRE_R0]	     = { R_24, 0, 0, 0, 0, 0 },
229	[INSTR_RRE_RA]	     = { R_24, A_28, 0, 0, 0, 0 },
230	[INSTR_RRE_RF]	     = { R_24, F_28, 0, 0, 0, 0 },
231	[INSTR_RRE_RR]	     = { R_24, R_28, 0, 0, 0, 0 },
232	[INSTR_RRF_0UFF]     = { F_24, F_28, U4_20, 0, 0, 0 },
233	[INSTR_RRF_0URF]     = { R_24, F_28, U4_20, 0, 0, 0 },
234	[INSTR_RRF_F0FF]     = { F_16, F_24, F_28, 0, 0, 0 },
235	[INSTR_RRF_F0FF2]    = { F_24, F_16, F_28, 0, 0, 0 },
236	[INSTR_RRF_F0FR]     = { F_24, F_16, R_28, 0, 0, 0 },
237	[INSTR_RRF_FFRU]     = { F_24, F_16, R_28, U4_20, 0, 0 },
238	[INSTR_RRF_FUFF]     = { F_24, F_16, F_28, U4_20, 0, 0 },
239	[INSTR_RRF_FUFF2]    = { F_24, F_28, F_16, U4_20, 0, 0 },
240	[INSTR_RRF_R0RR]     = { R_24, R_16, R_28, 0, 0, 0 },
241	[INSTR_RRF_R0RR2]    = { R_24, R_28, R_16, 0, 0, 0 },
242	[INSTR_RRF_RURR]     = { R_24, R_28, R_16, U4_20, 0, 0 },
243	[INSTR_RRF_RURR2]    = { R_24, R_16, R_28, U4_20, 0, 0 },
244	[INSTR_RRF_U0FF]     = { F_24, U4_16, F_28, 0, 0, 0 },
245	[INSTR_RRF_U0RF]     = { R_24, U4_16, F_28, 0, 0, 0 },
246	[INSTR_RRF_U0RR]     = { R_24, R_28, U4_16, 0, 0, 0 },
247	[INSTR_RRF_URR]	     = { R_24, R_28, U8_16, 0, 0, 0 },
248	[INSTR_RRF_UUFF]     = { F_24, U4_16, F_28, U4_20, 0, 0 },
249	[INSTR_RRF_UUFR]     = { F_24, U4_16, R_28, U4_20, 0, 0 },
250	[INSTR_RRF_UURF]     = { R_24, U4_16, F_28, U4_20, 0, 0 },
251	[INSTR_RRS_RRRDU]    = { R_8, R_12, U4_32, D_20, B_16 },
252	[INSTR_RR_FF]	     = { F_8, F_12, 0, 0, 0, 0 },
253	[INSTR_RR_R0]	     = { R_8,  0, 0, 0, 0, 0 },
254	[INSTR_RR_RR]	     = { R_8, R_12, 0, 0, 0, 0 },
255	[INSTR_RR_U0]	     = { U8_8,	0, 0, 0, 0, 0 },
256	[INSTR_RR_UR]	     = { U4_8, R_12, 0, 0, 0, 0 },
257	[INSTR_RSI_RRP]	     = { R_8, R_12, J16_16, 0, 0, 0 },
258	[INSTR_RSL_LRDFU]    = { F_32, D_20, L8_8, B_16, U4_36, 0 },
259	[INSTR_RSL_R0RD]     = { D_20, L4_8, B_16, 0, 0, 0 },
260	[INSTR_RSY_AARD]     = { A_8, A_12, D20_20, B_16, 0, 0 },
261	[INSTR_RSY_CCRD]     = { C_8, C_12, D20_20, B_16, 0, 0 },
 
262	[INSTR_RSY_RRRD]     = { R_8, R_12, D20_20, B_16, 0, 0 },
263	[INSTR_RSY_RURD]     = { R_8, U4_12, D20_20, B_16, 0, 0 },
264	[INSTR_RSY_RURD2]    = { R_8, D20_20, B_16, U4_12, 0, 0 },
265	[INSTR_RS_AARD]	     = { A_8, A_12, D_20, B_16, 0, 0 },
266	[INSTR_RS_CCRD]	     = { C_8, C_12, D_20, B_16, 0, 0 },
267	[INSTR_RS_R0RD]	     = { R_8, D_20, B_16, 0, 0, 0 },
268	[INSTR_RS_RRRD]	     = { R_8, R_12, D_20, B_16, 0, 0 },
269	[INSTR_RS_RURD]	     = { R_8, U4_12, D_20, B_16, 0, 0 },
270	[INSTR_RXE_FRRD]     = { F_8, D_20, X_12, B_16, 0, 0 },
271	[INSTR_RXE_RRRDU]    = { R_8, D_20, X_12, B_16, U4_32, 0 },
272	[INSTR_RXF_FRRDF]    = { F_32, F_8, D_20, X_12, B_16, 0 },
273	[INSTR_RXY_FRRD]     = { F_8, D20_20, X_12, B_16, 0, 0 },
274	[INSTR_RXY_RRRD]     = { R_8, D20_20, X_12, B_16, 0, 0 },
275	[INSTR_RXY_URRD]     = { U4_8, D20_20, X_12, B_16, 0, 0 },
276	[INSTR_RX_FRRD]	     = { F_8, D_20, X_12, B_16, 0, 0 },
277	[INSTR_RX_RRRD]	     = { R_8, D_20, X_12, B_16, 0, 0 },
278	[INSTR_RX_URRD]	     = { U4_8, D_20, X_12, B_16, 0, 0 },
279	[INSTR_SIL_RDI]	     = { D_20, B_16, I16_32, 0, 0, 0 },
280	[INSTR_SIL_RDU]	     = { D_20, B_16, U16_32, 0, 0, 0 },
281	[INSTR_SIY_IRD]	     = { D20_20, B_16, I8_8, 0, 0, 0 },
282	[INSTR_SIY_RD]	     = { D20_20, B_16, 0, 0, 0, 0 },
283	[INSTR_SIY_URD]	     = { D20_20, B_16, U8_8, 0, 0, 0 },
284	[INSTR_SI_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
285	[INSTR_SI_URD]	     = { D_20, B_16, U8_8, 0, 0, 0 },
286	[INSTR_SMI_U0RDP]    = { U4_8, J16_32, D_20, B_16, 0, 0 },
287	[INSTR_SSE_RDRD]     = { D_20, B_16, D_36, B_32, 0, 0 },
288	[INSTR_SSF_RRDRD]    = { D_20, B_16, D_36, B_32, R_8, 0 },
289	[INSTR_SSF_RRDRD2]   = { R_8, D_20, B_16, D_36, B_32, 0 },
290	[INSTR_SS_L0RDRD]    = { D_20, L8_8, B_16, D_36, B_32, 0 },
291	[INSTR_SS_L2RDRD]    = { D_20, B_16, D_36, L8_8, B_32, 0 },
292	[INSTR_SS_LIRDRD]    = { D_20, L4_8, B_16, D_36, B_32, U4_12 },
293	[INSTR_SS_LLRDRD]    = { D_20, L4_8, B_16, D_36, L4_12, B_32 },
294	[INSTR_SS_RRRDRD]    = { D_20, R_8, B_16, D_36, B_32, R_12 },
295	[INSTR_SS_RRRDRD2]   = { R_8, D_20, B_16, R_12, D_36, B_32 },
296	[INSTR_SS_RRRDRD3]   = { R_8, R_12, D_20, B_16, D_36, B_32 },
297	[INSTR_S_00]	     = { 0, 0, 0, 0, 0, 0 },
298	[INSTR_S_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
299	[INSTR_VRI_V0IU]     = { V_8, I16_16, U4_32, 0, 0, 0 },
300	[INSTR_VRI_V0U]	     = { V_8, U16_16, 0, 0, 0, 0 },
301	[INSTR_VRI_V0UU2]    = { V_8, U16_16, U4_32, 0, 0, 0 },
302	[INSTR_VRI_V0UUU]    = { V_8, U8_16, U8_24, U4_32, 0, 0 },
303	[INSTR_VRI_VR0UU]    = { V_8, R_12, U8_28, U4_24, 0, 0 },
304	[INSTR_VRI_VV0UU]    = { V_8, V_12, U8_28, U4_24, 0, 0 },
305	[INSTR_VRI_VVUU]     = { V_8, V_12, U16_16, U4_32, 0, 0 },
306	[INSTR_VRI_VVUUU]    = { V_8, V_12, U12_16, U4_32, U4_28, 0 },
307	[INSTR_VRI_VVUUU2]   = { V_8, V_12, U8_28, U8_16, U4_24, 0 },
308	[INSTR_VRI_VVV0U]    = { V_8, V_12, V_16, U8_24, 0, 0 },
309	[INSTR_VRI_VVV0UU]   = { V_8, V_12, V_16, U8_24, U4_32, 0 },
310	[INSTR_VRI_VVV0UU2]  = { V_8, V_12, V_16, U8_28, U4_24, 0 },
311	[INSTR_VRI_VVV0UV]   = { V_8, V_12, V_16, V_32, U8_24, 0 },
312	[INSTR_VRR_0V0U]     = { V_12, U16_20, 0, 0, 0, 0 },
313	[INSTR_VRR_0VV0U]    = { V_12, V_16, U4_24, 0, 0, 0 },
314	[INSTR_VRR_0VVU]     = { V_12, V_16, U16_20, 0, 0, 0 },
315	[INSTR_VRR_RV0UU]    = { R_8, V_12, U4_24, U4_28, 0, 0 },
316	[INSTR_VRR_VRR]	     = { V_8, R_12, R_16, 0, 0, 0 },
317	[INSTR_VRR_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
318	[INSTR_VRR_VV0U]     = { V_8, V_12, U4_32, 0, 0, 0 },
319	[INSTR_VRR_VV0U0U]   = { V_8, V_12, U4_32, U4_24, 0, 0 },
320	[INSTR_VRR_VV0U2]    = { V_8, V_12, U4_24, 0, 0, 0 },
321	[INSTR_VRR_VV0UU2]   = { V_8, V_12, U4_32, U4_28, 0, 0 },
322	[INSTR_VRR_VV0UUU]   = { V_8, V_12, U4_32, U4_28, U4_24, 0 },
323	[INSTR_VRR_VVV]	     = { V_8, V_12, V_16, 0, 0, 0 },
324	[INSTR_VRR_VVV0U]    = { V_8, V_12, V_16, U4_32, 0, 0 },
325	[INSTR_VRR_VVV0U0]   = { V_8, V_12, V_16, U4_24, 0, 0 },
326	[INSTR_VRR_VVV0U0U]  = { V_8, V_12, V_16, U4_32, U4_24, 0 },
327	[INSTR_VRR_VVV0UU]   = { V_8, V_12, V_16, U4_32, U4_28, 0 },
328	[INSTR_VRR_VVV0UUU]  = { V_8, V_12, V_16, U4_32, U4_28, U4_24 },
329	[INSTR_VRR_VVV0V]    = { V_8, V_12, V_16, V_32, 0, 0 },
330	[INSTR_VRR_VVVU0UV]  = { V_8, V_12, V_16, V_32, U4_28, U4_20 },
331	[INSTR_VRR_VVVU0V]   = { V_8, V_12, V_16, V_32, U4_20, 0 },
332	[INSTR_VRR_VVVUU0V]  = { V_8, V_12, V_16, V_32, U4_20, U4_24 },
333	[INSTR_VRS_RRDV]     = { V_32, R_12, D_20, B_16, 0, 0 },
334	[INSTR_VRS_RVRDU]    = { R_8, V_12, D_20, B_16, U4_32, 0 },
335	[INSTR_VRS_VRRD]     = { V_8, R_12, D_20, B_16, 0, 0 },
336	[INSTR_VRS_VRRDU]    = { V_8, R_12, D_20, B_16, U4_32, 0 },
337	[INSTR_VRS_VVRDU]    = { V_8, V_12, D_20, B_16, U4_32, 0 },
338	[INSTR_VRV_VVXRDU]   = { V_8, D_20, VX_12, B_16, U4_32, 0 },
339	[INSTR_VRX_VRRDU]    = { V_8, D_20, X_12, B_16, U4_32, 0 },
340	[INSTR_VRX_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
341	[INSTR_VSI_URDV]     = { V_32, D_20, B_16, U8_8, 0, 0 },
342};
343
344static char long_insn_name[][7] = LONG_INSN_INITIALIZER;
345static struct s390_insn opcode[] = OPCODE_TABLE_INITIALIZER;
346static struct s390_opcode_offset opcode_offset[] = OPCODE_OFFSET_INITIALIZER;
347
348/* Extracts an operand value from an instruction.  */
349static unsigned int extract_operand(unsigned char *code,
350				    const struct s390_operand *operand)
351{
352	unsigned char *cp;
353	unsigned int val;
354	int bits;
355
356	/* Extract fragments of the operand byte for byte.  */
357	cp = code + operand->shift / 8;
358	bits = (operand->shift & 7) + operand->bits;
359	val = 0;
360	do {
361		val <<= 8;
362		val |= (unsigned int) *cp++;
363		bits -= 8;
364	} while (bits > 0);
365	val >>= -bits;
366	val &= ((1U << (operand->bits - 1)) << 1) - 1;
367
368	/* Check for special long displacement case.  */
369	if (operand->bits == 20 && operand->shift == 20)
370		val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
371
372	/* Check for register extensions bits for vector registers. */
373	if (operand->flags & OPERAND_VR) {
374		if (operand->shift == 8)
375			val |= (code[4] & 8) << 1;
376		else if (operand->shift == 12)
377			val |= (code[4] & 4) << 2;
378		else if (operand->shift == 16)
379			val |= (code[4] & 2) << 3;
380		else if (operand->shift == 32)
381			val |= (code[4] & 1) << 4;
382	}
383
384	/* Sign extend value if the operand is signed or pc relative.  */
385	if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
386	    (val & (1U << (operand->bits - 1))))
387		val |= (-1U << (operand->bits - 1)) << 1;
388
389	/* Double value if the operand is pc relative.	*/
390	if (operand->flags & OPERAND_PCREL)
391		val <<= 1;
392
393	/* Length x in an instructions has real length x + 1.  */
394	if (operand->flags & OPERAND_LENGTH)
395		val++;
396	return val;
397}
398
399struct s390_insn *find_insn(unsigned char *code)
400{
401	struct s390_opcode_offset *entry;
402	struct s390_insn *insn;
403	unsigned char opfrag;
404	int i;
405
406	/* Search the opcode offset table to find an entry which
407	 * matches the beginning of the opcode. If there is no match
408	 * the last entry will be used, which is the default entry for
409	 * unknown instructions as well as 1-byte opcode instructions.
410	 */
411	for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
412		entry = &opcode_offset[i];
413		if (entry->opcode == code[0])
414			break;
415	}
416
417	opfrag = *(code + entry->byte) & entry->mask;
418
419	insn = &opcode[entry->offset];
420	for (i = 0; i < entry->count; i++) {
421		if (insn->opfrag == opfrag)
422			return insn;
423		insn++;
424	}
425	return NULL;
426}
427
428static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
429{
430	struct s390_insn *insn;
431	const unsigned char *ops;
432	const struct s390_operand *operand;
433	unsigned int value;
434	char separator;
435	char *ptr;
436	int i;
437
438	ptr = buffer;
439	insn = find_insn(code);
440	if (insn) {
441		if (insn->zero == 0)
442			ptr += sprintf(ptr, "%.7s\t",
443				       long_insn_name[insn->offset]);
444		else
445			ptr += sprintf(ptr, "%.5s\t", insn->name);
446		/* Extract the operands. */
447		separator = 0;
448		for (ops = formats[insn->format], i = 0;
449		     *ops != 0 && i < 6; ops++, i++) {
450			operand = operands + *ops;
451			value = extract_operand(code, operand);
452			if ((operand->flags & OPERAND_INDEX)  && value == 0)
453				continue;
454			if ((operand->flags & OPERAND_BASE) &&
455			    value == 0 && separator == '(') {
456				separator = ',';
457				continue;
458			}
459			if (separator)
460				ptr += sprintf(ptr, "%c", separator);
461			if (operand->flags & OPERAND_GPR)
462				ptr += sprintf(ptr, "%%r%u", value);
463			else if (operand->flags & OPERAND_FPR)
464				ptr += sprintf(ptr, "%%f%u", value);
465			else if (operand->flags & OPERAND_AR)
466				ptr += sprintf(ptr, "%%a%u", value);
467			else if (operand->flags & OPERAND_CR)
468				ptr += sprintf(ptr, "%%c%u", value);
469			else if (operand->flags & OPERAND_VR)
470				ptr += sprintf(ptr, "%%v%u", value);
471			else if (operand->flags & OPERAND_PCREL) {
472				void *pcrel = (void *)((int)value + addr);
473
474				ptr += sprintf(ptr, "%px", pcrel);
475			} else if (operand->flags & OPERAND_SIGNED)
476				ptr += sprintf(ptr, "%i", (int)value);
477			else
478				ptr += sprintf(ptr, "%u", value);
479			if (operand->flags & OPERAND_DISP)
480				separator = '(';
481			else if (operand->flags & OPERAND_BASE) {
482				ptr += sprintf(ptr, ")");
483				separator = ',';
484			} else
485				separator = ',';
486		}
487	} else
488		ptr += sprintf(ptr, "unknown");
489	return (int) (ptr - buffer);
490}
491
492static int copy_from_regs(struct pt_regs *regs, void *dst, void *src, int len)
493{
494	if (user_mode(regs)) {
495		if (copy_from_user(dst, (char __user *)src, len))
496			return -EFAULT;
497	} else {
498		if (copy_from_kernel_nofault(dst, src, len))
499			return -EFAULT;
500	}
501	return 0;
502}
503
504void show_code(struct pt_regs *regs)
505{
506	char *mode = user_mode(regs) ? "User" : "Krnl";
507	unsigned char code[64];
508	char buffer[128], *ptr;
 
509	unsigned long addr;
510	int start, end, opsize, hops, i;
511
512	/* Get a snapshot of the 64 bytes surrounding the fault address. */
 
 
513	for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
514		addr = regs->psw.addr - 34 + start;
515		if (copy_from_regs(regs, code + start - 2, (void *)addr, 2))
 
516			break;
517	}
518	for (end = 32; end < 64; end += 2) {
519		addr = regs->psw.addr + end - 32;
520		if (copy_from_regs(regs, code + end, (void *)addr, 2))
 
521			break;
522	}
523	/* Code snapshot usable ? */
 
524	if ((regs->psw.addr & 1) || start >= end) {
525		printk("%s Code: Bad PSW.\n", mode);
526		return;
527	}
528	/* Find a starting point for the disassembly. */
529	while (start < 32) {
530		for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
531			if (!find_insn(code + start + i))
532				break;
533			i += insn_length(code[start + i]);
534		}
535		if (start + i == 32)
536			/* Looks good, sequence ends at PSW. */
537			break;
538		start += 2;
539	}
540	/* Decode the instructions. */
541	ptr = buffer;
542	ptr += sprintf(ptr, "%s Code:", mode);
543	hops = 0;
544	while (start < end && hops < 8) {
545		opsize = insn_length(code[start]);
546		if  (start + opsize == 32)
547			*ptr++ = '#';
548		else if (start == 32)
549			*ptr++ = '>';
550		else
551			*ptr++ = ' ';
552		addr = regs->psw.addr + start - 32;
553		ptr += sprintf(ptr, "%px: ", (void *)addr);
554		if (start + opsize >= end)
555			break;
556		for (i = 0; i < opsize; i++)
557			ptr += sprintf(ptr, "%02x", code[start + i]);
558		*ptr++ = '\t';
559		if (i < 6)
560			*ptr++ = '\t';
561		ptr += print_insn(ptr, code + start, addr);
562		start += opsize;
563		pr_cont("%s", buffer);
564		ptr = buffer;
565		ptr += sprintf(ptr, "\n          ");
566		hops++;
567	}
568	pr_cont("\n");
569}
570
571void print_fn_code(unsigned char *code, unsigned long len)
572{
573	char buffer[128], *ptr;
574	int opsize, i;
575
576	while (len) {
577		ptr = buffer;
578		opsize = insn_length(*code);
579		if (opsize > len)
580			break;
581		ptr += sprintf(ptr, "%px: ", code);
582		for (i = 0; i < opsize; i++)
583			ptr += sprintf(ptr, "%02x", code[i]);
584		*ptr++ = '\t';
585		if (i < 4)
586			*ptr++ = '\t';
587		ptr += print_insn(ptr, code, (unsigned long) code);
588		*ptr++ = '\n';
589		*ptr++ = 0;
590		printk("%s", buffer);
591		code += opsize;
592		len -= opsize;
593	}
594}