GIT 54d4f9edb5f8b6fdb3f9644785084dd9ddaed553 git://git390.osdl.marist.edu/pub/scm/linux-2.6.git#for-andrew commit Author: Peter Oberparleiter Date: Wed Mar 7 18:41:25 2007 +0100 [S390] cio: introduce struct chp_id Introduce data type for channel-path IDs. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky commit c91ff139feffef06542c7a30eb172bee8028e814 Author: Heiko Carstens Date: Wed Mar 7 18:39:54 2007 +0100 [S390] cio/ipl: Clean interface between cio and ipl code. Clean interface between cio and ipl code, so Peter stops complaining. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit 24c158a6709f9611bd99e70c33ab9cf5701595e9 Author: Heiko Carstens Date: Wed Mar 7 18:39:51 2007 +0100 [S390] Use generic bug. Generic bug implementation for s390. Will increase the value of the console output on BUG() statements since registers r0-r5,r14 will not be clobbered by a printk() call that was previously done before the illegal instruction of BUG() was hit. Also implements an architecture specific WARN_ON(). Output of that could be increased but requires common code change. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit ad38a3072ca9bac125809d78e11eb121a6c7d48c Author: Martin Schwidefsky Date: Wed Mar 7 18:39:48 2007 +0100 [S390] improved oops output. This patch adds two improvements to the oops output. First it adds an additional line after the PSW which decodes the different fields of it. Second a disassembler is added that decodes the instructions surrounding the faulting PSW. The output of a test oops now looks like this: kernel BUG at init/main.c:419 illegal operation: 0001 [#1] CPU: 0 Not tainted Process swapper (pid: 0, task: 0000000000464968, ksp: 00000000004be000) Krnl PSW : 0700000180000000 00000000000120b6 (rest_init+0x36/0x38) R:0 T:1 IO:1 EX:1 Key:0 M:0 W:0 P:0 AS:0 CC:0 PM:0 EA:3 Krnl GPRS: 0000000000000003 00000000004ba017 0000000000000022 0000000000000001 000000000003a5f6 0000000000000000 00000000004be6a8 0000000000000000 0000000000000000 00000000004b8200 0000000000003a50 0000000000008000 0000000000516368 000000000033d008 00000000000120b2 00000000004bdee0 Krnl Code: 00000000000120a6: e3e0f0980024 stg %r14,152(%r15) 00000000000120ac: c0e500014296 brasl %r14,3a5d8 00000000000120b2: a7f40001 brc 15,120b4 >00000000000120b6: 0707 bcr 0,%r7 00000000000120b8: eb7ff0500024 stmg %r7,%r15,80(%r15) 00000000000120be: c0d000195825 larl %r13,33d108 00000000000120c4: a7f13f00 tmll %r15,16128 00000000000120c8: a7840001 brc 8,120ca Call Trace: ([<00000000000120b2>] rest_init+0x32/0x38) [<00000000004be614>] start_kernel+0x37c/0x410 [<0000000000012020>] _ehead+0x20/0x80 Signed-off-by: Martin Schwidefsky commit 6d35b1a05e1146d6b142638c51644b039f6dc6b8 Author: Martin Schwidefsky Date: Wed Mar 7 18:39:45 2007 +0100 [S390] system call cleanup. Remove system call glue for sys_clone, sys_fork, sys_vfork, sys_execve, sys_sigreturn, sys_rt_sigreturn and sys_sigaltstack. Call do_execve from kernel_execve directly, move pt_regs to the right place and branch to sysc_return to start the user space program. This removes the last in-kernel system call. Signed-off-by: Martin Schwidefsky commit 92c5d8f66d644ccf8583a910fa0cc09a32e81d06 Author: Jean Delvare Date: Wed Mar 7 18:39:24 2007 +0100 [S390] strlcpy is smart enough strlcpy already accounts for the trailing zero in its length computation, so there is no need to substract one to the buffer size. Signed-off-by: Jean Delvare Cc: Martin Schwidefsky Signed-off-by: Andrew Morton commit eeceff6d80a6c5b593c0fc5256bd0cdcb70c260e Author: Heiko Carstens Date: Wed Mar 7 18:38:39 2007 +0100 memory detection: fix off by one bug. diag 260 returns the address of the last addressable byte and not the size of memory. Since we want the size we have to add 1 to the return value. Disable diag 260 for non z/Arch mode since it doesn't work there anyway. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky commit 3d05ca7fc204436493c3a257666bd925dd118f4f Author: Ursula Braun Date: Wed Mar 7 18:38:32 2007 +0100 [S390] cio: qdio slsb setup Make sure set_slsb problems are handled correctly in qdio_do_qdio_fill_input() and qdio_do_qdio_fill_output. Signed-off-by: Ursula Braun Signed-off-by: Martin Schwidefsky arch/s390/Kconfig | 5 arch/s390/defconfig | 2 arch/s390/kernel/Makefile | 2 arch/s390/kernel/compat_linux.c | 60 +- arch/s390/kernel/compat_signal.c | 14 arch/s390/kernel/debug.c | 2 arch/s390/kernel/dis.c | 1268 ++++++++++++++++++++++++++++++++++++++ arch/s390/kernel/early.c | 10 arch/s390/kernel/entry.S | 87 +-- arch/s390/kernel/entry64.S | 100 +-- arch/s390/kernel/ipl.c | 23 + arch/s390/kernel/module.c | 4 arch/s390/kernel/process.c | 82 +- arch/s390/kernel/signal.c | 10 arch/s390/kernel/sys_s390.c | 20 - arch/s390/kernel/syscalls.S | 14 arch/s390/kernel/traps.c | 72 +- arch/s390/kernel/vmlinux.lds.S | 10 drivers/s390/cio/chpid.h | 53 ++ drivers/s390/cio/chsc.c | 175 +++-- drivers/s390/cio/chsc.h | 8 drivers/s390/cio/cio.c | 43 - drivers/s390/cio/device_fsm.c | 6 drivers/s390/cio/ioasm.h | 5 drivers/s390/cio/qdio.c | 26 + include/asm-s390/bug.h | 69 ++ include/asm-s390/cio.h | 7 include/asm-s390/ipl.h | 3 include/asm-s390/processor.h | 1 29 files changed, 1771 insertions(+), 410 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 0f293aa..0f9517b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -41,6 +41,11 @@ config GENERIC_HWEIGHT config GENERIC_TIME def_bool y +config GENERIC_BUG + bool + depends on BUG + default y + config NO_IOMEM def_bool y diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 741d2bb..80046d9 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -12,6 +12,7 @@ # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_BUG=y CONFIG_NO_IOMEM=y CONFIG_S390=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -705,6 +706,7 @@ # CONFIG_PROVE_LOCKING is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 5492d25..3195d37 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o base.o early.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o irq.o ipl.o + semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 664c669..5236fdb 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -495,29 +495,34 @@ sys32_rt_sigqueueinfo(int pid, int sig, * sys32_execve() executes a new program after the asm stub has set * things up for us. This should basically do what I want it to. */ -asmlinkage long -sys32_execve(struct pt_regs regs) +asmlinkage long sys32_execve(void) { - int error; - char * filename; + struct pt_regs *regs = task_pt_regs(current); + char *filename; + unsigned long result; + int rc; - filename = getname(compat_ptr(regs.orig_gpr2)); - error = PTR_ERR(filename); - if (IS_ERR(filename)) + filename = getname(compat_ptr(regs->orig_gpr2)); + if (IS_ERR(filename)) { + result = PTR_ERR(filename); goto out; - error = compat_do_execve(filename, compat_ptr(regs.gprs[3]), - compat_ptr(regs.gprs[4]), ®s); - if (error == 0) - { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - current->thread.fp_regs.fpc=0; - asm volatile("sfpc %0,0" : : "d" (0)); } + rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), + compat_ptr(regs->gprs[4]), regs); + if (rc) { + result = rc; + goto out_putname; + } + task_lock(current); + current->ptrace &= ~PT_DTRACE; + task_unlock(current); + current->thread.fp_regs.fpc=0; + asm volatile("sfpc %0,0" : : "d" (0)); + result = regs->gprs[2]; +out_putname: putname(filename); out: - return error; + return result; } @@ -918,19 +923,20 @@ asmlinkage long sys32_write(unsigned int return sys_write(fd, buf, count); } -asmlinkage long sys32_clone(struct pt_regs regs) +asmlinkage long sys32_clone(void) { - unsigned long clone_flags; - unsigned long newsp; + struct pt_regs *regs = task_pt_regs(current); + unsigned long clone_flags; + unsigned long newsp; int __user *parent_tidptr, *child_tidptr; - clone_flags = regs.gprs[3] & 0xffffffffUL; - newsp = regs.orig_gpr2 & 0x7fffffffUL; - parent_tidptr = compat_ptr(regs.gprs[4]); - child_tidptr = compat_ptr(regs.gprs[5]); - if (!newsp) - newsp = regs.gprs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + clone_flags = regs->gprs[3] & 0xffffffffUL; + newsp = regs->orig_gpr2 & 0x7fffffffUL; + parent_tidptr = compat_ptr(regs->gprs[4]); + child_tidptr = compat_ptr(regs->gprs[5]); + if (!newsp) + newsp = regs->gprs[15]; + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 887a988..80a54a0 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -255,9 +255,9 @@ sys32_rt_sigaction(int sig, const struct } asmlinkage long -sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, - struct pt_regs *regs) +sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss) { + struct pt_regs *regs = task_pt_regs(current); stack_t kss, koss; unsigned long ss_sp; int ret, err = 0; @@ -344,8 +344,9 @@ static int restore_sigregs32(struct pt_r return 0; } -asmlinkage long sys32_sigreturn(struct pt_regs *regs) +asmlinkage long sys32_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; sigset_t set; @@ -370,8 +371,9 @@ badframe: return 0; } -asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys32_rt_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; sigset_t set; stack_t st; @@ -407,8 +409,8 @@ asmlinkage long sys32_rt_sigreturn(struc return regs->gprs[2]; badframe: - force_sig(SIGSEGV, current); - return 0; + force_sig(SIGSEGV, current); + return 0; } /* diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index eca3fe5..dca6eaf 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -268,7 +268,7 @@ debug_info_alloc(char *name, int pages_p rc->level = level; rc->buf_size = buf_size; rc->entry_size = sizeof(debug_entry_t) + buf_size; - strlcpy(rc->name, name, sizeof(rc->name)-1); + strlcpy(rc->name, name, sizeof(rc->name)); memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *)); memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS * sizeof(struct dentry*)); diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c new file mode 100644 index 0000000..2d63617 --- /dev/null +++ b/arch/s390/kernel/dis.c @@ -0,0 +1,1268 @@ +/* + * arch/s390/kernel/dis.c + * + * Disassemble s390 instructions. + * + * Copyright IBM Corp. 2007 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_64BIT +#define ONELONG "%08lx: " +#else /* CONFIG_64BIT */ +#define ONELONG "%016lx: " +#endif /* CONFIG_64BIT */ + +#define OPERAND_GPR 0x1 /* Operand printed as %rx */ +#define OPERAND_FPR 0x2 /* Operand printed as %fx */ +#define OPERAND_AR 0x4 /* Operand printed as %ax */ +#define OPERAND_CR 0x8 /* Operand printed as %cx */ +#define OPERAND_DISP 0x10 /* Operand printed as displacement */ +#define OPERAND_BASE 0x20 /* Operand printed as base register */ +#define OPERAND_INDEX 0x40 /* Operand printed as index register */ +#define OPERAND_PCREL 0x80 /* Operand printed as pc-relative symbol */ +#define OPERAND_SIGNED 0x100 /* Operand printed as signed value */ +#define OPERAND_LENGTH 0x200 /* Operand printed as length (+1) */ + +enum { + UNUSED, /* Indicates the end of the operand list */ + R_8, /* GPR starting at position 8 */ + R_12, /* GPR starting at position 12 */ + R_16, /* GPR starting at position 16 */ + R_20, /* GPR starting at position 20 */ + R_24, /* GPR starting at position 24 */ + R_28, /* GPR starting at position 28 */ + R_32, /* GPR starting at position 32 */ + F_8, /* FPR starting at position 8 */ + F_12, /* FPR starting at position 12 */ + F_16, /* FPR starting at position 16 */ + F_20, /* FPR starting at position 16 */ + F_24, /* FPR starting at position 24 */ + F_28, /* FPR starting at position 28 */ + F_32, /* FPR starting at position 32 */ + A_8, /* Access reg. starting at position 8 */ + A_12, /* Access reg. starting at position 12 */ + A_24, /* Access reg. starting at position 24 */ + A_28, /* Access reg. starting at position 28 */ + C_8, /* Control reg. starting at position 8 */ + C_12, /* Control reg. starting at position 12 */ + B_16, /* Base register starting at position 16 */ + B_32, /* Base register starting at position 32 */ + X_12, /* Index register starting at position 12 */ + D_20, /* Displacement starting at position 20 */ + D_36, /* Displacement starting at position 36 */ + D20_20, /* 20 bit displacement starting at 20 */ + L4_8, /* 4 bit length starting at position 8 */ + L4_12, /* 4 bit length starting at position 12 */ + L8_8, /* 8 bit length starting at position 8 */ + U4_8, /* 4 bit unsigned value starting at 8 */ + U4_12, /* 4 bit unsigned value starting at 12 */ + U4_16, /* 4 bit unsigned value starting at 16 */ + U4_20, /* 4 bit unsigned value starting at 20 */ + U8_8, /* 8 bit unsigned value starting at 8 */ + U8_16, /* 8 bit unsigned value starting at 16 */ + I16_16, /* 16 bit signed value starting at 16 */ + U16_16, /* 16 bit unsigned value starting at 16 */ + J16_16, /* PC relative jump offset at 16 */ + J32_16, /* PC relative long offset at 16 */ + I32_16, /* 32 bit signed value starting at 16 */ + U32_16, /* 32 bit unsigned value starting at 16 */ + M_16, /* 4 bit optional mask starting at 16 */ + RO_28, /* optional GPR starting at position 28 */ +}; + +/* + * Enumeration of the different instruction formats. + * For details consult the principles of operation. + */ +enum { + INSTR_INVALID, + INSTR_E, INSTR_RIE_RRP, INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, + INSTR_RIL_UP, INSTR_RI_RI, INSTR_RI_RP, INSTR_RI_RU, INSTR_RI_UP, + INSTR_RRE_00, INSTR_RRE_0R, INSTR_RRE_AA, INSTR_RRE_AR, INSTR_RRE_F0, + INSTR_RRE_FF, INSTR_RRE_R0, INSTR_RRE_RA, INSTR_RRE_RF, INSTR_RRE_RR, + INSTR_RRE_RR_OPT, INSTR_RRF_F0FF, INSTR_RRF_FUFF, INSTR_RRF_M0RR, + INSTR_RRF_R0RR, INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF, + INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR, + INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD, INSTR_RSI_RRP, + INSTR_RSL_R0RD, INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, + INSTR_RSY_RURD, INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, + INSTR_RS_RRRD, INSTR_RS_RURD, INSTR_RXE_FRRD, INSTR_RXE_RRRD, + INSTR_RXF_FRRDF, INSTR_RXY_FRRD, INSTR_RXY_RRRD, INSTR_RX_FRRD, + INSTR_RX_RRRD, INSTR_RX_URRD, INSTR_SIY_URD, INSTR_SI_URD, + INSTR_SSE_RDRD, INSTR_SSF_RRDRD, INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, + INSTR_SS_LLRDRD, INSTR_SS_RRRDRD, INSTR_SS_RRRDRD2, INSTR_SS_RRRDRD3, + INSTR_S_00, INSTR_S_RD, +}; + +struct operand { + int bits; /* The number of bits in the operand. */ + int shift; /* The number of bits to shift. */ + int flags; /* One bit syntax flags. */ +}; + +struct insn { + const char name[5]; + unsigned char opfrag; + unsigned char opmask; + unsigned char format; +}; + +static const struct operand operands[] = +{ + [UNUSED] = { 0, 0, 0 }, + [R_8] = { 4, 8, OPERAND_GPR }, + [R_12] = { 4, 12, OPERAND_GPR }, + [R_16] = { 4, 16, OPERAND_GPR }, + [R_20] = { 4, 20, OPERAND_GPR }, + [R_24] = { 4, 24, OPERAND_GPR }, + [R_28] = { 4, 28, OPERAND_GPR }, + [R_32] = { 4, 32, OPERAND_GPR }, + [F_8] = { 4, 8, OPERAND_FPR }, + [F_12] = { 4, 12, OPERAND_FPR }, + [F_16] = { 4, 16, OPERAND_FPR }, + [F_20] = { 4, 16, OPERAND_FPR }, + [F_24] = { 4, 24, OPERAND_FPR }, + [F_28] = { 4, 28, OPERAND_FPR }, + [F_32] = { 4, 32, OPERAND_FPR }, + [A_8] = { 4, 8, OPERAND_AR }, + [A_12] = { 4, 12, OPERAND_AR }, + [A_24] = { 4, 24, OPERAND_AR }, + [A_28] = { 4, 28, OPERAND_AR }, + [C_8] = { 4, 8, OPERAND_CR }, + [C_12] = { 4, 12, OPERAND_CR }, + [B_16] = { 4, 16, OPERAND_BASE | OPERAND_GPR }, + [B_32] = { 4, 32, OPERAND_BASE | OPERAND_GPR }, + [X_12] = { 4, 12, OPERAND_INDEX | OPERAND_GPR }, + [D_20] = { 12, 20, OPERAND_DISP }, + [D_36] = { 12, 36, OPERAND_DISP }, + [D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED }, + [L4_8] = { 4, 8, OPERAND_LENGTH }, + [L4_12] = { 4, 12, OPERAND_LENGTH }, + [L8_8] = { 8, 8, OPERAND_LENGTH }, + [U4_8] = { 4, 8, 0 }, + [U4_12] = { 4, 12, 0 }, + [U4_16] = { 4, 16, 0 }, + [U4_20] = { 4, 20, 0 }, + [U8_8] = { 8, 8, 0 }, + [U8_16] = { 8, 16, 0 }, + [I16_16] = { 16, 16, OPERAND_SIGNED }, + [U16_16] = { 16, 16, 0 }, + [J16_16] = { 16, 16, OPERAND_PCREL }, + [J32_16] = { 32, 16, OPERAND_PCREL }, + [I32_16] = { 32, 16, OPERAND_SIGNED }, + [U32_16] = { 32, 16, 0 }, + [M_16] = { 4, 16, 0 }, + [RO_28] = { 4, 28, OPERAND_GPR } +}; + +static const unsigned char formats[][6] = { + [INSTR_E] = { 0,0,0,0,0,0 }, /* e.g. pr */ + [INSTR_RIE_RRP] = { R_8,R_12,J16_16,0,0,0 }, /* e.g. brxhg */ + [INSTR_RIL_RP] = { R_8,J32_16,0,0,0,0 }, /* e.g. brasl */ + [INSTR_RIL_UP] = { U4_8,J32_16,0,0,0,0 }, /* e.g. brcl */ + [INSTR_RIL_RI] = { R_8,I32_16,0,0,0,0 }, /* e.g. afi */ + [INSTR_RIL_RU] = { R_8,U32_16,0,0,0,0 }, /* e.g. alfi */ + [INSTR_RI_RI] = { R_8,I16_16,0,0,0,0 }, /* e.g. ahi */ + [INSTR_RI_RP] = { R_8,J16_16,0,0,0,0 }, /* e.g. brct */ + [INSTR_RI_RU] = { R_8,U16_16,0,0,0,0 }, /* e.g. tml */ + [INSTR_RI_UP] = { U4_8,J16_16,0,0,0,0 }, /* e.g. brc */ + [INSTR_RRE_00] = { 0,0,0,0,0,0 }, /* e.g. palb */ + [INSTR_RRE_0R] = { R_28,0,0,0,0,0 }, /* e.g. tb */ + [INSTR_RRE_AA] = { A_24,A_28,0,0,0,0 }, /* e.g. cpya */ + [INSTR_RRE_AR] = { A_24,R_28,0,0,0,0 }, /* e.g. sar */ + [INSTR_RRE_F0] = { F_24,0,0,0,0,0 }, /* e.g. sqer */ + [INSTR_RRE_FF] = { F_24,F_28,0,0,0,0 }, /* e.g. debr */ + [INSTR_RRE_R0] = { R_24,0,0,0,0,0 }, /* e.g. ipm */ + [INSTR_RRE_RA] = { R_24,A_28,0,0,0,0 }, /* e.g. ear */ + [INSTR_RRE_RF] = { R_24,F_28,0,0,0,0 }, /* e.g. cefbr */ + [INSTR_RRE_RR] = { R_24,R_28,0,0,0,0 }, /* e.g. lura */ + [INSTR_RRE_RR_OPT]= { R_24,RO_28,0,0,0,0 }, /* efpc, sfpc */ + [INSTR_RRF_F0FF] = { F_16,F_24,F_28,0,0,0 }, /* e.g. madbr */ + [INSTR_RRF_FUFF] = { F_24,F_16,F_28,U4_20,0,0 }, /* e.g. didbr */ + [INSTR_RRF_RURR] = { R_24,R_28,R_16,U4_20,0,0 }, /* e.g. .insn */ + [INSTR_RRF_R0RR] = { R_24,R_28,R_16,0,0,0 }, /* e.g. idte */ + [INSTR_RRF_U0FF] = { F_24,U4_16,F_28,0,0,0 }, /* e.g. fixr */ + [INSTR_RRF_U0RF] = { R_24,U4_16,F_28,0,0,0 }, /* e.g. cfebr */ + [INSTR_RRF_M0RR] = { R_24,R_28,M_16,0,0,0 }, /* e.g. sske */ + [INSTR_RR_FF] = { F_8,F_12,0,0,0,0 }, /* e.g. adr */ + [INSTR_RR_R0] = { R_8, 0,0,0,0,0 }, /* e.g. spm */ + [INSTR_RR_RR] = { R_8,R_12,0,0,0,0 }, /* e.g. lr */ + [INSTR_RR_U0] = { U8_8, 0,0,0,0,0 }, /* e.g. svc */ + [INSTR_RR_UR] = { U4_8,R_12,0,0,0,0 }, /* e.g. bcr */ + [INSTR_RSE_RRRD] = { R_8,R_12,D_20,B_16,0,0 }, /* e.g. lmh */ + [INSTR_RSE_CCRD] = { C_8,C_12,D_20,B_16,0,0 }, /* e.g. lmh */ + [INSTR_RSE_RURD] = { R_8,U4_12,D_20,B_16,0,0 }, /* e.g. icmh */ + [INSTR_RSL_R0RD] = { R_8,D_20,B_16,0,0,0 }, /* e.g. tp */ + [INSTR_RSI_RRP] = { R_8,R_12,J16_16,0,0,0 }, /* e.g. brxh */ + [INSTR_RSY_RRRD] = { R_8,R_12,D20_20,B_16,0,0 }, /* e.g. stmy */ + [INSTR_RSY_RURD] = { R_8,U4_12,D20_20,B_16,0,0 }, /* e.g. icmh */ + [INSTR_RSY_AARD] = { A_8,A_12,D20_20,B_16,0,0 }, /* e.g. lamy */ + [INSTR_RSY_CCRD] = { C_8,C_12,D20_20,B_16,0,0 }, /* e.g. lamy */ + [INSTR_RS_AARD] = { A_8,A_12,D_20,B_16,0,0 }, /* e.g. lam */ + [INSTR_RS_CCRD] = { C_8,C_12,D_20,B_16,0,0 }, /* e.g. lctl */ + [INSTR_RS_R0RD] = { R_8,D_20,B_16,0,0,0 }, /* e.g. sll */ + [INSTR_RS_RRRD] = { R_8,R_12,D_20,B_16,0,0 }, /* e.g. cs */ + [INSTR_RS_RURD] = { R_8,U4_12,D_20,B_16,0,0 }, /* e.g. icm */ + [INSTR_RXE_FRRD] = { F_8,D_20,X_12,B_16,0,0 }, /* e.g. axbr */ + [INSTR_RXE_RRRD] = { R_8,D_20,X_12,B_16,0,0 }, /* e.g. lg */ + [INSTR_RXF_FRRDF] = { F_32,F_8,D_20,X_12,B_16,0 }, /* e.g. madb */ + [INSTR_RXY_RRRD] = { R_8,D20_20,X_12,B_16,0,0 }, /* e.g. ly */ + [INSTR_RXY_FRRD] = { F_8,D20_20,X_12,B_16,0,0 }, /* e.g. ley */ + [INSTR_RX_FRRD] = { F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */ + [INSTR_RX_RRRD] = { R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */ + [INSTR_RX_URRD] = { U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */ + [INSTR_SI_URD] = { D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */ + [INSTR_SIY_URD] = { D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */ + [INSTR_SSE_RDRD] = { D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */ + [INSTR_SS_L0RDRD] = { D_20,L8_8,B_16,D_36,B_32,0 }, /* e.g. mvc */ + [INSTR_SS_LIRDRD] = { D_20,L4_8,B_16,D_36,B_32,U4_12 },/* e.g. srp */ + [INSTR_SS_LLRDRD] = { D_20,L4_8,B_16,D_36,L4_12,B_32 },/* e.g. pack */ + [INSTR_SS_RRRDRD] = { D_20,R_8,B_16,D_36,B_32,R_12 }, /* e.g. mvck */ + [INSTR_SS_RRRDRD2]= { R_8,D_20,B_16,R_12,D_36,B_32 }, /* e.g. plo */ + [INSTR_SS_RRRDRD3]= { R_8,R_12,D_20,B_16,D_36,B_32 }, /* e.g. lmd */ + [INSTR_S_00] = { 0,0,0,0,0,0 }, /* e.g. hsch */ + [INSTR_S_RD] = { D_20,B_16,0,0,0,0 }, /* e.g. lpsw */ + [INSTR_SSF_RRDRD] = { D_20,B_16,D_36,B_32,R_8,0 }, /* e.g. mvcos */ +}; + +static struct insn opcode[] = { +#ifdef CONFIG_64BIT + { "lmd", 0xef, 0xff, INSTR_SS_RRRDRD3 }, +#endif + { "spm", 0x04, 0xff, INSTR_RR_R0 }, + { "balr", 0x05, 0xff, INSTR_RR_RR }, + { "bctr", 0x06, 0xff, INSTR_RR_RR }, + { "bcr", 0x07, 0xff, INSTR_RR_UR }, + { "svc", 0x0a, 0xff, INSTR_RR_U0 }, + { "bsm", 0x0b, 0xff, INSTR_RR_RR }, + { "bassm", 0x0c, 0xff, INSTR_RR_RR }, + { "basr", 0x0d, 0xff, INSTR_RR_RR }, + { "mvcl", 0x0e, 0xff, INSTR_RR_RR }, + { "clcl", 0x0f, 0xff, INSTR_RR_RR }, + { "lpr", 0x10, 0xff, INSTR_RR_RR }, + { "lnr", 0x11, 0xff, INSTR_RR_RR }, + { "ltr", 0x12, 0xff, INSTR_RR_RR }, + { "lcr", 0x13, 0xff, INSTR_RR_RR }, + { "nr", 0x14, 0xff, INSTR_RR_RR }, + { "clr", 0x15, 0xff, INSTR_RR_RR }, + { "or", 0x16, 0xff, INSTR_RR_RR }, + { "xr", 0x17, 0xff, INSTR_RR_RR }, + { "lr", 0x18, 0xff, INSTR_RR_RR }, + { "cr", 0x19, 0xff, INSTR_RR_RR }, + { "ar", 0x1a, 0xff, INSTR_RR_RR }, + { "sr", 0x1b, 0xff, INSTR_RR_RR }, + { "mr", 0x1c, 0xff, INSTR_RR_RR }, + { "dr", 0x1d, 0xff, INSTR_RR_RR }, + { "alr", 0x1e, 0xff, INSTR_RR_RR }, + { "slr", 0x1f, 0xff, INSTR_RR_RR }, + { "lpdr", 0x20, 0xff, INSTR_RR_FF }, + { "lndr", 0x21, 0xff, INSTR_RR_FF }, + { "ltdr", 0x22, 0xff, INSTR_RR_FF }, + { "lcdr", 0x23, 0xff, INSTR_RR_FF }, + { "hdr", 0x24, 0xff, INSTR_RR_FF }, + { "ldxr", 0x25, 0xff, INSTR_RR_FF }, + { "lrdr", 0x25, 0xff, INSTR_RR_FF }, + { "mxr", 0x26, 0xff, INSTR_RR_FF }, + { "mxdr", 0x27, 0xff, INSTR_RR_FF }, + { "ldr", 0x28, 0xff, INSTR_RR_FF }, + { "cdr", 0x29, 0xff, INSTR_RR_FF }, + { "adr", 0x2a, 0xff, INSTR_RR_FF }, + { "sdr", 0x2b, 0xff, INSTR_RR_FF }, + { "mdr", 0x2c, 0xff, INSTR_RR_FF }, + { "ddr", 0x2d, 0xff, INSTR_RR_FF }, + { "awr", 0x2e, 0xff, INSTR_RR_FF }, + { "swr", 0x2f, 0xff, INSTR_RR_FF }, + { "lper", 0x30, 0xff, INSTR_RR_FF }, + { "lner", 0x31, 0xff, INSTR_RR_FF }, + { "lter", 0x32, 0xff, INSTR_RR_FF }, + { "lcer", 0x33, 0xff, INSTR_RR_FF }, + { "her", 0x34, 0xff, INSTR_RR_FF }, + { "ledr", 0x35, 0xff, INSTR_RR_FF }, + { "lrer", 0x35, 0xff, INSTR_RR_FF }, + { "axr", 0x36, 0xff, INSTR_RR_FF }, + { "sxr", 0x37, 0xff, INSTR_RR_FF }, + { "ler", 0x38, 0xff, INSTR_RR_FF }, + { "cer", 0x39, 0xff, INSTR_RR_FF }, + { "aer", 0x3a, 0xff, INSTR_RR_FF }, + { "ser", 0x3b, 0xff, INSTR_RR_FF }, + { "mder", 0x3c, 0xff, INSTR_RR_FF }, + { "mer", 0x3c, 0xff, INSTR_RR_FF }, + { "der", 0x3d, 0xff, INSTR_RR_FF }, + { "aur", 0x3e, 0xff, INSTR_RR_FF }, + { "sur", 0x3f, 0xff, INSTR_RR_FF }, + { "sth", 0x40, 0xff, INSTR_RX_RRRD }, + { "la", 0x41, 0xff, INSTR_RX_RRRD }, + { "stc", 0x42, 0xff, INSTR_RX_RRRD }, + { "ic", 0x43, 0xff, INSTR_RX_RRRD }, + { "ex", 0x44, 0xff, INSTR_RX_RRRD }, + { "bal", 0x45, 0xff, INSTR_RX_RRRD }, + { "bct", 0x46, 0xff, INSTR_RX_RRRD }, + { "bc", 0x47, 0xff, INSTR_RX_URRD }, + { "lh", 0x48, 0xff, INSTR_RX_RRRD }, + { "ch", 0x49, 0xff, INSTR_RX_RRRD }, + { "ah", 0x4a, 0xff, INSTR_RX_RRRD }, + { "sh", 0x4b, 0xff, INSTR_RX_RRRD }, + { "mh", 0x4c, 0xff, INSTR_RX_RRRD }, + { "bas", 0x4d, 0xff, INSTR_RX_RRRD }, + { "cvd", 0x4e, 0xff, INSTR_RX_RRRD }, + { "cvb", 0x4f, 0xff, INSTR_RX_RRRD }, + { "st", 0x50, 0xff, INSTR_RX_RRRD }, + { "lae", 0x51, 0xff, INSTR_RX_RRRD }, + { "n", 0x54, 0xff, INSTR_RX_RRRD }, + { "cl", 0x55, 0xff, INSTR_RX_RRRD }, + { "o", 0x56, 0xff, INSTR_RX_RRRD }, + { "x", 0x57, 0xff, INSTR_RX_RRRD }, + { "l", 0x58, 0xff, INSTR_RX_RRRD }, + { "c", 0x59, 0xff, INSTR_RX_RRRD }, + { "a", 0x5a, 0xff, INSTR_RX_RRRD }, + { "s", 0x5b, 0xff, INSTR_RX_RRRD }, + { "m", 0x5c, 0xff, INSTR_RX_RRRD }, + { "d", 0x5d, 0xff, INSTR_RX_RRRD }, + { "al", 0x5e, 0xff, INSTR_RX_RRRD }, + { "sl", 0x5f, 0xff, INSTR_RX_RRRD }, + { "std", 0x60, 0xff, INSTR_RX_FRRD }, + { "mxd", 0x67, 0xff, INSTR_RX_FRRD }, + { "ld", 0x68, 0xff, INSTR_RX_FRRD }, + { "cd", 0x69, 0xff, INSTR_RX_FRRD }, + { "ad", 0x6a, 0xff, INSTR_RX_FRRD }, + { "sd", 0x6b, 0xff, INSTR_RX_FRRD }, + { "md", 0x6c, 0xff, INSTR_RX_FRRD }, + { "dd", 0x6d, 0xff, INSTR_RX_FRRD }, + { "aw", 0x6e, 0xff, INSTR_RX_FRRD }, + { "sw", 0x6f, 0xff, INSTR_RX_FRRD }, + { "ste", 0x70, 0xff, INSTR_RX_FRRD }, + { "ms", 0x71, 0xff, INSTR_RX_RRRD }, + { "le", 0x78, 0xff, INSTR_RX_FRRD }, + { "ce", 0x79, 0xff, INSTR_RX_FRRD }, + { "ae", 0x7a, 0xff, INSTR_RX_FRRD }, + { "se", 0x7b, 0xff, INSTR_RX_FRRD }, + { "mde", 0x7c, 0xff, INSTR_RX_FRRD }, + { "me", 0x7c, 0xff, INSTR_RX_FRRD }, + { "de", 0x7d, 0xff, INSTR_RX_FRRD }, + { "au", 0x7e, 0xff, INSTR_RX_FRRD }, + { "su", 0x7f, 0xff, INSTR_RX_FRRD }, + { "ssm", 0x80, 0xff, INSTR_S_RD }, + { "lpsw", 0x82, 0xff, INSTR_S_RD }, + { "diag", 0x83, 0xff, INSTR_RS_RRRD }, + { "brxh", 0x84, 0xff, INSTR_RSI_RRP }, + { "brxle", 0x85, 0xff, INSTR_RSI_RRP }, + { "bxh", 0x86, 0xff, INSTR_RS_RRRD }, + { "bxle", 0x87, 0xff, INSTR_RS_RRRD }, + { "srl", 0x88, 0xff, INSTR_RS_R0RD }, + { "sll", 0x89, 0xff, INSTR_RS_R0RD }, + { "sra", 0x8a, 0xff, INSTR_RS_R0RD }, + { "sla", 0x8b, 0xff, INSTR_RS_R0RD }, + { "srdl", 0x8c, 0xff, INSTR_RS_R0RD }, + { "sldl", 0x8d, 0xff, INSTR_RS_R0RD }, + { "srda", 0x8e, 0xff, INSTR_RS_R0RD }, + { "slda", 0x8f, 0xff, INSTR_RS_R0RD }, + { "stm", 0x90, 0xff, INSTR_RS_RRRD }, + { "tm", 0x91, 0xff, INSTR_SI_URD }, + { "mvi", 0x92, 0xff, INSTR_SI_URD }, + { "ts", 0x93, 0xff, INSTR_S_RD }, + { "ni", 0x94, 0xff, INSTR_SI_URD }, + { "cli", 0x95, 0xff, INSTR_SI_URD }, + { "oi", 0x96, 0xff, INSTR_SI_URD }, + { "xi", 0x97, 0xff, INSTR_SI_URD }, + { "lm", 0x98, 0xff, INSTR_RS_RRRD }, + { "trace", 0x99, 0xff, INSTR_RS_RRRD }, + { "lam", 0x9a, 0xff, INSTR_RS_AARD }, + { "stam", 0x9b, 0xff, INSTR_RS_AARD }, + { "mvcle", 0xa8, 0xff, INSTR_RS_RRRD }, + { "clcle", 0xa9, 0xff, INSTR_RS_RRRD }, + { "stnsm", 0xac, 0xff, INSTR_SI_URD }, + { "stosm", 0xad, 0xff, INSTR_SI_URD }, + { "sigp", 0xae, 0xff, INSTR_RS_RRRD }, + { "mc", 0xaf, 0xff, INSTR_SI_URD }, + { "lra", 0xb1, 0xff, INSTR_RX_RRRD }, + { "stctl", 0xb6, 0xff, INSTR_RS_CCRD }, + { "lctl", 0xb7, 0xff, INSTR_RS_CCRD }, + { "cs", 0xba, 0xff, INSTR_RS_RRRD }, + { "cds", 0xbb, 0xff, INSTR_RS_RRRD }, + { "clm", 0xbd, 0xff, INSTR_RS_RURD }, + { "stcm", 0xbe, 0xff, INSTR_RS_RURD }, + { "icm", 0xbf, 0xff, INSTR_RS_RURD }, + { "mvn", 0xd1, 0xff, INSTR_SS_L0RDRD }, + { "mvc", 0xd2, 0xff, INSTR_SS_L0RDRD }, + { "mvz", 0xd3, 0xff, INSTR_SS_L0RDRD }, + { "nc", 0xd4, 0xff, INSTR_SS_L0RDRD }, + { "clc", 0xd5, 0xff, INSTR_SS_L0RDRD }, + { "oc", 0xd6, 0xff, INSTR_SS_L0RDRD }, + { "xc", 0xd7, 0xff, INSTR_SS_L0RDRD }, + { "mvck", 0xd9, 0xff, INSTR_SS_RRRDRD }, + { "mvcp", 0xda, 0xff, INSTR_SS_RRRDRD }, + { "mvcs", 0xdb, 0xff, INSTR_SS_RRRDRD }, + { "tr", 0xdc, 0xff, INSTR_SS_L0RDRD }, + { "trt", 0xdd, 0xff, INSTR_SS_L0RDRD }, + { "ed", 0xde, 0xff, INSTR_SS_L0RDRD }, + { "edmk", 0xdf, 0xff, INSTR_SS_L0RDRD }, + { "pku", 0xe1, 0xff, INSTR_SS_L0RDRD }, + { "unpku", 0xe2, 0xff, INSTR_SS_L0RDRD }, + { "mvcin", 0xe8, 0xff, INSTR_SS_L0RDRD }, + { "pka", 0xe9, 0xff, INSTR_SS_L0RDRD }, + { "unpka", 0xea, 0xff, INSTR_SS_L0RDRD }, + { "plo", 0xee, 0xff, INSTR_SS_RRRDRD2 }, + { "srp", 0xf0, 0xff, INSTR_SS_LIRDRD }, + { "mvo", 0xf1, 0xff, INSTR_SS_LLRDRD }, + { "pack", 0xf2, 0xff, INSTR_SS_LLRDRD }, + { "unpk", 0xf3, 0xff, INSTR_SS_LLRDRD }, + { "zap", 0xf8, 0xff, INSTR_SS_LLRDRD }, + { "cp", 0xf9, 0xff, INSTR_SS_LLRDRD }, + { "ap", 0xfa, 0xff, INSTR_SS_LLRDRD }, + { "sp", 0xfb, 0xff, INSTR_SS_LLRDRD }, + { "mp", 0xfc, 0xff, INSTR_SS_LLRDRD }, + { "dp", 0xfd, 0xff, INSTR_SS_LLRDRD }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_01[] = { +#ifdef CONFIG_64BIT + { "sam64", 0x0e, 0xff, INSTR_E }, +#endif + { "pr", 0x01, 0xff, INSTR_E }, + { "upt", 0x02, 0xff, INSTR_E }, + { "sckpf", 0x07, 0xff, INSTR_E }, + { "tam", 0x0b, 0xff, INSTR_E }, + { "sam24", 0x0c, 0xff, INSTR_E }, + { "sam31", 0x0d, 0xff, INSTR_E }, + { "trap2", 0xff, 0xff, INSTR_E }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_a5[] = { +#ifdef CONFIG_64BIT + { "iihh", 0x00, 0x0f, INSTR_RI_RU }, + { "iihl", 0x01, 0x0f, INSTR_RI_RU }, + { "iilh", 0x02, 0x0f, INSTR_RI_RU }, + { "iill", 0x03, 0x0f, INSTR_RI_RU }, + { "nihh", 0x04, 0x0f, INSTR_RI_RU }, + { "nihl", 0x05, 0x0f, INSTR_RI_RU }, + { "nilh", 0x06, 0x0f, INSTR_RI_RU }, + { "nill", 0x07, 0x0f, INSTR_RI_RU }, + { "oihh", 0x08, 0x0f, INSTR_RI_RU }, + { "oihl", 0x09, 0x0f, INSTR_RI_RU }, + { "oilh", 0x0a, 0x0f, INSTR_RI_RU }, + { "oill", 0x0b, 0x0f, INSTR_RI_RU }, + { "llihh", 0x0c, 0x0f, INSTR_RI_RU }, + { "llihl", 0x0d, 0x0f, INSTR_RI_RU }, + { "llilh", 0x0e, 0x0f, INSTR_RI_RU }, + { "llill", 0x0f, 0x0f, INSTR_RI_RU }, +#endif + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_a7[] = { +#ifdef CONFIG_64BIT + { "tmhh", 0x02, 0x0f, INSTR_RI_RU }, + { "tmhl", 0x03, 0x0f, INSTR_RI_RU }, + { "brctg", 0x07, 0x0f, INSTR_RI_RP }, + { "lghi", 0x09, 0x0f, INSTR_RI_RI }, + { "aghi", 0x0b, 0x0f, INSTR_RI_RI }, + { "mghi", 0x0d, 0x0f, INSTR_RI_RI }, + { "cghi", 0x0f, 0x0f, INSTR_RI_RI }, +#endif + { "tmlh", 0x00, 0x0f, INSTR_RI_RU }, + { "tmll", 0x01, 0x0f, INSTR_RI_RU }, + { "brc", 0x04, 0x0f, INSTR_RI_UP }, + { "bras", 0x05, 0x0f, INSTR_RI_RP }, + { "brct", 0x06, 0x0f, INSTR_RI_RP }, + { "lhi", 0x08, 0x0f, INSTR_RI_RI }, + { "ahi", 0x0a, 0x0f, INSTR_RI_RI }, + { "mhi", 0x0c, 0x0f, INSTR_RI_RI }, + { "chi", 0x0e, 0x0f, INSTR_RI_RI }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_b2[] = { +#ifdef CONFIG_64BIT + { "sske", 0x2b, 0xff, INSTR_RRF_M0RR }, + { "stckf", 0x7c, 0xff, INSTR_S_RD }, + { "cu21", 0xa6, 0xff, INSTR_RRF_M0RR }, + { "cuutf", 0xa6, 0xff, INSTR_RRF_M0RR }, + { "cu12", 0xa7, 0xff, INSTR_RRF_M0RR }, + { "cutfu", 0xa7, 0xff, INSTR_RRF_M0RR }, + { "stfle", 0xb0, 0xff, INSTR_S_RD }, + { "lpswe", 0xb2, 0xff, INSTR_S_RD }, +#endif + { "stidp", 0x02, 0xff, INSTR_S_RD }, + { "sck", 0x04, 0xff, INSTR_S_RD }, + { "stck", 0x05, 0xff, INSTR_S_RD }, + { "sckc", 0x06, 0xff, INSTR_S_RD }, + { "stckc", 0x07, 0xff, INSTR_S_RD }, + { "spt", 0x08, 0xff, INSTR_S_RD }, + { "stpt", 0x09, 0xff, INSTR_S_RD }, + { "spka", 0x0a, 0xff, INSTR_S_RD }, + { "ipk", 0x0b, 0xff, INSTR_S_00 }, + { "ptlb", 0x0d, 0xff, INSTR_S_00 }, + { "spx", 0x10, 0xff, INSTR_S_RD }, + { "stpx", 0x11, 0xff, INSTR_S_RD }, + { "stap", 0x12, 0xff, INSTR_S_RD }, + { "sie", 0x14, 0xff, INSTR_S_RD }, + { "pc", 0x18, 0xff, INSTR_S_RD }, + { "sac", 0x19, 0xff, INSTR_S_RD }, + { "cfc", 0x1a, 0xff, INSTR_S_RD }, + { "ipte", 0x21, 0xff, INSTR_RRE_RR }, + { "ipm", 0x22, 0xff, INSTR_RRE_R0 }, + { "ivsk", 0x23, 0xff, INSTR_RRE_RR }, + { "iac", 0x24, 0xff, INSTR_RRE_R0 }, + { "ssar", 0x25, 0xff, INSTR_RRE_R0 }, + { "epar", 0x26, 0xff, INSTR_RRE_R0 }, + { "esar", 0x27, 0xff, INSTR_RRE_R0 }, + { "pt", 0x28, 0xff, INSTR_RRE_RR }, + { "iske", 0x29, 0xff, INSTR_RRE_RR }, + { "rrbe", 0x2a, 0xff, INSTR_RRE_RR }, + { "sske", 0x2b, 0xff, INSTR_RRE_RR }, + { "tb", 0x2c, 0xff, INSTR_RRE_0R }, + { "dxr", 0x2d, 0xff, INSTR_RRE_F0 }, + { "pgin", 0x2e, 0xff, INSTR_RRE_RR }, + { "pgout", 0x2f, 0xff, INSTR_RRE_RR }, + { "csch", 0x30, 0xff, INSTR_S_00 }, + { "hsch", 0x31, 0xff, INSTR_S_00 }, + { "msch", 0x32, 0xff, INSTR_S_RD }, + { "ssch", 0x33, 0xff, INSTR_S_RD }, + { "stsch", 0x34, 0xff, INSTR_S_RD }, + { "tsch", 0x35, 0xff, INSTR_S_RD }, + { "tpi", 0x36, 0xff, INSTR_S_RD }, + { "sal", 0x37, 0xff, INSTR_S_00 }, + { "rsch", 0x38, 0xff, INSTR_S_00 }, + { "stcrw", 0x39, 0xff, INSTR_S_RD }, + { "stcps", 0x3a, 0xff, INSTR_S_RD }, + { "rchp", 0x3b, 0xff, INSTR_S_00 }, + { "schm", 0x3c, 0xff, INSTR_S_00 }, + { "bakr", 0x40, 0xff, INSTR_RRE_RR }, + { "cksm", 0x41, 0xff, INSTR_RRE_RR }, + { "sqdr", 0x44, 0xff, INSTR_RRE_F0 }, + { "sqer", 0x45, 0xff, INSTR_RRE_F0 }, + { "stura", 0x46, 0xff, INSTR_RRE_RR }, + { "msta", 0x47, 0xff, INSTR_RRE_R0 }, + { "palb", 0x48, 0xff, INSTR_RRE_00 }, + { "ereg", 0x49, 0xff, INSTR_RRE_RR }, + { "esta", 0x4a, 0xff, INSTR_RRE_RR }, + { "lura", 0x4b, 0xff, INSTR_RRE_RR }, + { "tar", 0x4c, 0xff, INSTR_RRE_AR }, + { "cpya", 0x4d, 0xff, INSTR_RRE_AA }, + { "sar", 0x4e, 0xff, INSTR_RRE_AR }, + { "ear", 0x4f, 0xff, INSTR_RRE_RA }, + { "csp", 0x50, 0xff, INSTR_RRE_RR }, + { "msr", 0x52, 0xff, INSTR_RRE_RR }, + { "mvpg", 0x54, 0xff, INSTR_RRE_RR }, + { "mvst", 0x55, 0xff, INSTR_RRE_RR }, + { "cuse", 0x57, 0xff, INSTR_RRE_RR }, + { "bsg", 0x58, 0xff, INSTR_RRE_RR }, + { "bsa", 0x5a, 0xff, INSTR_RRE_RR }, + { "clst", 0x5d, 0xff, INSTR_RRE_RR }, + { "srst", 0x5e, 0xff, INSTR_RRE_RR }, + { "cmpsc", 0x63, 0xff, INSTR_RRE_RR }, + { "cmpsc", 0x63, 0xff, INSTR_RRE_RR }, + { "siga", 0x74, 0xff, INSTR_S_RD }, + { "xsch", 0x76, 0xff, INSTR_S_00 }, + { "rp", 0x77, 0xff, INSTR_S_RD }, + { "stcke", 0x78, 0xff, INSTR_S_RD }, + { "sacf", 0x79, 0xff, INSTR_S_RD }, + { "stsi", 0x7d, 0xff, INSTR_S_RD }, + { "srnm", 0x99, 0xff, INSTR_S_RD }, + { "stfpc", 0x9c, 0xff, INSTR_S_RD }, + { "lfpc", 0x9d, 0xff, INSTR_S_RD }, + { "tre", 0xa5, 0xff, INSTR_RRE_RR }, + { "cuutf", 0xa6, 0xff, INSTR_RRE_RR }, + { "cutfu", 0xa7, 0xff, INSTR_RRE_RR }, + { "stfl", 0xb1, 0xff, INSTR_S_RD }, + { "trap4", 0xff, 0xff, INSTR_S_RD }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_b3[] = { +#ifdef CONFIG_64BIT + { "maylr", 0x38, 0xff, INSTR_RRF_F0FF }, + { "mylr", 0x39, 0xff, INSTR_RRF_F0FF }, + { "mayr", 0x3a, 0xff, INSTR_RRF_F0FF }, + { "myr", 0x3b, 0xff, INSTR_RRF_F0FF }, + { "mayhr", 0x3c, 0xff, INSTR_RRF_F0FF }, + { "myhr", 0x3d, 0xff, INSTR_RRF_F0FF }, + { "cegbr", 0xa4, 0xff, INSTR_RRE_RR }, + { "cdgbr", 0xa5, 0xff, INSTR_RRE_RR }, + { "cxgbr", 0xa6, 0xff, INSTR_RRE_RR }, + { "cgebr", 0xa8, 0xff, INSTR_RRF_U0RF }, + { "cgdbr", 0xa9, 0xff, INSTR_RRF_U0RF }, + { "cgxbr", 0xaa, 0xff, INSTR_RRF_U0RF }, + { "cfer", 0xb8, 0xff, INSTR_RRF_U0RF }, + { "cfdr", 0xb9, 0xff, INSTR_RRF_U0RF }, + { "cfxr", 0xba, 0xff, INSTR_RRF_U0RF }, + { "cegr", 0xc4, 0xff, INSTR_RRE_RR }, + { "cdgr", 0xc5, 0xff, INSTR_RRE_RR }, + { "cxgr", 0xc6, 0xff, INSTR_RRE_RR }, + { "cger", 0xc8, 0xff, INSTR_RRF_U0RF }, + { "cgdr", 0xc9, 0xff, INSTR_RRF_U0RF }, + { "cgxr", 0xca, 0xff, INSTR_RRF_U0RF }, +#endif + { "lpebr", 0x00, 0xff, INSTR_RRE_FF }, + { "lnebr", 0x01, 0xff, INSTR_RRE_FF }, + { "ltebr", 0x02, 0xff, INSTR_RRE_FF }, + { "lcebr", 0x03, 0xff, INSTR_RRE_FF }, + { "ldebr", 0x04, 0xff, INSTR_RRE_FF }, + { "lxdbr", 0x05, 0xff, INSTR_RRE_FF }, + { "lxebr", 0x06, 0xff, INSTR_RRE_FF }, + { "mxdbr", 0x07, 0xff, INSTR_RRE_FF }, + { "kebr", 0x08, 0xff, INSTR_RRE_FF }, + { "cebr", 0x09, 0xff, INSTR_RRE_FF }, + { "aebr", 0x0a, 0xff, INSTR_RRE_FF }, + { "sebr", 0x0b, 0xff, INSTR_RRE_FF }, + { "mdebr", 0x0c, 0xff, INSTR_RRE_FF }, + { "debr", 0x0d, 0xff, INSTR_RRE_FF }, + { "maebr", 0x0e, 0xff, INSTR_RRF_F0FF }, + { "msebr", 0x0f, 0xff, INSTR_RRF_F0FF }, + { "lpdbr", 0x10, 0xff, INSTR_RRE_FF }, + { "lndbr", 0x11, 0xff, INSTR_RRE_FF }, + { "ltdbr", 0x12, 0xff, INSTR_RRE_FF }, + { "lcdbr", 0x13, 0xff, INSTR_RRE_FF }, + { "sqebr", 0x14, 0xff, INSTR_RRE_FF }, + { "sqdbr", 0x15, 0xff, INSTR_RRE_FF }, + { "sqxbr", 0x16, 0xff, INSTR_RRE_FF }, + { "meebr", 0x17, 0xff, INSTR_RRE_FF }, + { "kdbr", 0x18, 0xff, INSTR_RRE_FF }, + { "cdbr", 0x19, 0xff, INSTR_RRE_FF }, + { "adbr", 0x1a, 0xff, INSTR_RRE_FF }, + { "sdbr", 0x1b, 0xff, INSTR_RRE_FF }, + { "mdbr", 0x1c, 0xff, INSTR_RRE_FF }, + { "ddbr", 0x1d, 0xff, INSTR_RRE_FF }, + { "madbr", 0x1e, 0xff, INSTR_RRF_F0FF }, + { "msdbr", 0x1f, 0xff, INSTR_RRF_F0FF }, + { "lder", 0x24, 0xff, INSTR_RRE_FF }, + { "lxdr", 0x25, 0xff, INSTR_RRE_FF }, + { "lxer", 0x26, 0xff, INSTR_RRE_FF }, + { "maer", 0x2e, 0xff, INSTR_RRF_F0FF }, + { "mser", 0x2f, 0xff, INSTR_RRF_F0FF }, + { "sqxr", 0x36, 0xff, INSTR_RRE_FF }, + { "meer", 0x37, 0xff, INSTR_RRE_FF }, + { "madr", 0x3e, 0xff, INSTR_RRF_F0FF }, + { "msdr", 0x3f, 0xff, INSTR_RRF_F0FF }, + { "lpxbr", 0x40, 0xff, INSTR_RRE_FF }, + { "lnxbr", 0x41, 0xff, INSTR_RRE_FF }, + { "ltxbr", 0x42, 0xff, INSTR_RRE_FF }, + { "lcxbr", 0x43, 0xff, INSTR_RRE_FF }, + { "ledbr", 0x44, 0xff, INSTR_RRE_FF }, + { "ldxbr", 0x45, 0xff, INSTR_RRE_FF }, + { "lexbr", 0x46, 0xff, INSTR_RRE_FF }, + { "fixbr", 0x47, 0xff, INSTR_RRF_U0FF }, + { "kxbr", 0x48, 0xff, INSTR_RRE_FF }, + { "cxbr", 0x49, 0xff, INSTR_RRE_FF }, + { "axbr", 0x4a, 0xff, INSTR_RRE_FF }, + { "sxbr", 0x4b, 0xff, INSTR_RRE_FF }, + { "mxbr", 0x4c, 0xff, INSTR_RRE_FF }, + { "dxbr", 0x4d, 0xff, INSTR_RRE_FF }, + { "tbedr", 0x50, 0xff, INSTR_RRF_U0FF }, + { "tbdr", 0x51, 0xff, INSTR_RRF_U0FF }, + { "diebr", 0x53, 0xff, INSTR_RRF_FUFF }, + { "fiebr", 0x57, 0xff, INSTR_RRF_U0FF }, + { "thder", 0x58, 0xff, INSTR_RRE_RR }, + { "thdr", 0x59, 0xff, INSTR_RRE_RR }, + { "didbr", 0x5b, 0xff, INSTR_RRF_FUFF }, + { "fidbr", 0x5f, 0xff, INSTR_RRF_U0FF }, + { "lpxr", 0x60, 0xff, INSTR_RRE_FF }, + { "lnxr", 0x61, 0xff, INSTR_RRE_FF }, + { "ltxr", 0x62, 0xff, INSTR_RRE_FF }, + { "lcxr", 0x63, 0xff, INSTR_RRE_FF }, + { "lxr", 0x65, 0xff, INSTR_RRE_RR }, + { "lexr", 0x66, 0xff, INSTR_RRE_FF }, + { "fixr", 0x67, 0xff, INSTR_RRF_U0FF }, + { "cxr", 0x69, 0xff, INSTR_RRE_FF }, + { "lzer", 0x74, 0xff, INSTR_RRE_R0 }, + { "lzdr", 0x75, 0xff, INSTR_RRE_R0 }, + { "lzxr", 0x76, 0xff, INSTR_RRE_R0 }, + { "fier", 0x77, 0xff, INSTR_RRF_U0FF }, + { "fidr", 0x7f, 0xff, INSTR_RRF_U0FF }, + { "sfpc", 0x84, 0xff, INSTR_RRE_RR_OPT }, + { "efpc", 0x8c, 0xff, INSTR_RRE_RR_OPT }, + { "cefbr", 0x94, 0xff, INSTR_RRE_RF }, + { "cdfbr", 0x95, 0xff, INSTR_RRE_RF }, + { "cxfbr", 0x96, 0xff, INSTR_RRE_RF }, + { "cfebr", 0x98, 0xff, INSTR_RRF_U0RF }, + { "cfdbr", 0x99, 0xff, INSTR_RRF_U0RF }, + { "cfxbr", 0x9a, 0xff, INSTR_RRF_U0RF }, + { "cefr", 0xb4, 0xff, INSTR_RRE_RF }, + { "cdfr", 0xb5, 0xff, INSTR_RRE_RF }, + { "cxfr", 0xb6, 0xff, INSTR_RRE_RF }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_b9[] = { +#ifdef CONFIG_64BIT + { "lpgr", 0x00, 0xff, INSTR_RRE_RR }, + { "lngr", 0x01, 0xff, INSTR_RRE_RR }, + { "ltgr", 0x02, 0xff, INSTR_RRE_RR }, + { "lcgr", 0x03, 0xff, INSTR_RRE_RR }, + { "lgr", 0x04, 0xff, INSTR_RRE_RR }, + { "lurag", 0x05, 0xff, INSTR_RRE_RR }, + { "lgbr", 0x06, 0xff, INSTR_RRE_RR }, + { "lghr", 0x07, 0xff, INSTR_RRE_RR }, + { "agr", 0x08, 0xff, INSTR_RRE_RR }, + { "sgr", 0x09, 0xff, INSTR_RRE_RR }, + { "algr", 0x0a, 0xff, INSTR_RRE_RR }, + { "slgr", 0x0b, 0xff, INSTR_RRE_RR }, + { "msgr", 0x0c, 0xff, INSTR_RRE_RR }, + { "dsgr", 0x0d, 0xff, INSTR_RRE_RR }, + { "eregg", 0x0e, 0xff, INSTR_RRE_RR }, + { "lrvgr", 0x0f, 0xff, INSTR_RRE_RR }, + { "lpgfr", 0x10, 0xff, INSTR_RRE_RR }, + { "lngfr", 0x11, 0xff, INSTR_RRE_RR }, + { "ltgfr", 0x12, 0xff, INSTR_RRE_RR }, + { "lcgfr", 0x13, 0xff, INSTR_RRE_RR }, + { "lgfr", 0x14, 0xff, INSTR_RRE_RR }, + { "llgfr", 0x16, 0xff, INSTR_RRE_RR }, + { "llgtr", 0x17, 0xff, INSTR_RRE_RR }, + { "agfr", 0x18, 0xff, INSTR_RRE_RR }, + { "sgfr", 0x19, 0xff, INSTR_RRE_RR }, + { "algfr", 0x1a, 0xff, INSTR_RRE_RR }, + { "slgfr", 0x1b, 0xff, INSTR_RRE_RR }, + { "msgfr", 0x1c, 0xff, INSTR_RRE_RR }, + { "dsgfr", 0x1d, 0xff, INSTR_RRE_RR }, + { "cgr", 0x20, 0xff, INSTR_RRE_RR }, + { "clgr", 0x21, 0xff, INSTR_RRE_RR }, + { "sturg", 0x25, 0xff, INSTR_RRE_RR }, + { "lbr", 0x26, 0xff, INSTR_RRE_RR }, + { "lhr", 0x27, 0xff, INSTR_RRE_RR }, + { "cgfr", 0x30, 0xff, INSTR_RRE_RR }, + { "clgfr", 0x31, 0xff, INSTR_RRE_RR }, + { "bctgr", 0x46, 0xff, INSTR_RRE_RR }, + { "ngr", 0x80, 0xff, INSTR_RRE_RR }, + { "ogr", 0x81, 0xff, INSTR_RRE_RR }, + { "xgr", 0x82, 0xff, INSTR_RRE_RR }, + { "flogr", 0x83, 0xff, INSTR_RRE_RR }, + { "llgcr", 0x84, 0xff, INSTR_RRE_RR }, + { "llghr", 0x85, 0xff, INSTR_RRE_RR }, + { "mlgr", 0x86, 0xff, INSTR_RRE_RR }, + { "dlgr", 0x87, 0xff, INSTR_RRE_RR }, + { "alcgr", 0x88, 0xff, INSTR_RRE_RR }, + { "slbgr", 0x89, 0xff, INSTR_RRE_RR }, + { "cspg", 0x8a, 0xff, INSTR_RRE_RR }, + { "idte", 0x8e, 0xff, INSTR_RRF_R0RR }, + { "llcr", 0x94, 0xff, INSTR_RRE_RR }, + { "llhr", 0x95, 0xff, INSTR_RRE_RR }, + { "esea", 0x9d, 0xff, INSTR_RRE_R0 }, + { "lptea", 0xaa, 0xff, INSTR_RRF_RURR }, + { "cu14", 0xb0, 0xff, INSTR_RRF_M0RR }, + { "cu24", 0xb1, 0xff, INSTR_RRF_M0RR }, + { "cu41", 0xb2, 0xff, INSTR_RRF_M0RR }, + { "cu42", 0xb3, 0xff, INSTR_RRF_M0RR }, +#endif + { "kmac", 0x1e, 0xff, INSTR_RRE_RR }, + { "lrvr", 0x1f, 0xff, INSTR_RRE_RR }, + { "km", 0x2e, 0xff, INSTR_RRE_RR }, + { "kmc", 0x2f, 0xff, INSTR_RRE_RR }, + { "kimd", 0x3e, 0xff, INSTR_RRE_RR }, + { "klmd", 0x3f, 0xff, INSTR_RRE_RR }, + { "epsw", 0x8d, 0xff, INSTR_RRE_RR }, + { "trtt", 0x90, 0xff, INSTR_RRE_RR }, + { "trtt", 0x90, 0xff, INSTR_RRF_M0RR }, + { "trto", 0x91, 0xff, INSTR_RRE_RR }, + { "trto", 0x91, 0xff, INSTR_RRF_M0RR }, + { "trot", 0x92, 0xff, INSTR_RRE_RR }, + { "trot", 0x92, 0xff, INSTR_RRF_M0RR }, + { "troo", 0x93, 0xff, INSTR_RRE_RR }, + { "troo", 0x93, 0xff, INSTR_RRF_M0RR }, + { "mlr", 0x96, 0xff, INSTR_RRE_RR }, + { "dlr", 0x97, 0xff, INSTR_RRE_RR }, + { "alcr", 0x98, 0xff, INSTR_RRE_RR }, + { "slbr", 0x99, 0xff, INSTR_RRE_RR }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_c0[] = { +#ifdef CONFIG_64BIT + { "lgfi", 0x01, 0x0f, INSTR_RIL_RI }, + { "xihf", 0x06, 0x0f, INSTR_RIL_RU }, + { "xilf", 0x07, 0x0f, INSTR_RIL_RU }, + { "iihf", 0x08, 0x0f, INSTR_RIL_RU }, + { "iilf", 0x09, 0x0f, INSTR_RIL_RU }, + { "nihf", 0x0a, 0x0f, INSTR_RIL_RU }, + { "nilf", 0x0b, 0x0f, INSTR_RIL_RU }, + { "oihf", 0x0c, 0x0f, INSTR_RIL_RU }, + { "oilf", 0x0d, 0x0f, INSTR_RIL_RU }, + { "llihf", 0x0e, 0x0f, INSTR_RIL_RU }, + { "llilf", 0x0f, 0x0f, INSTR_RIL_RU }, +#endif + { "larl", 0x00, 0x0f, INSTR_RIL_RP }, + { "brcl", 0x04, 0x0f, INSTR_RIL_UP }, + { "brasl", 0x05, 0x0f, INSTR_RIL_RP }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_c2[] = { +#ifdef CONFIG_64BIT + { "slgfi", 0x04, 0x0f, INSTR_RIL_RU }, + { "slfi", 0x05, 0x0f, INSTR_RIL_RU }, + { "agfi", 0x08, 0x0f, INSTR_RIL_RI }, + { "afi", 0x09, 0x0f, INSTR_RIL_RI }, + { "algfi", 0x0a, 0x0f, INSTR_RIL_RU }, + { "alfi", 0x0b, 0x0f, INSTR_RIL_RU }, + { "cgfi", 0x0c, 0x0f, INSTR_RIL_RI }, + { "cfi", 0x0d, 0x0f, INSTR_RIL_RI }, + { "clgfi", 0x0e, 0x0f, INSTR_RIL_RU }, + { "clfi", 0x0f, 0x0f, INSTR_RIL_RU }, +#endif + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_c8[] = { +#ifdef CONFIG_64BIT + { "mvcos", 0x00, 0xff, INSTR_SSF_RRDRD }, +#endif + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_e3[] = { +#ifdef CONFIG_64BIT + { "ltg", 0x02, 0xff, INSTR_RXY_RRRD }, + { "lrag", 0x03, 0xff, INSTR_RXY_RRRD }, + { "lg", 0x04, 0xff, INSTR_RXY_RRRD }, + { "cvby", 0x06, 0xff, INSTR_RXY_RRRD }, + { "ag", 0x08, 0xff, INSTR_RXY_RRRD }, + { "sg", 0x09, 0xff, INSTR_RXY_RRRD }, + { "alg", 0x0a, 0xff, INSTR_RXY_RRRD }, + { "slg", 0x0b, 0xff, INSTR_RXY_RRRD }, + { "msg", 0x0c, 0xff, INSTR_RXY_RRRD }, + { "dsg", 0x0d, 0xff, INSTR_RXY_RRRD }, + { "cvbg", 0x0e, 0xff, INSTR_RXY_RRRD }, + { "lrvg", 0x0f, 0xff, INSTR_RXY_RRRD }, + { "lt", 0x12, 0xff, INSTR_RXY_RRRD }, + { "lray", 0x13, 0xff, INSTR_RXY_RRRD }, + { "lgf", 0x14, 0xff, INSTR_RXY_RRRD }, + { "lgh", 0x15, 0xff, INSTR_RXY_RRRD }, + { "llgf", 0x16, 0xff, INSTR_RXY_RRRD }, + { "llgt", 0x17, 0xff, INSTR_RXY_RRRD }, + { "agf", 0x18, 0xff, INSTR_RXY_RRRD }, + { "sgf", 0x19, 0xff, INSTR_RXY_RRRD }, + { "algf", 0x1a, 0xff, INSTR_RXY_RRRD }, + { "slgf", 0x1b, 0xff, INSTR_RXY_RRRD }, + { "msgf", 0x1c, 0xff, INSTR_RXY_RRRD }, + { "dsgf", 0x1d, 0xff, INSTR_RXY_RRRD }, + { "cg", 0x20, 0xff, INSTR_RXY_RRRD }, + { "clg", 0x21, 0xff, INSTR_RXY_RRRD }, + { "stg", 0x24, 0xff, INSTR_RXY_RRRD }, + { "cvdy", 0x26, 0xff, INSTR_RXY_RRRD }, + { "cvdg", 0x2e, 0xff, INSTR_RXY_RRRD }, + { "strvg", 0x2f, 0xff, INSTR_RXY_RRRD }, + { "cgf", 0x30, 0xff, INSTR_RXY_RRRD }, + { "clgf", 0x31, 0xff, INSTR_RXY_RRRD }, + { "strvh", 0x3f, 0xff, INSTR_RXY_RRRD }, + { "bctg", 0x46, 0xff, INSTR_RXY_RRRD }, + { "sty", 0x50, 0xff, INSTR_RXY_RRRD }, + { "msy", 0x51, 0xff, INSTR_RXY_RRRD }, + { "ny", 0x54, 0xff, INSTR_RXY_RRRD }, + { "cly", 0x55, 0xff, INSTR_RXY_RRRD }, + { "oy", 0x56, 0xff, INSTR_RXY_RRRD }, + { "xy", 0x57, 0xff, INSTR_RXY_RRRD }, + { "ly", 0x58, 0xff, INSTR_RXY_RRRD }, + { "cy", 0x59, 0xff, INSTR_RXY_RRRD }, + { "ay", 0x5a, 0xff, INSTR_RXY_RRRD }, + { "sy", 0x5b, 0xff, INSTR_RXY_RRRD }, + { "aly", 0x5e, 0xff, INSTR_RXY_RRRD }, + { "sly", 0x5f, 0xff, INSTR_RXY_RRRD }, + { "sthy", 0x70, 0xff, INSTR_RXY_RRRD }, + { "lay", 0x71, 0xff, INSTR_RXY_RRRD }, + { "stcy", 0x72, 0xff, INSTR_RXY_RRRD }, + { "icy", 0x73, 0xff, INSTR_RXY_RRRD }, + { "lb", 0x76, 0xff, INSTR_RXY_RRRD }, + { "lgb", 0x77, 0xff, INSTR_RXY_RRRD }, + { "lhy", 0x78, 0xff, INSTR_RXY_RRRD }, + { "chy", 0x79, 0xff, INSTR_RXY_RRRD }, + { "ahy", 0x7a, 0xff, INSTR_RXY_RRRD }, + { "shy", 0x7b, 0xff, INSTR_RXY_RRRD }, + { "ng", 0x80, 0xff, INSTR_RXY_RRRD }, + { "og", 0x81, 0xff, INSTR_RXY_RRRD }, + { "xg", 0x82, 0xff, INSTR_RXY_RRRD }, + { "mlg", 0x86, 0xff, INSTR_RXY_RRRD }, + { "dlg", 0x87, 0xff, INSTR_RXY_RRRD }, + { "alcg", 0x88, 0xff, INSTR_RXY_RRRD }, + { "slbg", 0x89, 0xff, INSTR_RXY_RRRD }, + { "stpq", 0x8e, 0xff, INSTR_RXY_RRRD }, + { "lpq", 0x8f, 0xff, INSTR_RXY_RRRD }, + { "llgc", 0x90, 0xff, INSTR_RXY_RRRD }, + { "llgh", 0x91, 0xff, INSTR_RXY_RRRD }, + { "llc", 0x94, 0xff, INSTR_RXY_RRRD }, + { "llh", 0x95, 0xff, INSTR_RXY_RRRD }, +#endif + { "lrv", 0x1e, 0xff, INSTR_RXY_RRRD }, + { "lrvh", 0x1f, 0xff, INSTR_RXY_RRRD }, + { "strv", 0x3e, 0xff, INSTR_RXY_RRRD }, + { "ml", 0x96, 0xff, INSTR_RXY_RRRD }, + { "dl", 0x97, 0xff, INSTR_RXY_RRRD }, + { "alc", 0x98, 0xff, INSTR_RXY_RRRD }, + { "slb", 0x99, 0xff, INSTR_RXY_RRRD }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_e5[] = { +#ifdef CONFIG_64BIT + { "strag", 0x02, 0xff, INSTR_SSE_RDRD }, +#endif + { "lasp", 0x00, 0xff, INSTR_SSE_RDRD }, + { "tprot", 0x01, 0xff, INSTR_SSE_RDRD }, + { "mvcsk", 0x0e, 0xff, INSTR_SSE_RDRD }, + { "mvcdk", 0x0f, 0xff, INSTR_SSE_RDRD }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_eb[] = { +#ifdef CONFIG_64BIT + { "lmg", 0x04, 0xff, INSTR_RSY_RRRD }, + { "srag", 0x0a, 0xff, INSTR_RSY_RRRD }, + { "slag", 0x0b, 0xff, INSTR_RSY_RRRD }, + { "srlg", 0x0c, 0xff, INSTR_RSY_RRRD }, + { "sllg", 0x0d, 0xff, INSTR_RSY_RRRD }, + { "tracg", 0x0f, 0xff, INSTR_RSY_RRRD }, + { "csy", 0x14, 0xff, INSTR_RSY_RRRD }, + { "rllg", 0x1c, 0xff, INSTR_RSY_RRRD }, + { "clmh", 0x20, 0xff, INSTR_RSY_RURD }, + { "clmy", 0x21, 0xff, INSTR_RSY_RURD }, + { "stmg", 0x24, 0xff, INSTR_RSY_RRRD }, + { "stctg", 0x25, 0xff, INSTR_RSY_CCRD }, + { "stmh", 0x26, 0xff, INSTR_RSY_RRRD }, + { "stcmh", 0x2c, 0xff, INSTR_RSY_RURD }, + { "stcmy", 0x2d, 0xff, INSTR_RSY_RURD }, + { "lctlg", 0x2f, 0xff, INSTR_RSY_CCRD }, + { "csg", 0x30, 0xff, INSTR_RSY_RRRD }, + { "cdsy", 0x31, 0xff, INSTR_RSY_RRRD }, + { "cdsg", 0x3e, 0xff, INSTR_RSY_RRRD }, + { "bxhg", 0x44, 0xff, INSTR_RSY_RRRD }, + { "bxleg", 0x45, 0xff, INSTR_RSY_RRRD }, + { "tmy", 0x51, 0xff, INSTR_SIY_URD }, + { "mviy", 0x52, 0xff, INSTR_SIY_URD }, + { "niy", 0x54, 0xff, INSTR_SIY_URD }, + { "cliy", 0x55, 0xff, INSTR_SIY_URD }, + { "oiy", 0x56, 0xff, INSTR_SIY_URD }, + { "xiy", 0x57, 0xff, INSTR_SIY_URD }, + { "icmh", 0x80, 0xff, INSTR_RSE_RURD }, + { "icmh", 0x80, 0xff, INSTR_RSY_RURD }, + { "icmy", 0x81, 0xff, INSTR_RSY_RURD }, + { "clclu", 0x8f, 0xff, INSTR_RSY_RRRD }, + { "stmy", 0x90, 0xff, INSTR_RSY_RRRD }, + { "lmh", 0x96, 0xff, INSTR_RSY_RRRD }, + { "lmy", 0x98, 0xff, INSTR_RSY_RRRD }, + { "lamy", 0x9a, 0xff, INSTR_RSY_AARD }, + { "stamy", 0x9b, 0xff, INSTR_RSY_AARD }, +#endif + { "rll", 0x1d, 0xff, INSTR_RSY_RRRD }, + { "mvclu", 0x8e, 0xff, INSTR_RSY_RRRD }, + { "tp", 0xc0, 0xff, INSTR_RSL_R0RD }, + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_ec[] = { +#ifdef CONFIG_64BIT + { "brxhg", 0x44, 0x0f, INSTR_RIE_RRP }, + { "brxlg", 0x45, 0x0f, INSTR_RIE_RRP }, +#endif + { "", 0, 0, INSTR_INVALID } +}; + +static struct insn opcode_ed[] = { +#ifdef CONFIG_64BIT + { "mayl", 0x38, 0xff, INSTR_RXF_FRRDF }, + { "myl", 0x39, 0xff, INSTR_RXF_FRRDF }, + { "may", 0x3a, 0xff, INSTR_RXF_FRRDF }, + { "my", 0x3b, 0xff, INSTR_RXF_FRRDF }, + { "mayh", 0x3c, 0xff, INSTR_RXF_FRRDF }, + { "myh", 0x3d, 0xff, INSTR_RXF_FRRDF }, + { "ley", 0x64, 0xff, INSTR_RXY_FRRD }, + { "ldy", 0x65, 0xff, INSTR_RXY_FRRD }, + { "stey", 0x66, 0xff, INSTR_RXY_FRRD }, + { "stdy", 0x67, 0xff, INSTR_RXY_FRRD }, +#endif + { "ldeb", 0x04, 0xff, INSTR_RXE_FRRD }, + { "lxdb", 0x05, 0xff, INSTR_RXE_FRRD }, + { "lxeb", 0x06, 0xff, INSTR_RXE_FRRD }, + { "mxdb", 0x07, 0xff, INSTR_RXE_FRRD }, + { "keb", 0x08, 0xff, INSTR_RXE_FRRD }, + { "ceb", 0x09, 0xff, INSTR_RXE_FRRD }, + { "aeb", 0x0a, 0xff, INSTR_RXE_FRRD }, + { "seb", 0x0b, 0xff, INSTR_RXE_FRRD }, + { "mdeb", 0x0c, 0xff, INSTR_RXE_FRRD }, + { "deb", 0x0d, 0xff, INSTR_RXE_FRRD }, + { "maeb", 0x0e, 0xff, INSTR_RXF_FRRDF }, + { "mseb", 0x0f, 0xff, INSTR_RXF_FRRDF }, + { "tceb", 0x10, 0xff, INSTR_RXE_FRRD }, + { "tcdb", 0x11, 0xff, INSTR_RXE_FRRD }, + { "tcxb", 0x12, 0xff, INSTR_RXE_FRRD }, + { "sqeb", 0x14, 0xff, INSTR_RXE_FRRD }, + { "sqdb", 0x15, 0xff, INSTR_RXE_FRRD }, + { "meeb", 0x17, 0xff, INSTR_RXE_FRRD }, + { "kdb", 0x18, 0xff, INSTR_RXE_FRRD }, + { "cdb", 0x19, 0xff, INSTR_RXE_FRRD }, + { "adb", 0x1a, 0xff, INSTR_RXE_FRRD }, + { "sdb", 0x1b, 0xff, INSTR_RXE_FRRD }, + { "mdb", 0x1c, 0xff, INSTR_RXE_FRRD }, + { "ddb", 0x1d, 0xff, INSTR_RXE_FRRD }, + { "madb", 0x1e, 0xff, INSTR_RXF_FRRDF }, + { "msdb", 0x1f, 0xff, INSTR_RXF_FRRDF }, + { "lde", 0x24, 0xff, INSTR_RXE_FRRD }, + { "lxd", 0x25, 0xff, INSTR_RXE_FRRD }, + { "lxe", 0x26, 0xff, INSTR_RXE_FRRD }, + { "mae", 0x2e, 0xff, INSTR_RXF_FRRDF }, + { "mse", 0x2f, 0xff, INSTR_RXF_FRRDF }, + { "sqe", 0x34, 0xff, INSTR_RXE_FRRD }, + { "mee", 0x37, 0xff, INSTR_RXE_FRRD }, + { "mad", 0x3e, 0xff, INSTR_RXF_FRRDF }, + { "msd", 0x3f, 0xff, INSTR_RXF_FRRDF }, + { "", 0, INSTR_INVALID } +}; + +/* Extracts an operand value from an instruction. */ +static unsigned int extract_operand(unsigned char *code, + const struct operand *operand) +{ + unsigned int val; + int bits; + + /* Extract fragments of the operand byte for byte. */ + code += operand->shift / 8; + bits = (operand->shift & 7) + operand->bits; + val = 0; + do { + val <<= 8; + val |= (unsigned int) *code++; + bits -= 8; + } while (bits > 0); + val >>= -bits; + val &= ((1U << (operand->bits - 1)) << 1) - 1; + + /* Check for special long displacement case. */ + if (operand->bits == 20 && operand->shift == 20) + val = (val & 0xff) << 12 | (val & 0xfff00) >> 8; + + /* Sign extend value if the operand is signed or pc relative. */ + if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) && + (val & (1U << (operand->bits - 1)))) + val |= (-1U << (operand->bits - 1)) << 1; + + /* Double value if the operand is pc relative. */ + if (operand->flags & OPERAND_PCREL) + val <<= 1; + + /* Length x in an instructions has real length x + 1. */ + if (operand->flags & OPERAND_LENGTH) + val++; + return val; +} + +static inline int insn_length(unsigned char code) +{ + return ((((int) code + 64) >> 7) + 1) << 1; +} + +static struct insn *find_insn(unsigned char *code) +{ + unsigned char opfrag = code[1]; + struct insn *table; + + switch (code[0]) { + case 0x01: + table = opcode_01; + break; + case 0xa5: + table = opcode_a5; + break; + case 0xa7: + table = opcode_a7; + break; + case 0xb2: + table = opcode_b2; + break; + case 0xb3: + table = opcode_b3; + break; + case 0xb9: + table = opcode_b9; + break; + case 0xc0: + table = opcode_c0; + break; + case 0xc2: + table = opcode_c2; + break; + case 0xc8: + table = opcode_c8; + break; + case 0xe3: + table = opcode_e3; + opfrag = code[5]; + break; + case 0xe5: + table = opcode_e5; + break; + case 0xeb: + table = opcode_eb; + opfrag = code[5]; + break; + case 0xec: + table = opcode_ec; + opfrag = code[5]; + break; + case 0xed: + table = opcode_ed; + opfrag = code[5]; + break; + default: + table = opcode; + opfrag = code[0]; + break; + } + while (table->format != INSTR_INVALID) { + if (table->opfrag == (opfrag & table->opmask)) + return table; + table++; + } + return NULL; +} + +static int print_insn(char *buffer, unsigned char *code, unsigned long addr) +{ + struct insn *insn; + const unsigned char *ops; + const struct operand *operand; + unsigned int value; + char separator; + char *ptr; + + ptr = buffer; + insn = find_insn(code); + if (insn) { + ptr += sprintf(ptr, "%.5s\t", insn->name); + /* Extract the operands. */ + separator = 0; + for (ops = formats[insn->format]; *ops != 0; ops++) { + operand = operands + *ops; + value = extract_operand(code, operand); + if ((operand->flags & OPERAND_INDEX) && value == 0) + continue; + if ((operand->flags & OPERAND_BASE) && + value == 0 && separator == '(') { + separator = ','; + continue; + } + if (separator) + ptr += sprintf(ptr, "%c", separator); + if (operand->flags & OPERAND_GPR) + ptr += sprintf(ptr, "%%r%i", value); + else if (operand->flags & OPERAND_FPR) + ptr += sprintf(ptr, "%%f%i", value); + else if (operand->flags & OPERAND_AR) + ptr += sprintf(ptr, "%%a%i", value); + else if (operand->flags & OPERAND_CR) + ptr += sprintf(ptr, "%%c%i", value); + else if (operand->flags & OPERAND_PCREL) + ptr += sprintf(ptr, "%lx", value + addr); + else if (operand->flags & OPERAND_SIGNED) + ptr += sprintf(ptr, "%i", value); + else + ptr += sprintf(ptr, "%u", value); + if (operand->flags & OPERAND_DISP) + separator = '('; + else if (operand->flags & OPERAND_BASE) { + ptr += sprintf(ptr, ")"); + separator = ','; + } else + separator = ','; + } + } else + ptr += sprintf(ptr, "unknown"); + return (int) (ptr - buffer); +} + +void show_code(struct pt_regs *regs) +{ + char *mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl"; + unsigned char code[64]; + char buffer[64], *ptr; + mm_segment_t old_fs; + unsigned long addr; + int start, end, opsize, hops, i; + + /* Get a snapshot of the 64 bytes surrounding the fault address. */ + old_fs = get_fs(); + set_fs((regs->psw.mask & PSW_MASK_PSTATE) ? USER_DS : KERNEL_DS); + for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) { + addr = regs->psw.addr - 34 + start; + if (__copy_from_user(code + start - 2, + (char __user *) addr, 2)) + break; + } + for (end = 32; end < 64; end += 2) { + addr = regs->psw.addr + end - 32; + if (__copy_from_user(code + end, + (char __user *) addr, 2)) + break; + } + set_fs(old_fs); + /* Code snapshot useable ? */ + if ((regs->psw.addr & 1) || start >= end) { + printk("%s Code: Bad PSW.\n", mode); + return; + } + /* Find a starting point for the disassembly. */ + while (start < 32) { + hops = 0; + for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) { + if (!find_insn(code + start + i)) + break; + i += insn_length(code[start + i]); + } + if (start + i == 32) + /* Looks good, sequence ends at PSW. */ + break; + start += 2; + } + /* Decode the instructions. */ + ptr = buffer; + ptr += sprintf(ptr, "%s Code:", mode); + hops = 0; + while (start < end && hops < 8) { + *ptr++ = (start == 32) ? '>' : ' '; + addr = regs->psw.addr + start - 32; + ptr += sprintf(ptr, ONELONG, addr); + opsize = insn_length(code[start]); + if (start + opsize >= end) + break; + for (i = 0; i < opsize; i++) + ptr += sprintf(ptr, "%02x", code[start + i]); + *ptr++ = '\t'; + if (i < 6) + *ptr++ = '\t'; + ptr += print_insn(ptr, code + start, addr); + start += opsize; + printk(buffer); + ptr = buffer; + ptr += sprintf(ptr, "\n "); + hops++; + } + printk("\n"); +} diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index afca1c6..5e47936 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -141,9 +141,9 @@ static noinline __init void detect_machi machine_flags |= 4; } +#ifdef CONFIG_64BIT static noinline __init int memory_fast_detect(void) { - unsigned long val0 = 0; unsigned long val1 = 0xc; int ret = -ENOSYS; @@ -161,9 +161,15 @@ static noinline __init int memory_fast_d if (ret || val0 != val1) return -ENOSYS; - memory_chunk[0].size = val0; + memory_chunk[0].size = val0 + 1; return 0; } +#else +static inline int memory_fast_detect(void) +{ + return -ENOSYS; +} +#endif #define ADDR2G (1UL << 31) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index dddc3de..c8a2212 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -249,8 +249,6 @@ sysc_do_restart: bnz BASED(sysc_tracesys) basr %r14,%r8 # call sys_xxxx st %r2,SP_R2(%r15) # store return value (change R2 on stack) - # ATTENTION: check sys_execve_glue before - # changing anything here !! sysc_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -381,50 +379,37 @@ ret_from_fork: b BASED(sysc_return) # -# clone, fork, vfork, exec and sigreturn need glue, -# because they all expect pt_regs as parameter, -# but are called with different parameter. -# return-address is set up above +# kernel_execve function needs to deal with pt_regs that is not +# at the usual place # -sys_clone_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lclone) - br %r1 # branch to sys_clone - -sys_fork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lfork) - br %r1 # branch to sys_fork - -sys_vfork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lvfork) - br %r1 # branch to sys_vfork - -sys_execve_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - l %r1,BASED(.Lexecve) - lr %r12,%r14 # save return address - basr %r14,%r1 # call sys_execve - ltr %r2,%r2 # check if execve failed - bnz 0(%r12) # it did fail -> store result in gpr2 - b 4(%r12) # SKIP ST 2,SP_R2(15) after BASR 14,8 - # in system_call/sysc_tracesys - -sys_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,BASED(.Lsigreturn) - br %r1 # branch to sys_sigreturn - -sys_rt_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,BASED(.Lrt_sigreturn) - br %r1 # branch to sys_sigreturn - -sys_sigaltstack_glue: - la %r4,SP_PTREGS(%r15) # load pt_regs as parameter - l %r1,BASED(.Lsigaltstack) - br %r1 # branch to sys_sigreturn + .globl kernel_execve +kernel_execve: + stm %r12,%r15,48(%r15) + lr %r14,%r15 + l %r13,__LC_SVC_NEW_PSW+4 + s %r15,BASED(.Lc_spsize) + st %r14,__SF_BACKCHAIN(%r15) + la %r12,SP_PTREGS(%r15) + xc 0(__PT_SIZE,%r12),0(%r12) + l %r1,BASED(.Ldo_execve) + lr %r5,%r12 + basr %r14,%r1 + ltr %r2,%r2 + be BASED(0f) + a %r15,BASED(.Lc_spsize) + lm %r12,%r15,48(%r15) + br %r14 + # execve succeeded. +0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts + l %r15,__LC_KERNEL_STACK # load ksp + s %r15,BASED(.Lc_spsize) # make room for registers & psw + l %r9,__LC_THREAD_INFO + mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + l %r1,BASED(.Lexecve_tail) + basr %r14,%r1 + b BASED(sysc_return) /* * Program check handler routine @@ -1031,19 +1016,11 @@ #endif .Ldo_extint: .long do_extint .Ldo_signal: .long do_signal .Lhandle_per: .long do_single_step +.Ldo_execve: .long do_execve +.Lexecve_tail: .long execve_tail .Ljump_table: .long pgm_check_table .Lschedule: .long schedule -.Lclone: .long sys_clone -.Lexecve: .long sys_execve -.Lfork: .long sys_fork -.Lrt_sigreturn: .long sys_rt_sigreturn -.Lrt_sigsuspend: - .long sys_rt_sigsuspend -.Lsigreturn: .long sys_sigreturn -.Lsigsuspend: .long sys_sigsuspend -.Lsigaltstack: .long sys_sigaltstack .Ltrace: .long syscall_trace -.Lvfork: .long sys_vfork .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 0f758c3..93745fd 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -244,8 +244,6 @@ #endif jnz sysc_tracesys basr %r14,%r8 # call sys_xxxx stg %r2,SP_R2(%r15) # store return value (change R2 on stack) - # ATTENTION: check sys_execve_glue before - # changing anything here !! sysc_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -371,77 +369,35 @@ ret_from_fork: j sysc_return # -# clone, fork, vfork, exec and sigreturn need glue, -# because they all expect pt_regs as parameter, -# but are called with different parameter. -# return-address is set up above +# kernel_execve function needs to deal with pt_regs that is not +# at the usual place # -sys_clone_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys_clone # branch to sys_clone - -#ifdef CONFIG_COMPAT -sys32_clone_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys32_clone # branch to sys32_clone -#endif - -sys_fork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys_fork # branch to sys_fork - -sys_vfork_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - jg sys_vfork # branch to sys_vfork - -sys_execve_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - lgr %r12,%r14 # save return address - brasl %r14,sys_execve # call sys_execve - ltgr %r2,%r2 # check if execve failed - bnz 0(%r12) # it did fail -> store result in gpr2 - b 6(%r12) # SKIP STG 2,SP_R2(15) in - # system_call/sysc_tracesys -#ifdef CONFIG_COMPAT -sys32_execve_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs - lgr %r12,%r14 # save return address - brasl %r14,sys32_execve # call sys32_execve - ltgr %r2,%r2 # check if execve failed - bnz 0(%r12) # it did fail -> store result in gpr2 - b 6(%r12) # SKIP STG 2,SP_R2(15) in - # system_call/sysc_tracesys -#endif - -sys_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys_sigreturn # branch to sys_sigreturn - -#ifdef CONFIG_COMPAT -sys32_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys32_sigreturn # branch to sys32_sigreturn -#endif - -sys_rt_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys_rt_sigreturn # branch to sys_sigreturn - -#ifdef CONFIG_COMPAT -sys32_rt_sigreturn_glue: - la %r2,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys32_rt_sigreturn # branch to sys32_sigreturn -#endif - -sys_sigaltstack_glue: - la %r4,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys_sigaltstack # branch to sys_sigreturn - -#ifdef CONFIG_COMPAT -sys32_sigaltstack_glue: - la %r4,SP_PTREGS(%r15) # load pt_regs as parameter - jg sys32_sigaltstack_wrapper # branch to sys_sigreturn -#endif + .globl kernel_execve +kernel_execve: + stmg %r12,%r15,96(%r15) + lgr %r14,%r15 + aghi %r15,-SP_SIZE + stg %r14,__SF_BACKCHAIN(%r15) + la %r12,SP_PTREGS(%r15) + xc 0(__PT_SIZE,%r12),0(%r12) + lgr %r5,%r12 + brasl %r14,do_execve + ltgfr %r2,%r2 + je 0f + aghi %r15,SP_SIZE + lmg %r12,%r15,96(%r15) + br %r14 + # execve succeeded. +0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts + lg %r15,__LC_KERNEL_STACK # load ksp + aghi %r15,-SP_SIZE # make room for registers & psw + lg %r13,__LC_SVC_NEW_PSW+8 + lg %r9,__LC_THREAD_INFO + mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + brasl %r14,execve_tail + j sysc_return /* * Program check handler routine diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index d125a4e..bb57de8 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -47,7 +47,7 @@ #define IPL_NSS_STR "nss" * Must be in data section since the bss section * is not cleared when these are accessed. */ -u16 ipl_devno __attribute__((__section__(".data"))) = 0; +static u16 ipl_devno __attribute__((__section__(".data"))) = 0; u32 ipl_flags __attribute__((__section__(".data"))) = 0; static char *ipl_type_str(enum ipl_type type) @@ -1039,6 +1039,27 @@ static int __init s390_ipl_init(void) __initcall(s390_ipl_init); +void __init ipl_save_parameters(void) +{ + struct cio_iplinfo iplinfo; + unsigned int *ipl_ptr; + void *src, *dst; + + if (cio_get_iplinfo(&iplinfo)) + return; + + ipl_devno = iplinfo.devno; + ipl_flags |= IPL_DEVNO_VALID; + if (!iplinfo.is_qdio) + return; + ipl_flags |= IPL_PARMBLOCK_VALID; + ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR; + src = (void *)(unsigned long)*ipl_ptr; + dst = (void *)IPL_PARMBLOCK_ORIGIN; + memmove(dst, src, PAGE_SIZE); + *ipl_ptr = IPL_PARMBLOCK_ORIGIN; +} + static LIST_HEAD(rcall); static DEFINE_MUTEX(rcall_mutex); diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index 39d1dd7..59b4e79 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -31,6 +31,7 @@ #include #include #include #include +#include #if 0 #define DEBUGP printk @@ -398,9 +399,10 @@ int module_finalize(const Elf_Ehdr *hdr, struct module *me) { vfree(me->arch.syminfo); - return 0; + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { + module_bug_cleanup(mod); } diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5acfac6..11d9b01 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -280,24 +280,26 @@ #endif /* CONFIG_64BIT */ return 0; } -asmlinkage long sys_fork(struct pt_regs regs) +asmlinkage long sys_fork(void) { - return do_fork(SIGCHLD, regs.gprs[15], ®s, 0, NULL, NULL); + struct pt_regs *regs = task_pt_regs(current); + return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } -asmlinkage long sys_clone(struct pt_regs regs) +asmlinkage long sys_clone(void) { - unsigned long clone_flags; - unsigned long newsp; + struct pt_regs *regs = task_pt_regs(current); + unsigned long clone_flags; + unsigned long newsp; int __user *parent_tidptr, *child_tidptr; - clone_flags = regs.gprs[3]; - newsp = regs.orig_gpr2; - parent_tidptr = (int __user *) regs.gprs[4]; - child_tidptr = (int __user *) regs.gprs[5]; - if (!newsp) - newsp = regs.gprs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + clone_flags = regs->gprs[3]; + newsp = regs->orig_gpr2; + parent_tidptr = (int __user *) regs->gprs[4]; + child_tidptr = (int __user *) regs->gprs[5]; + if (!newsp) + newsp = regs->gprs[15]; + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } @@ -311,40 +313,52 @@ asmlinkage long sys_clone(struct pt_regs * do not have enough call-clobbered registers to hold all * the information you need. */ -asmlinkage long sys_vfork(struct pt_regs regs) +asmlinkage long sys_vfork(void) { + struct pt_regs *regs = task_pt_regs(current); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - regs.gprs[15], ®s, 0, NULL, NULL); + regs->gprs[15], regs, 0, NULL, NULL); +} + +asmlinkage void execve_tail(void) +{ + task_lock(current); + current->ptrace &= ~PT_DTRACE; + task_unlock(current); + current->thread.fp_regs.fpc = 0; + if (MACHINE_HAS_IEEE) + asm volatile("sfpc %0,%0" : : "d" (0)); } /* * sys_execve() executes a new program. */ -asmlinkage long sys_execve(struct pt_regs regs) +asmlinkage long sys_execve(void) { - int error; - char * filename; - - filename = getname((char __user *) regs.orig_gpr2); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, (char __user * __user *) regs.gprs[3], - (char __user * __user *) regs.gprs[4], ®s); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - current->thread.fp_regs.fpc = 0; - if (MACHINE_HAS_IEEE) - asm volatile("sfpc %0,%0" : : "d" (0)); + struct pt_regs *regs = task_pt_regs(current); + char *filename; + unsigned long result; + int rc; + + filename = getname((char __user *) regs->orig_gpr2); + if (IS_ERR(filename)) { + result = PTR_ERR(filename); + goto out; } - putname(filename); + rc = do_execve(filename, (char __user * __user *) regs->gprs[3], + (char __user * __user *) regs->gprs[4], regs); + if (rc) { + result = rc; + goto out_putname; + } + execve_tail(); + result = regs->gprs[2]; +out_putname: + putname(filename); out: - return error; + return result; } - /* * fill in the FPU structure for a core dump. */ diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 554f9cf..3c41907 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -102,9 +102,9 @@ sys_sigaction(int sig, const struct old_ } asmlinkage long -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - struct pt_regs *regs) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { + struct pt_regs *regs = task_pt_regs(current); return do_sigaltstack(uss, uoss, regs->gprs[15]); } @@ -163,8 +163,9 @@ static int restore_sigregs(struct pt_reg return 0; } -asmlinkage long sys_sigreturn(struct pt_regs *regs) +asmlinkage long sys_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); sigframe __user *frame = (sigframe __user *)regs->gprs[15]; sigset_t set; @@ -189,8 +190,9 @@ badframe: return 0; } -asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys_rt_sigreturn(void) { + struct pt_regs *regs = task_pt_regs(current); rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15]; sigset_t set; diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 584ed95..3a77c22 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -266,23 +266,3 @@ s390_fadvise64_64(struct fadvise64_64_ar return -EFAULT; return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register const char *__arg1 asm("2") = filename; - register char *const*__arg2 asm("3") = argv; - register char *const*__arg3 asm("4") = envp; - register long __svcres asm("2"); - asm volatile( - "svc %b1" - : "=d" (__svcres) - : "i" (__NR_execve), - "0" (__arg1), - "d" (__arg2), - "d" (__arg3) : "memory"); - return __svcres; -} diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index a52c444..b807a90 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -10,7 +10,7 @@ #define NI_SYSCALL SYSCALL(sys_ni_syscal NI_SYSCALL /* 0 */ SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper) -SYSCALL(sys_fork_glue,sys_fork_glue,sys_fork_glue) +SYSCALL(sys_fork,sys_fork,sys_fork) SYSCALL(sys_read,sys_read,sys32_read_wrapper) SYSCALL(sys_write,sys_write,sys32_write_wrapper) SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */ @@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_ SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) SYSCALL(sys_link,sys_link,sys32_link_wrapper) SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ -SYSCALL(sys_execve_glue,sys_execve_glue,sys32_execve_glue) +SYSCALL(sys_execve,sys_execve,sys32_execve) SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) @@ -127,8 +127,8 @@ SYSCALL(sys_swapoff,sys_swapoff,sys32_sw SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) -SYSCALL(sys_sigreturn_glue,sys_sigreturn_glue,sys32_sigreturn_glue) -SYSCALL(sys_clone_glue,sys_clone_glue,sys32_clone_glue) /* 120 */ +SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) +SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */ SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper) NI_SYSCALL /* modify_ldt for i386 */ @@ -181,7 +181,7 @@ SYSCALL(sys_nfsservctl,sys_nfsservctl,co SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper) /* 170 old setresgid16 syscall */ SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */ SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper) -SYSCALL(sys_rt_sigreturn_glue,sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue) +SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,sys32_rt_sigreturn) SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper) SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */ SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper) @@ -194,11 +194,11 @@ SYSCALL(sys_chown16,sys_ni_syscall,sys32 SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper) SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper) SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */ -SYSCALL(sys_sigaltstack_glue,sys_sigaltstack_glue,sys32_sigaltstack_glue) +SYSCALL(sys_sigaltstack,sys_sigaltstack,sys32_sigaltstack) SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper) NI_SYSCALL /* streams1 */ NI_SYSCALL /* streams2 */ -SYSCALL(sys_vfork_glue,sys_vfork_glue,sys_vfork_glue) /* 190 */ +SYSCALL(sys_vfork,sys_vfork,sys_vfork) /* 190 */ SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper) SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper) SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index f0e5a32..49dec83 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -30,7 +30,7 @@ #include #include #include #include - +#include #include #include #include @@ -188,18 +188,31 @@ void dump_stack(void) EXPORT_SYMBOL(dump_stack); +static inline int mask_bits(struct pt_regs *regs, unsigned long bits) +{ + return (regs->psw.mask & bits) / ((~bits + 1) & bits); +} + void show_registers(struct pt_regs *regs) { - mm_segment_t old_fs; char *mode; - int i; mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl"; printk("%s PSW : %p %p", mode, (void *) regs->psw.mask, (void *) regs->psw.addr); print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN); - printk("%s GPRS: " FOURLONG, mode, + printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x " + "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER), + mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO), + mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY), + mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT), + mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC), + mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM)); +#ifdef CONFIG_64BIT + printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS)); +#endif + printk("\n%s GPRS: " FOURLONG, mode, regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]); printk(" " FOURLONG, regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]); @@ -208,41 +221,7 @@ void show_registers(struct pt_regs *regs printk(" " FOURLONG, regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]); -#if 0 - /* FIXME: this isn't needed any more but it changes the ksymoops - * input. To remove or not to remove ... */ - save_access_regs(regs->acrs); - printk("%s ACRS: %08x %08x %08x %08x\n", mode, - regs->acrs[0], regs->acrs[1], regs->acrs[2], regs->acrs[3]); - printk(" %08x %08x %08x %08x\n", - regs->acrs[4], regs->acrs[5], regs->acrs[6], regs->acrs[7]); - printk(" %08x %08x %08x %08x\n", - regs->acrs[8], regs->acrs[9], regs->acrs[10], regs->acrs[11]); - printk(" %08x %08x %08x %08x\n", - regs->acrs[12], regs->acrs[13], regs->acrs[14], regs->acrs[15]); -#endif - - /* - * Print the first 20 byte of the instruction stream at the - * time of the fault. - */ - old_fs = get_fs(); - if (regs->psw.mask & PSW_MASK_PSTATE) - set_fs(USER_DS); - else - set_fs(KERNEL_DS); - printk("%s Code: ", mode); - for (i = 0; i < 20; i++) { - unsigned char c; - if (__get_user(c, (char __user *)(regs->psw.addr + i))) { - printk(" Bad PSW."); - break; - } - printk("%02x ", c); - } - set_fs(old_fs); - - printk("\n"); + show_code(regs); } /* This is called from fs/proc/array.c */ @@ -318,6 +297,11 @@ #if defined(CONFIG_SYSCTL) || defined(CO #endif } +int is_valid_bugaddr(unsigned long addr) +{ + return 1; +} + static void __kprobes inline do_trap(long interruption_code, int signr, char *str, struct pt_regs *regs, siginfo_t *info) @@ -344,8 +328,14 @@ static void __kprobes inline do_trap(lon fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); if (fixup) regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; - else - die(str, regs, interruption_code); + else { + enum bug_trap_type btt; + + btt = report_bug(regs->psw.addr & PSW_ADDR_INSN); + if (btt == BUG_TRAP_TYPE_WARN) + return; + die(str, regs, interruption_code); + } } } diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index c30716a..418f642 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -45,6 +45,8 @@ #endif __ex_table : { *(__ex_table) } __stop___ex_table = .; + BUG_TABLE + .data : { /* Data */ *(.data) CONSTRUCTORS @@ -77,6 +79,12 @@ #endif *(.init.text) _einittext = .; } + /* + * .exit.text is discarded at runtime, not link time, + * to deal with references from __bug_table + */ + .exit.text : { *(.exit.text) } + .init.data : { *(.init.data) } . = ALIGN(256); __setup_start = .; @@ -116,7 +124,7 @@ #endif /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) *(.exit.data) *(.exitcall.exit) + *(.exit.data) *(.exitcall.exit) } /* Stabs debugging sections. */ diff --git a/drivers/s390/cio/chpid.h b/drivers/s390/cio/chpid.h new file mode 100644 index 0000000..93c7ab9 --- /dev/null +++ b/drivers/s390/cio/chpid.h @@ -0,0 +1,53 @@ +/* + * drivers/s390/cio/chpid.h + * + * Copyright IBM Corp. 2007 + * Author(s): Peter Oberparleiter + */ + +#ifndef S390_CHP_ID_H +#define S390_CHP_ID_H S390_CHP_ID_H + +#include +#include +#include "css.h" + +struct chp_id { + u8 reserved1; + u8 cssid; + u8 reserved2; + u8 id; +} __attribute__((packed)); + +static inline void chp_id_init(struct chp_id *chpid) +{ + memset(chpid, 0, sizeof(struct chp_id)); + chpid->cssid = 0; + chpid->id = 0; +} + +static inline int chp_id_is_equal(struct chp_id *a, struct chp_id *b) +{ + return (a->id == b->id) && (a->cssid == b->cssid); +} + +static inline void chp_id_next(struct chp_id *chpid) +{ + if (chpid->id < __MAX_CHPID) + chpid->id++; + else { + chpid->id = 0; + chpid->cssid++; + } +} + +static inline int chp_id_is_valid(struct chp_id *chpid) +{ + return (chpid->cssid <= __MAX_CSSID); +} + + +#define chp_id_for_each(c) \ + for (chp_id_init(c); chp_id_is_valid(c); chp_id_next(c)) + +#endif /* S390_CHP_ID_H */ diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 6f05a44..3e8bb85 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -20,43 +20,45 @@ #include "css.h" #include "cio.h" #include "cio_debug.h" #include "ioasm.h" +#include "chpid.h" #include "chsc.h" +#define chpid_to_chp(c) (css[(c).cssid]->chps[(c).id]) + static void *sei_page; -static int new_channel_path(int chpid); +static int new_channel_path(struct chp_id chpid); -static inline void -set_chp_logically_online(int chp, int onoff) +static void set_chp_logically_online(struct chp_id chpid, int onoff) { - css[0]->chps[chp]->state = onoff; + chpid_to_chp(chpid)->state = onoff; } -static int -get_chp_status(int chp) +static int get_chp_status(struct chp_id chpid) { - return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV); + return (chpid_to_chp(chpid) ? chpid_to_chp(chpid)->state : -ENODEV); } -void -chsc_validate_chpids(struct subchannel *sch) +void chsc_validate_chpids(struct subchannel *sch) { int mask, chp; + struct chp_id chpid; + chp_id_init(&chpid); for (chp = 0; chp <= 7; chp++) { mask = 0x80 >> chp; - if (!get_chp_status(sch->schib.pmcw.chpid[chp])) + chpid.id = sch->schib.pmcw.chpid[chp]; + if (!get_chp_status(chpid)) /* disable using this path */ sch->opm &= ~mask; } } -void -chpid_is_actually_online(int chp) +void chpid_is_actually_online(struct chp_id chpid) { int state; - state = get_chp_status(chp); + state = get_chp_status(chpid); if (state < 0) { need_rescan = 1; queue_work(slow_path_wq, &slow_path_work); @@ -200,11 +202,14 @@ css_get_ssd_info(struct subchannel *sch) spin_unlock_irq(sch->lock); free_page((unsigned long)page); if (!ret) { - int j, chpid, mask; + int j, mask; + struct chp_id chpid; + + chp_id_init(&chpid); /* Allocate channel path structures, if needed. */ for (j = 0; j < 8; j++) { mask = 0x80 >> j; - chpid = sch->ssd_info.chpid[j]; + chpid.id = sch->ssd_info.chpid[j]; if ((sch->schib.pmcw.pim & mask) && (get_chp_status(chpid) < 0)) new_channel_path(chpid); @@ -227,7 +232,7 @@ s390_subchannel_remove_chpid(struct devi for (j = 0; j < 8; j++) { mask = 0x80 >> j; if ((sch->schib.pmcw.pim & mask) && - (sch->schib.pmcw.chpid[j] == chpid->id)) + (sch->schib.pmcw.chpid[j] == chpid->chpid.id)) break; } if (j >= 8) @@ -277,18 +282,17 @@ out_unreg: return 0; } -static void -s390_set_chpid_offline( __u8 chpid) +static void s390_set_chpid_offline(struct chp_id chpid) { char dbf_txt[15]; struct device *dev; - sprintf(dbf_txt, "chpr%x", chpid); + sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_txt); if (get_chp_status(chpid) <= 0) return; - dev = get_device(&css[0]->chps[chpid]->dev); + dev = get_device(&(chpid_to_chp(chpid)->dev)); bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev), s390_subchannel_remove_chpid); @@ -316,7 +320,7 @@ s390_process_res_acc_sch(struct res_acc_ * check if chpid is in information updated by ssd */ if (sch->ssd_info.valid && - sch->ssd_info.chpid[chp] == res_data->chp->id && + sch->ssd_info.chpid[chp] == res_data->chp->chpid.id && (sch->ssd_info.fla[chp] & res_data->fla_mask) == res_data->fla) { found = 1; @@ -409,7 +413,8 @@ s390_process_res_acc (struct res_acc_dat int rc; char dbf_txt[15]; - sprintf(dbf_txt, "accpr%x", res_data->chp->id); + sprintf(dbf_txt, "accpr%x.%02x", res_data->chp->chpid.cssid, + res_data->chp->chpid.id); CIO_TRACE_EVENT( 2, dbf_txt); if (res_data->fla != 0) { sprintf(dbf_txt, "fla%x", res_data->fla); @@ -482,17 +487,21 @@ struct chsc_sei_area { static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) { - int chpid; + struct chp_id chpid; + int id; CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n", sei_area->rs, sei_area->rsid); if (sei_area->rs != 4) return 0; - chpid = __get_chpid_from_lir(sei_area->ccdf); - if (chpid < 0) + id = __get_chpid_from_lir(sei_area->ccdf); + if (id < 0) CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n"); - else + else { + chp_id_init(&chpid); + chpid.id = id; s390_set_chpid_offline(chpid); + } return 0; } @@ -501,6 +510,7 @@ static int chsc_process_sei_res_acc(stru { struct res_acc_data res_data; struct device *dev; + struct chp_id chpid; int status; int rc; @@ -508,13 +518,15 @@ static int chsc_process_sei_res_acc(stru "rs_id=%04x)\n", sei_area->rs, sei_area->rsid); if (sei_area->rs != 4) return 0; + chp_id_init(&chpid); + chpid.id = sei_area->rsid; /* allocate a new channel path structure, if needed */ - status = get_chp_status(sei_area->rsid); + status = get_chp_status(chpid); if (status < 0) - new_channel_path(sei_area->rsid); + new_channel_path(chpid); else if (!status) return 0; - dev = get_device(&css[0]->chps[sei_area->rsid]->dev); + dev = get_device(&(chpid_to_chp(chpid)->dev)); memset(&res_data, 0, sizeof(struct res_acc_data)); res_data.chp = to_channelpath(dev); if ((sei_area->vf & 0xc0) != 0) { @@ -631,7 +643,7 @@ __chp_add(struct subchannel_id schid, vo for (i=0; i<8; i++) { mask = 0x80 >> i; if ((sch->schib.pmcw.pim & mask) && - (sch->schib.pmcw.chpid[i] == chp->id)) { + (sch->schib.pmcw.chpid[i] == chp->chpid.id)) { if (stsch(sch->schid, &sch->schib) != 0) { /* Endgame. */ spin_unlock_irq(sch->lock); @@ -657,8 +669,7 @@ __chp_add(struct subchannel_id schid, vo return 0; } -static int -chp_add(int chpid) +static int chp_add(struct chp_id chpid) { int rc; char dbf_txt[15]; @@ -667,10 +678,10 @@ chp_add(int chpid) if (!get_chp_status(chpid)) return 0; /* no need to do the rest */ - sprintf(dbf_txt, "cadd%x", chpid); + sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id); CIO_TRACE_EVENT(2, dbf_txt); - dev = get_device(&css[0]->chps[chpid]->dev); + dev = get_device(&(chpid_to_chp(chpid)->dev)); rc = for_each_subchannel(__chp_add, to_channelpath(dev)); if (css_slow_subchannels_exist()) rc = -EAGAIN; @@ -683,9 +694,12 @@ chp_add(int chpid) /* * Handling of crw machine checks with channel path source. */ -int -chp_process_crw(int chpid, int on) +int chp_process_crw(int id, int on) { + struct chp_id chpid; + + chp_id_init(&chpid); + chpid.id = id; if (on == 0) { /* Path has gone. We use the link incident routine.*/ s390_set_chpid_offline(chpid); @@ -733,8 +747,8 @@ static void terminate_internal_io(struct sch->driver->termination(&sch->dev); } -static void -__s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) +static void __s390_subchannel_vary_chpid(struct subchannel *sch, + struct chp_id chpid, int on) { int chp, old_lpm; unsigned long flags; @@ -745,7 +759,7 @@ __s390_subchannel_vary_chpid(struct subc spin_lock_irqsave(sch->lock, flags); old_lpm = sch->lpm; for (chp = 0; chp < 8; chp++) { - if (sch->ssd_info.chpid[chp] != chpid) + if (sch->ssd_info.chpid[chp] != chpid.id) continue; if (on) { @@ -780,11 +794,10 @@ __s390_subchannel_vary_chpid(struct subc spin_unlock_irqrestore(sch->lock, flags); } -static int -s390_subchannel_vary_chpid_off(struct device *dev, void *data) +static int s390_subchannel_vary_chpid_off(struct device *dev, void *data) { struct subchannel *sch; - __u8 *chpid; + struct chp_id *chpid; sch = to_subchannel(dev); chpid = data; @@ -793,11 +806,10 @@ s390_subchannel_vary_chpid_off(struct de return 0; } -static int -s390_subchannel_vary_chpid_on(struct device *dev, void *data) +static int s390_subchannel_vary_chpid_on(struct device *dev, void *data) { struct subchannel *sch; - __u8 *chpid; + struct chp_id *chpid; sch = to_subchannel(dev); chpid = data; @@ -833,23 +845,25 @@ __s390_vary_chpid_on(struct subchannel_i * Function: s390_vary_chpid * Varies the specified chpid online or offline */ -static int -s390_vary_chpid( __u8 chpid, int on) +static int s390_vary_chpid(struct chp_id chpid, int on) { char dbf_text[15]; int status; - sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid); + sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, + chpid.id); CIO_TRACE_EVENT( 2, dbf_text); status = get_chp_status(chpid); if (status < 0) { - printk(KERN_ERR "Can't vary unknown chpid %02X\n", chpid); + printk(KERN_ERR "Can't vary unknown chpid %x.%02x\n", + chpid.cssid, chpid.id); return -EINVAL; } if (!on && !status) { - printk(KERN_ERR "chpid %x is already offline\n", chpid); + printk(KERN_ERR "chpid %x.%02x is already offline\n", + chpid.cssid, chpid.id); return -EINVAL; } @@ -904,20 +918,19 @@ static struct bin_attribute chp_measurem .read = chp_measurement_chars_read, }; -static void -chp_measurement_copy_block(struct cmg_entry *buf, - struct channel_subsystem *css, int chpid) +static void chp_measurement_copy_block(struct cmg_entry *buf, + struct channel_subsystem *css, struct chp_id chpid) { void *area; struct cmg_entry *entry, reference_buf; int idx; - if (chpid < 128) { + if (chpid.id < 128) { area = css->cub_addr1; - idx = chpid; + idx = chpid.id; } else { area = css->cub_addr2; - idx = chpid - 128; + idx = chpid.id - 128; } entry = area + (idx * sizeof(struct cmg_entry)); do { @@ -941,7 +954,7 @@ chp_measurement_read(struct kobject *kob /* Only allow single reads. */ if (off || count < size) return 0; - chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id); + chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->chpid); count = size; return count; } @@ -1137,7 +1150,7 @@ chp_status_show(struct device *dev, stru if (!chp) return 0; - return (get_chp_status(chp->id) ? sprintf(buf, "online\n") : + return (get_chp_status(chp->chpid) ? sprintf(buf, "online\n") : sprintf(buf, "offline\n")); } @@ -1154,9 +1167,9 @@ chp_status_write(struct device *dev, str return count; if (!strnicmp(cmd, "on", 2)) - error = s390_vary_chpid(cp->id, 1); + error = s390_vary_chpid(cp->chpid, 1); else if (!strnicmp(cmd, "off", 3)) - error = s390_vary_chpid(cp->id, 0); + error = s390_vary_chpid(cp->chpid, 0); else error = -EINVAL; @@ -1227,9 +1240,8 @@ chp_release(struct device *dev) kfree(cp); } -static int -chsc_determine_channel_path_description(int chpid, - struct channel_path_desc *desc) +static int chsc_determine_channel_path_description(struct chp_id chpid, + struct channel_path_desc *desc) { int ccode, ret; @@ -1252,8 +1264,8 @@ chsc_determine_channel_path_description( scpd_area->request.length = 0x0010; scpd_area->request.code = 0x0002; - scpd_area->first_chpid = chpid; - scpd_area->last_chpid = chpid; + scpd_area->first_chpid = chpid.id; + scpd_area->last_chpid = chpid.id; ccode = chsc(scpd_area); if (ccode > 0) { @@ -1349,8 +1361,8 @@ chsc_get_channel_measurement_chars(struc scmc_area->request.length = 0x0010; scmc_area->request.code = 0x0022; - scmc_area->first_chpid = chp->id; - scmc_area->last_chpid = chp->id; + scmc_area->first_chpid = chp->chpid.id; + scmc_area->last_chpid = chp->chpid.id; ccode = chsc(scmc_area); if (ccode > 0) { @@ -1396,8 +1408,7 @@ out: * Entries for chpids on the system bus. * This replaces /proc/chpids. */ -static int -new_channel_path(int chpid) +static int new_channel_path(struct chp_id chpid) { struct channel_path *chp; int ret; @@ -1407,11 +1418,12 @@ new_channel_path(int chpid) return -ENOMEM; /* fill in status, etc. */ - chp->id = chpid; + chp->chpid = chpid; chp->state = 1; - chp->dev.parent = &css[0]->device; + chp->dev.parent = &css[chpid.cssid]->device; chp->dev.release = chp_release; - snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid); + snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, + chpid.id); /* Obtain channel path description and fill it in. */ ret = chsc_determine_channel_path_description(chpid, &chp->desc); @@ -1437,8 +1449,8 @@ new_channel_path(int chpid) /* make it known to the system */ ret = device_register(&chp->dev); if (ret) { - printk(KERN_WARNING "%s: could not register %02x\n", - __func__, chpid); + printk(KERN_WARNING "%s: could not register %x.%02x\n", + __func__, chpid.cssid, chpid.id); goto out_free; } ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); @@ -1446,18 +1458,18 @@ new_channel_path(int chpid) device_unregister(&chp->dev); goto out_free; } - mutex_lock(&css[0]->mutex); - if (css[0]->cm_enabled) { + mutex_lock(&css[chpid.cssid]->mutex); + if (css[chpid.cssid]->cm_enabled) { ret = chsc_add_chp_cmg_attr(chp); if (ret) { sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); device_unregister(&chp->dev); - mutex_unlock(&css[0]->mutex); + mutex_unlock(&css[chpid.cssid]->mutex); goto out_free; } } - css[0]->chps[chpid] = chp; - mutex_unlock(&css[0]->mutex); + css[chpid.cssid]->chps[chpid.id] = chp; + mutex_unlock(&css[chpid.cssid]->mutex); return ret; out_free: kfree(chp); @@ -1469,8 +1481,11 @@ chsc_get_chp_desc(struct subchannel *sch { struct channel_path *chp; struct channel_path_desc *desc; + struct chp_id chpid; - chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]]; + chp_id_init(&chpid); + chpid.id = sch->schib.pmcw.chpid[chp_no]; + chp = chpid_to_chp(chpid); if (!chp) return NULL; desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 0fb2b02..2949c85 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -1,6 +1,10 @@ #ifndef S390_CHSC_H #define S390_CHSC_H +#include +#include +#include "chpid.h" + #define CHSC_SEI_ACC_CHPID 1 #define CHSC_SEI_ACC_LINKADDR 2 #define CHSC_SEI_ACC_FULLLINKADDR 3 @@ -34,7 +38,7 @@ struct channel_path_desc { } __attribute__ ((packed)); struct channel_path { - int id; + struct chp_id chpid; int state; struct channel_path_desc desc; /* Channel-measurement related stuff: */ @@ -46,7 +50,7 @@ struct channel_path { extern void s390_process_css( void ); extern void chsc_validate_chpids(struct subchannel *); -extern void chpid_is_actually_online(int); +extern void chpid_is_actually_online(struct chp_id); extern int css_get_ssd_info(struct subchannel *); extern int chsc_process_crw(void); extern int chp_process_crw(int, int); diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 9cb129a..bab7292 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -954,6 +954,7 @@ static void css_reset(void) { int i, ret; unsigned long long timeout; + struct chp_id chpid; /* Reset subchannels. */ for_each_subchannel(__shutdown_subchannel_easy, NULL); @@ -963,8 +964,10 @@ static void css_reset(void) __ctl_set_bit(14, 28); /* Temporarily reenable machine checks. */ local_mcck_enable(); + chp_id_init(&chpid); for (i = 0; i <= __MAX_CHPID; i++) { - ret = rchp(i); + chpid.id = i; + ret = rchp(chpid); if ((ret == 0) || (ret == 2)) /* * rchp either succeeded, or another rchp is already @@ -1048,37 +1051,19 @@ void reipl_ccw_dev(struct ccw_dev_id *de do_reipl_asm(*((__u32*)&schid)); } -static struct schib __initdata ipl_schib; - -/* - * ipl_save_parameters gets called very early. It is not allowed to access - * anything in the bss section at all. The bss section is not cleared yet, - * but may contain some ipl parameters written by the firmware. - * These parameters (if present) are copied to 0x2000. - * To avoid corruption of the ipl parameters, all variables used by this - * function must reside on the stack or in the data section. - */ -void ipl_save_parameters(void) +int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) { struct subchannel_id schid; - unsigned int *ipl_ptr; - void *src, *dst; + struct schib schib; schid = *(struct subchannel_id *)__LC_SUBCHANNEL_ID; if (!schid.one) - return; - if (stsch(schid, &ipl_schib)) - return; - if (!ipl_schib.pmcw.dnv) - return; - ipl_devno = ipl_schib.pmcw.dev; - ipl_flags |= IPL_DEVNO_VALID; - if (!ipl_schib.pmcw.qf) - return; - ipl_flags |= IPL_PARMBLOCK_VALID; - ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR; - src = (void *)(unsigned long)*ipl_ptr; - dst = (void *)IPL_PARMBLOCK_ORIGIN; - memmove(dst, src, PAGE_SIZE); - *ipl_ptr = IPL_PARMBLOCK_ORIGIN; + return -ENODEV; + if (stsch(schid, &schib)) + return -ENODEV; + if (!schib.pmcw.dnv) + return -ENODEV; + iplinfo->devno = schib.pmcw.dev; + iplinfo->is_qdio = schib.pmcw.qf; + return 0; } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 089a3dd..5f5ee1e 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -22,6 +22,7 @@ #include "css.h" #include "device.h" #include "chsc.h" #include "ioasm.h" +#include "chpid.h" int device_is_online(struct subchannel *sch) @@ -210,14 +211,17 @@ static void __recover_lost_chpids(struct subchannel *sch, int old_lpm) { int mask, i; + struct chp_id chpid; + chp_id_init(&chpid); for (i = 0; i<8; i++) { mask = 0x80 >> i; if (!(sch->lpm & mask)) continue; if (old_lpm & mask) continue; - chpid_is_actually_online(sch->schib.pmcw.chpid[i]); + chpid.id = sch->schib.pmcw.chpid[i]; + chpid_is_actually_online(chpid); } } diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index ad6d829..78c7db6 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -2,6 +2,7 @@ #ifndef S390_CIO_IOASM_H #define S390_CIO_IOASM_H #include "schid.h" +#include "chpid.h" /* * TPI info structure @@ -189,9 +190,9 @@ static inline int chsc(void *chsc_area) return cc; } -static inline int rchp(int chpid) +static inline int rchp(struct chp_id chpid) { - register unsigned int reg1 asm ("1") = chpid; + register struct chp_id reg1 asm ("1") = chpid; int ccode; asm volatile( diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 5b1e3ff..05fac07 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -210,9 +210,11 @@ again: goto again; } if (rc < 0) { - QDIO_DBF_TEXT3(1,trace,"sqberr"); - sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no); - QDIO_DBF_TEXT3(1,trace,dbf_text); + QDIO_DBF_TEXT3(1,trace,"sqberr"); + sprintf(dbf_text,"%2x,%2x",tmp_cnt,*cnt); + QDIO_DBF_TEXT3(1,trace,dbf_text); + sprintf(dbf_text,"%d,%d",ccq,q_no); + QDIO_DBF_TEXT3(1,trace,dbf_text); q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION| QDIO_STATUS_LOOK_FOR_ERROR, 0, 0, 0, -1, -1, q->int_parm); @@ -1250,7 +1252,6 @@ #endif if (!no_used) { QDIO_DBF_TEXT4(0,trace,"inqisdnA"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - QDIO_DBF_TEXT4(0,trace,dbf_text); return 1; } if (irq->is_qebsm) { @@ -3371,10 +3372,15 @@ qdio_do_qdio_fill_input(struct qdio_q *q unsigned int count, struct qdio_buffer *buffers) { struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; + int tmp = 0; + qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); if (irq->is_qebsm) { - while (count) - set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); + while (count) { + tmp = set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); + if (!tmp) + return; + } return; } for (;;) { @@ -3390,11 +3396,15 @@ qdio_do_qdio_fill_output(struct qdio_q * unsigned int count, struct qdio_buffer *buffers) { struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; + int tmp = 0; qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); if (irq->is_qebsm) { - while (count) - set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); + while (count) { + tmp = set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); + if (!tmp) + return; + } return; } diff --git a/include/asm-s390/bug.h b/include/asm-s390/bug.h index 8768983..838684d 100644 --- a/include/asm-s390/bug.h +++ b/include/asm-s390/bug.h @@ -1,27 +1,70 @@ -#ifndef _S390_BUG_H -#define _S390_BUG_H +#ifndef _ASM_S390_BUG_H +#define _ASM_S390_BUG_H #include #ifdef CONFIG_BUG -static inline __attribute__((noreturn)) void __do_illegal_op(void) -{ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) - __builtin_trap(); +#ifdef CONFIG_64BIT +#define S390_LONG ".quad" #else - asm volatile(".long 0"); +#define S390_LONG ".long" #endif -} -#define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - __do_illegal_op(); \ +#ifdef CONFIG_DEBUG_BUGVERBOSE + +#define __EMIT_BUG(x) do { \ + asm volatile( \ + "0: j 0b+2\n" \ + "1:\n" \ + ".section .rodata.str,\"aMS\",@progbits,1\n" \ + "2: .asciz \""__FILE__"\"\n" \ + ".previous\n" \ + ".section __bug_table,\"a\"\n" \ + "3:\t" S390_LONG "\t1b,2b\n" \ + " .short %0,%1\n" \ + " .org 3b+%2\n" \ + ".previous\n" \ + : : "i" (__LINE__), \ + "i" (x), \ + "i" (sizeof(struct bug_entry))); \ } while (0) +#else /* CONFIG_DEBUG_BUGVERBOSE */ + +#define __EMIT_BUG(x) do { \ + asm volatile( \ + "0: j 0b+2\n" \ + "1:\n" \ + ".section __bug_table,\"a\"\n" \ + "2:\t" S390_LONG "\t1b\n" \ + " .short %0\n" \ + " .org 2b+%1\n" \ + ".previous\n" \ + : : "i" (x), \ + "i" (sizeof(struct bug_entry))); \ +} while (0) + +#endif /* CONFIG_DEBUG_BUGVERBOSE */ + +#define BUG() __EMIT_BUG(0) + +#define WARN_ON(x) ({ \ + typeof(x) __ret_warn_on = (x); \ + if (__builtin_constant_p(__ret_warn_on)) { \ + if (__ret_warn_on) \ + __EMIT_BUG(BUGFLAG_WARNING); \ + } else { \ + if (unlikely(__ret_warn_on)) \ + __EMIT_BUG(BUGFLAG_WARNING); \ + } \ + unlikely(__ret_warn_on); \ +}) + #define HAVE_ARCH_BUG -#endif +#define HAVE_ARCH_WARN_ON +#endif /* CONFIG_BUG */ #include -#endif +#endif /* _ASM_S390_BUG_H */ diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index d927850..0db017b 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h @@ -292,6 +292,13 @@ extern void css_schedule_reprobe(void); extern void reipl_ccw_dev(struct ccw_dev_id *id); +struct cio_iplinfo { + u16 devno; + int is_qdio; +}; + +extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo); + #endif #endif diff --git a/include/asm-s390/ipl.h b/include/asm-s390/ipl.h index 660f782..3cbe86b 100644 --- a/include/asm-s390/ipl.h +++ b/include/asm-s390/ipl.h @@ -69,10 +69,9 @@ struct ipl_parameter_block { } __attribute__((packed)); /* - * IPL validity flags and parameters as detected in head.S + * IPL validity flags */ extern u32 ipl_flags; -extern u16 ipl_devno; extern u32 dump_prefix_page; extern void do_reipl(void); diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index 33b80ce..96a6f80 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h @@ -196,6 +196,7 @@ extern unsigned long thread_saved_pc(str extern char *task_show_regs(struct task_struct *task, char *buffer); extern void show_registers(struct pt_regs *regs); +extern void show_code(struct pt_regs *regs); extern void show_trace(struct task_struct *task, unsigned long *sp); unsigned long get_wchan(struct task_struct *p);