linux/arch/s390/kernel/dis.c
<<
>>
Prefs
   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                                void *pcrel = (void *)((int)value + addr);
 466
 467                                ptr += sprintf(ptr, "%px", pcrel);
 468                        } else if (operand->flags & OPERAND_SIGNED)
 469                                ptr += sprintf(ptr, "%i", value);
 470                        else
 471                                ptr += sprintf(ptr, "%u", value);
 472                        if (operand->flags & OPERAND_DISP)
 473                                separator = '(';
 474                        else if (operand->flags & OPERAND_BASE) {
 475                                ptr += sprintf(ptr, ")");
 476                                separator = ',';
 477                        } else
 478                                separator = ',';
 479                }
 480        } else
 481                ptr += sprintf(ptr, "unknown");
 482        return (int) (ptr - buffer);
 483}
 484
 485static int copy_from_regs(struct pt_regs *regs, void *dst, void *src, int len)
 486{
 487        if (user_mode(regs)) {
 488                if (copy_from_user(dst, (char __user *)src, len))
 489                        return -EFAULT;
 490        } else {
 491                if (copy_from_kernel_nofault(dst, src, len))
 492                        return -EFAULT;
 493        }
 494        return 0;
 495}
 496
 497void show_code(struct pt_regs *regs)
 498{
 499        char *mode = user_mode(regs) ? "User" : "Krnl";
 500        unsigned char code[64];
 501        char buffer[128], *ptr;
 502        unsigned long addr;
 503        int start, end, opsize, hops, i;
 504
 505        /* Get a snapshot of the 64 bytes surrounding the fault address. */
 506        for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
 507                addr = regs->psw.addr - 34 + start;
 508                if (copy_from_regs(regs, code + start - 2, (void *)addr, 2))
 509                        break;
 510        }
 511        for (end = 32; end < 64; end += 2) {
 512                addr = regs->psw.addr + end - 32;
 513                if (copy_from_regs(regs, code + end, (void *)addr, 2))
 514                        break;
 515        }
 516        /* Code snapshot useable ? */
 517        if ((regs->psw.addr & 1) || start >= end) {
 518                printk("%s Code: Bad PSW.\n", mode);
 519                return;
 520        }
 521        /* Find a starting point for the disassembly. */
 522        while (start < 32) {
 523                for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
 524                        if (!find_insn(code + start + i))
 525                                break;
 526                        i += insn_length(code[start + i]);
 527                }
 528                if (start + i == 32)
 529                        /* Looks good, sequence ends at PSW. */
 530                        break;
 531                start += 2;
 532        }
 533        /* Decode the instructions. */
 534        ptr = buffer;
 535        ptr += sprintf(ptr, "%s Code:", mode);
 536        hops = 0;
 537        while (start < end && hops < 8) {
 538                opsize = insn_length(code[start]);
 539                if  (start + opsize == 32)
 540                        *ptr++ = '#';
 541                else if (start == 32)
 542                        *ptr++ = '>';
 543                else
 544                        *ptr++ = ' ';
 545                addr = regs->psw.addr + start - 32;
 546                ptr += sprintf(ptr, "%px: ", (void *)addr);
 547                if (start + opsize >= end)
 548                        break;
 549                for (i = 0; i < opsize; i++)
 550                        ptr += sprintf(ptr, "%02x", code[start + i]);
 551                *ptr++ = '\t';
 552                if (i < 6)
 553                        *ptr++ = '\t';
 554                ptr += print_insn(ptr, code + start, addr);
 555                start += opsize;
 556                pr_cont("%s", buffer);
 557                ptr = buffer;
 558                ptr += sprintf(ptr, "\n          ");
 559                hops++;
 560        }
 561        pr_cont("\n");
 562}
 563
 564void print_fn_code(unsigned char *code, unsigned long len)
 565{
 566        char buffer[128], *ptr;
 567        int opsize, i;
 568
 569        while (len) {
 570                ptr = buffer;
 571                opsize = insn_length(*code);
 572                if (opsize > len)
 573                        break;
 574                ptr += sprintf(ptr, "%px: ", code);
 575                for (i = 0; i < opsize; i++)
 576                        ptr += sprintf(ptr, "%02x", code[i]);
 577                *ptr++ = '\t';
 578                if (i < 4)
 579                        *ptr++ = '\t';
 580                ptr += print_insn(ptr, code, (unsigned long) code);
 581                *ptr++ = '\n';
 582                *ptr++ = 0;
 583                printk("%s", buffer);
 584                code += opsize;
 585                len -= opsize;
 586        }
 587}
 588