cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dis.c (21582B)


      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_RD]	     = { D20_20, B_16, 0, 0, 0, 0 },
    282	[INSTR_SIY_URD]	     = { D20_20, B_16, U8_8, 0, 0, 0 },
    283	[INSTR_SI_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
    284	[INSTR_SI_URD]	     = { D_20, B_16, U8_8, 0, 0, 0 },
    285	[INSTR_SMI_U0RDP]    = { U4_8, J16_32, D_20, B_16, 0, 0 },
    286	[INSTR_SSE_RDRD]     = { D_20, B_16, D_36, B_32, 0, 0 },
    287	[INSTR_SSF_RRDRD]    = { D_20, B_16, D_36, B_32, R_8, 0 },
    288	[INSTR_SSF_RRDRD2]   = { R_8, D_20, B_16, D_36, B_32, 0 },
    289	[INSTR_SS_L0RDRD]    = { D_20, L8_8, B_16, D_36, B_32, 0 },
    290	[INSTR_SS_L2RDRD]    = { D_20, B_16, D_36, L8_8, B_32, 0 },
    291	[INSTR_SS_LIRDRD]    = { D_20, L4_8, B_16, D_36, B_32, U4_12 },
    292	[INSTR_SS_LLRDRD]    = { D_20, L4_8, B_16, D_36, L4_12, B_32 },
    293	[INSTR_SS_RRRDRD]    = { D_20, R_8, B_16, D_36, B_32, R_12 },
    294	[INSTR_SS_RRRDRD2]   = { R_8, D_20, B_16, R_12, D_36, B_32 },
    295	[INSTR_SS_RRRDRD3]   = { R_8, R_12, D_20, B_16, D_36, B_32 },
    296	[INSTR_S_00]	     = { 0, 0, 0, 0, 0, 0 },
    297	[INSTR_S_RD]	     = { D_20, B_16, 0, 0, 0, 0 },
    298	[INSTR_VRI_V0IU]     = { V_8, I16_16, U4_32, 0, 0, 0 },
    299	[INSTR_VRI_V0U]	     = { V_8, U16_16, 0, 0, 0, 0 },
    300	[INSTR_VRI_V0UU2]    = { V_8, U16_16, U4_32, 0, 0, 0 },
    301	[INSTR_VRI_V0UUU]    = { V_8, U8_16, U8_24, U4_32, 0, 0 },
    302	[INSTR_VRI_VR0UU]    = { V_8, R_12, U8_28, U4_24, 0, 0 },
    303	[INSTR_VRI_VVUU]     = { V_8, V_12, U16_16, U4_32, 0, 0 },
    304	[INSTR_VRI_VVUUU]    = { V_8, V_12, U12_16, U4_32, U4_28, 0 },
    305	[INSTR_VRI_VVUUU2]   = { V_8, V_12, U8_28, U8_16, U4_24, 0 },
    306	[INSTR_VRI_VVV0U]    = { V_8, V_12, V_16, U8_24, 0, 0 },
    307	[INSTR_VRI_VVV0UU]   = { V_8, V_12, V_16, U8_24, U4_32, 0 },
    308	[INSTR_VRI_VVV0UU2]  = { V_8, V_12, V_16, U8_28, U4_24, 0 },
    309	[INSTR_VRR_0V]	     = { V_12, 0, 0, 0, 0, 0 },
    310	[INSTR_VRR_0VV0U]    = { V_12, V_16, U4_24, 0, 0, 0 },
    311	[INSTR_VRR_RV0UU]    = { R_8, V_12, U4_24, U4_28, 0, 0 },
    312	[INSTR_VRR_VRR]	     = { V_8, R_12, R_16, 0, 0, 0 },
    313	[INSTR_VRR_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
    314	[INSTR_VRR_VV0U]     = { V_8, V_12, U4_32, 0, 0, 0 },
    315	[INSTR_VRR_VV0U0U]   = { V_8, V_12, U4_32, U4_24, 0, 0 },
    316	[INSTR_VRR_VV0U2]    = { V_8, V_12, U4_24, 0, 0, 0 },
    317	[INSTR_VRR_VV0UU2]   = { V_8, V_12, U4_32, U4_28, 0, 0 },
    318	[INSTR_VRR_VV0UUU]   = { V_8, V_12, U4_32, U4_28, U4_24, 0 },
    319	[INSTR_VRR_VVV]	     = { V_8, V_12, V_16, 0, 0, 0 },
    320	[INSTR_VRR_VVV0U]    = { V_8, V_12, V_16, U4_32, 0, 0 },
    321	[INSTR_VRR_VVV0U0]   = { V_8, V_12, V_16, U4_24, 0, 0 },
    322	[INSTR_VRR_VVV0U0U]  = { V_8, V_12, V_16, U4_32, U4_24, 0 },
    323	[INSTR_VRR_VVV0UU]   = { V_8, V_12, V_16, U4_32, U4_28, 0 },
    324	[INSTR_VRR_VVV0UUU]  = { V_8, V_12, V_16, U4_32, U4_28, U4_24 },
    325	[INSTR_VRR_VVV0V]    = { V_8, V_12, V_16, V_32, 0, 0 },
    326	[INSTR_VRR_VVVU0UV]  = { V_8, V_12, V_16, V_32, U4_28, U4_20 },
    327	[INSTR_VRR_VVVU0V]   = { V_8, V_12, V_16, V_32, U4_20, 0 },
    328	[INSTR_VRR_VVVUU0V]  = { V_8, V_12, V_16, V_32, U4_20, U4_24 },
    329	[INSTR_VRS_RRDV]     = { V_32, R_12, D_20, B_16, 0, 0 },
    330	[INSTR_VRS_RVRDU]    = { R_8, V_12, D_20, B_16, U4_32, 0 },
    331	[INSTR_VRS_VRRD]     = { V_8, R_12, D_20, B_16, 0, 0 },
    332	[INSTR_VRS_VRRDU]    = { V_8, R_12, D_20, B_16, U4_32, 0 },
    333	[INSTR_VRS_VVRDU]    = { V_8, V_12, D_20, B_16, U4_32, 0 },
    334	[INSTR_VRV_VVXRDU]   = { V_8, D_20, VX_12, B_16, U4_32, 0 },
    335	[INSTR_VRX_VRRDU]    = { V_8, D_20, X_12, B_16, U4_32, 0 },
    336	[INSTR_VRX_VV]	     = { V_8, V_12, 0, 0, 0, 0 },
    337	[INSTR_VSI_URDV]     = { V_32, D_20, B_16, U8_8, 0, 0 },
    338};
    339
    340static char long_insn_name[][7] = LONG_INSN_INITIALIZER;
    341static struct s390_insn opcode[] = OPCODE_TABLE_INITIALIZER;
    342static struct s390_opcode_offset opcode_offset[] = OPCODE_OFFSET_INITIALIZER;
    343
    344/* Extracts an operand value from an instruction.  */
    345static unsigned int extract_operand(unsigned char *code,
    346				    const struct s390_operand *operand)
    347{
    348	unsigned char *cp;
    349	unsigned int val;
    350	int bits;
    351
    352	/* Extract fragments of the operand byte for byte.  */
    353	cp = code + operand->shift / 8;
    354	bits = (operand->shift & 7) + operand->bits;
    355	val = 0;
    356	do {
    357		val <<= 8;
    358		val |= (unsigned int) *cp++;
    359		bits -= 8;
    360	} while (bits > 0);
    361	val >>= -bits;
    362	val &= ((1U << (operand->bits - 1)) << 1) - 1;
    363
    364	/* Check for special long displacement case.  */
    365	if (operand->bits == 20 && operand->shift == 20)
    366		val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
    367
    368	/* Check for register extensions bits for vector registers. */
    369	if (operand->flags & OPERAND_VR) {
    370		if (operand->shift == 8)
    371			val |= (code[4] & 8) << 1;
    372		else if (operand->shift == 12)
    373			val |= (code[4] & 4) << 2;
    374		else if (operand->shift == 16)
    375			val |= (code[4] & 2) << 3;
    376		else if (operand->shift == 32)
    377			val |= (code[4] & 1) << 4;
    378	}
    379
    380	/* Sign extend value if the operand is signed or pc relative.  */
    381	if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
    382	    (val & (1U << (operand->bits - 1))))
    383		val |= (-1U << (operand->bits - 1)) << 1;
    384
    385	/* Double value if the operand is pc relative.	*/
    386	if (operand->flags & OPERAND_PCREL)
    387		val <<= 1;
    388
    389	/* Length x in an instructions has real length x + 1.  */
    390	if (operand->flags & OPERAND_LENGTH)
    391		val++;
    392	return val;
    393}
    394
    395struct s390_insn *find_insn(unsigned char *code)
    396{
    397	struct s390_opcode_offset *entry;
    398	struct s390_insn *insn;
    399	unsigned char opfrag;
    400	int i;
    401
    402	/* Search the opcode offset table to find an entry which
    403	 * matches the beginning of the opcode. If there is no match
    404	 * the last entry will be used, which is the default entry for
    405	 * unknown instructions as well as 1-byte opcode instructions.
    406	 */
    407	for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
    408		entry = &opcode_offset[i];
    409		if (entry->opcode == code[0])
    410			break;
    411	}
    412
    413	opfrag = *(code + entry->byte) & entry->mask;
    414
    415	insn = &opcode[entry->offset];
    416	for (i = 0; i < entry->count; i++) {
    417		if (insn->opfrag == opfrag)
    418			return insn;
    419		insn++;
    420	}
    421	return NULL;
    422}
    423
    424static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
    425{
    426	struct s390_insn *insn;
    427	const unsigned char *ops;
    428	const struct s390_operand *operand;
    429	unsigned int value;
    430	char separator;
    431	char *ptr;
    432	int i;
    433
    434	ptr = buffer;
    435	insn = find_insn(code);
    436	if (insn) {
    437		if (insn->zero == 0)
    438			ptr += sprintf(ptr, "%.7s\t",
    439				       long_insn_name[insn->offset]);
    440		else
    441			ptr += sprintf(ptr, "%.5s\t", insn->name);
    442		/* Extract the operands. */
    443		separator = 0;
    444		for (ops = formats[insn->format], i = 0;
    445		     *ops != 0 && i < 6; ops++, i++) {
    446			operand = operands + *ops;
    447			value = extract_operand(code, operand);
    448			if ((operand->flags & OPERAND_INDEX)  && value == 0)
    449				continue;
    450			if ((operand->flags & OPERAND_BASE) &&
    451			    value == 0 && separator == '(') {
    452				separator = ',';
    453				continue;
    454			}
    455			if (separator)
    456				ptr += sprintf(ptr, "%c", separator);
    457			if (operand->flags & OPERAND_GPR)
    458				ptr += sprintf(ptr, "%%r%i", value);
    459			else if (operand->flags & OPERAND_FPR)
    460				ptr += sprintf(ptr, "%%f%i", value);
    461			else if (operand->flags & OPERAND_AR)
    462				ptr += sprintf(ptr, "%%a%i", value);
    463			else if (operand->flags & OPERAND_CR)
    464				ptr += sprintf(ptr, "%%c%i", value);
    465			else if (operand->flags & OPERAND_VR)
    466				ptr += sprintf(ptr, "%%v%i", value);
    467			else if (operand->flags & OPERAND_PCREL) {
    468				void *pcrel = (void *)((int)value + addr);
    469
    470				ptr += sprintf(ptr, "%px", pcrel);
    471			} else if (operand->flags & OPERAND_SIGNED)
    472				ptr += sprintf(ptr, "%i", value);
    473			else
    474				ptr += sprintf(ptr, "%u", value);
    475			if (operand->flags & OPERAND_DISP)
    476				separator = '(';
    477			else if (operand->flags & OPERAND_BASE) {
    478				ptr += sprintf(ptr, ")");
    479				separator = ',';
    480			} else
    481				separator = ',';
    482		}
    483	} else
    484		ptr += sprintf(ptr, "unknown");
    485	return (int) (ptr - buffer);
    486}
    487
    488static int copy_from_regs(struct pt_regs *regs, void *dst, void *src, int len)
    489{
    490	if (user_mode(regs)) {
    491		if (copy_from_user(dst, (char __user *)src, len))
    492			return -EFAULT;
    493	} else {
    494		if (copy_from_kernel_nofault(dst, src, len))
    495			return -EFAULT;
    496	}
    497	return 0;
    498}
    499
    500void show_code(struct pt_regs *regs)
    501{
    502	char *mode = user_mode(regs) ? "User" : "Krnl";
    503	unsigned char code[64];
    504	char buffer[128], *ptr;
    505	unsigned long addr;
    506	int start, end, opsize, hops, i;
    507
    508	/* Get a snapshot of the 64 bytes surrounding the fault address. */
    509	for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
    510		addr = regs->psw.addr - 34 + start;
    511		if (copy_from_regs(regs, code + start - 2, (void *)addr, 2))
    512			break;
    513	}
    514	for (end = 32; end < 64; end += 2) {
    515		addr = regs->psw.addr + end - 32;
    516		if (copy_from_regs(regs, code + end, (void *)addr, 2))
    517			break;
    518	}
    519	/* Code snapshot useable ? */
    520	if ((regs->psw.addr & 1) || start >= end) {
    521		printk("%s Code: Bad PSW.\n", mode);
    522		return;
    523	}
    524	/* Find a starting point for the disassembly. */
    525	while (start < 32) {
    526		for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
    527			if (!find_insn(code + start + i))
    528				break;
    529			i += insn_length(code[start + i]);
    530		}
    531		if (start + i == 32)
    532			/* Looks good, sequence ends at PSW. */
    533			break;
    534		start += 2;
    535	}
    536	/* Decode the instructions. */
    537	ptr = buffer;
    538	ptr += sprintf(ptr, "%s Code:", mode);
    539	hops = 0;
    540	while (start < end && hops < 8) {
    541		opsize = insn_length(code[start]);
    542		if  (start + opsize == 32)
    543			*ptr++ = '#';
    544		else if (start == 32)
    545			*ptr++ = '>';
    546		else
    547			*ptr++ = ' ';
    548		addr = regs->psw.addr + start - 32;
    549		ptr += sprintf(ptr, "%px: ", (void *)addr);
    550		if (start + opsize >= end)
    551			break;
    552		for (i = 0; i < opsize; i++)
    553			ptr += sprintf(ptr, "%02x", code[start + i]);
    554		*ptr++ = '\t';
    555		if (i < 6)
    556			*ptr++ = '\t';
    557		ptr += print_insn(ptr, code + start, addr);
    558		start += opsize;
    559		pr_cont("%s", buffer);
    560		ptr = buffer;
    561		ptr += sprintf(ptr, "\n          ");
    562		hops++;
    563	}
    564	pr_cont("\n");
    565}
    566
    567void print_fn_code(unsigned char *code, unsigned long len)
    568{
    569	char buffer[128], *ptr;
    570	int opsize, i;
    571
    572	while (len) {
    573		ptr = buffer;
    574		opsize = insn_length(*code);
    575		if (opsize > len)
    576			break;
    577		ptr += sprintf(ptr, "%px: ", code);
    578		for (i = 0; i < opsize; i++)
    579			ptr += sprintf(ptr, "%02x", code[i]);
    580		*ptr++ = '\t';
    581		if (i < 4)
    582			*ptr++ = '\t';
    583		ptr += print_insn(ptr, code, (unsigned long) code);
    584		*ptr++ = '\n';
    585		*ptr++ = 0;
    586		printk("%s", buffer);
    587		code += opsize;
    588		len -= opsize;
    589	}
    590}