summaryrefslogtreecommitdiff
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/Makefile3
-rw-r--r--arch/s390/kernel/asm-offsets.c99
-rw-r--r--arch/s390/kernel/base.S2
-rw-r--r--arch/s390/kernel/dis.c369
-rw-r--r--arch/s390/kernel/early.c22
-rw-r--r--arch/s390/kernel/entry.S1
-rw-r--r--arch/s390/kernel/entry64.S2
-rw-r--r--arch/s390/kernel/ftrace.c12
-rw-r--r--arch/s390/kernel/head.S60
-rw-r--r--arch/s390/kernel/head31.S16
-rw-r--r--arch/s390/kernel/head64.S92
-rw-r--r--arch/s390/kernel/ipl.c41
-rw-r--r--arch/s390/kernel/machine_kexec.c10
-rw-r--r--arch/s390/kernel/ptrace.c58
-rw-r--r--arch/s390/kernel/reipl.S2
-rw-r--r--arch/s390/kernel/reipl64.S2
-rw-r--r--arch/s390/kernel/sclp.S36
-rw-r--r--arch/s390/kernel/setup.c11
-rw-r--r--arch/s390/kernel/smp.c120
-rw-r--r--arch/s390/kernel/switch_cpu.S58
-rw-r--r--arch/s390/kernel/switch_cpu64.S51
-rw-r--r--arch/s390/kernel/swsusp_asm64.S2
-rw-r--r--arch/s390/kernel/time.c67
-rw-r--r--arch/s390/kernel/vdso.c1
24 files changed, 801 insertions, 336 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 683f6381cc59..64230bc392fa 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -29,9 +29,12 @@ obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
extra-y += head.o init_task.o vmlinux.lds
+extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o)
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
obj-$(CONFIG_SMP) += smp.o topology.o
+obj-$(CONFIG_SMP) += $(if $(CONFIG_64BIT),switch_cpu64.o, \
+ switch_cpu.o)
obj-$(CONFIG_HIBERNATION) += suspend.o swsusp_asm64.o
obj-$(CONFIG_AUDIT) += audit.o
compat-obj-$(CONFIG_AUDIT) += compat_audit.o
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 63e46433e81d..08db736dded0 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -4,18 +4,27 @@
* and format the required data.
*/
-#include <linux/sched.h>
+#define ASM_OFFSETS_C
+
#include <linux/kbuild.h>
+#include <linux/sched.h>
#include <asm/vdso.h>
#include <asm/sigp.h>
+/*
+ * Make sure that the compiler is new enough. We want a compiler that
+ * is known to work with the "Q" assembler constraint.
+ */
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+#error Your compiler is too old; please use version 3.3.3 or newer
+#endif
+
int main(void)
{
DEFINE(__THREAD_info, offsetof(struct task_struct, stack));
DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp));
DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info));
- DEFINE(__THREAD_mm_segment,
- offsetof(struct task_struct, thread.mm_segment));
+ DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment));
BLANK();
DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
BLANK();
@@ -52,18 +61,94 @@ int main(void)
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
- DEFINE(__VDSO_ECTG_BASE,
- offsetof(struct vdso_per_cpu_data, ectg_timer_base));
- DEFINE(__VDSO_ECTG_USER,
- offsetof(struct vdso_per_cpu_data, ectg_user_time));
+ DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));
+ DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));
/* constants used by the vdso */
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
+ BLANK();
/* constants for SIGP */
DEFINE(__SIGP_STOP, sigp_stop);
DEFINE(__SIGP_RESTART, sigp_restart);
DEFINE(__SIGP_SENSE, sigp_sense);
DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset);
+ BLANK();
+ /* lowcore offsets */
+ DEFINE(__LC_EXT_PARAMS, offsetof(struct _lowcore, ext_params));
+ DEFINE(__LC_CPU_ADDRESS, offsetof(struct _lowcore, cpu_addr));
+ DEFINE(__LC_EXT_INT_CODE, offsetof(struct _lowcore, ext_int_code));
+ DEFINE(__LC_SVC_ILC, offsetof(struct _lowcore, svc_ilc));
+ DEFINE(__LC_SVC_INT_CODE, offsetof(struct _lowcore, svc_code));
+ DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc));
+ DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code));
+ DEFINE(__LC_PER_ATMID, offsetof(struct _lowcore, per_perc_atmid));
+ DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address));
+ DEFINE(__LC_PER_ACCESS_ID, offsetof(struct _lowcore, per_access_id));
+ DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_access_id));
+ DEFINE(__LC_SUBCHANNEL_ID, offsetof(struct _lowcore, subchannel_id));
+ DEFINE(__LC_SUBCHANNEL_NR, offsetof(struct _lowcore, subchannel_nr));
+ DEFINE(__LC_IO_INT_PARM, offsetof(struct _lowcore, io_int_parm));
+ DEFINE(__LC_IO_INT_WORD, offsetof(struct _lowcore, io_int_word));
+ DEFINE(__LC_STFL_FAC_LIST, offsetof(struct _lowcore, stfl_fac_list));
+ DEFINE(__LC_MCCK_CODE, offsetof(struct _lowcore, mcck_interruption_code));
+ DEFINE(__LC_DUMP_REIPL, offsetof(struct _lowcore, ipib));
+ BLANK();
+ DEFINE(__LC_RST_NEW_PSW, offsetof(struct _lowcore, restart_psw));
+ DEFINE(__LC_RST_OLD_PSW, offsetof(struct _lowcore, restart_old_psw));
+ DEFINE(__LC_EXT_OLD_PSW, offsetof(struct _lowcore, external_old_psw));
+ DEFINE(__LC_SVC_OLD_PSW, offsetof(struct _lowcore, svc_old_psw));
+ DEFINE(__LC_PGM_OLD_PSW, offsetof(struct _lowcore, program_old_psw));
+ DEFINE(__LC_MCK_OLD_PSW, offsetof(struct _lowcore, mcck_old_psw));
+ DEFINE(__LC_IO_OLD_PSW, offsetof(struct _lowcore, io_old_psw));
+ DEFINE(__LC_EXT_NEW_PSW, offsetof(struct _lowcore, external_new_psw));
+ DEFINE(__LC_SVC_NEW_PSW, offsetof(struct _lowcore, svc_new_psw));
+ DEFINE(__LC_PGM_NEW_PSW, offsetof(struct _lowcore, program_new_psw));
+ DEFINE(__LC_MCK_NEW_PSW, offsetof(struct _lowcore, mcck_new_psw));
+ DEFINE(__LC_IO_NEW_PSW, offsetof(struct _lowcore, io_new_psw));
+ DEFINE(__LC_SAVE_AREA, offsetof(struct _lowcore, save_area));
+ DEFINE(__LC_RETURN_PSW, offsetof(struct _lowcore, return_psw));
+ DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw));
+ DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer));
+ DEFINE(__LC_ASYNC_ENTER_TIMER, offsetof(struct _lowcore, async_enter_timer));
+ DEFINE(__LC_EXIT_TIMER, offsetof(struct _lowcore, exit_timer));
+ DEFINE(__LC_USER_TIMER, offsetof(struct _lowcore, user_timer));
+ DEFINE(__LC_SYSTEM_TIMER, offsetof(struct _lowcore, system_timer));
+ DEFINE(__LC_STEAL_TIMER, offsetof(struct _lowcore, steal_timer));
+ DEFINE(__LC_LAST_UPDATE_TIMER, offsetof(struct _lowcore, last_update_timer));
+ DEFINE(__LC_LAST_UPDATE_CLOCK, offsetof(struct _lowcore, last_update_clock));
+ DEFINE(__LC_CURRENT, offsetof(struct _lowcore, current_task));
+ DEFINE(__LC_THREAD_INFO, offsetof(struct _lowcore, thread_info));
+ DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack));
+ DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack));
+ DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
+ DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce));
+ DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
+ DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce));
+ DEFINE(__LC_CPUID, offsetof(struct _lowcore, cpu_id));
+ DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
+ DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));
+ DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func));
+ DEFINE(__LC_IRB, offsetof(struct _lowcore, irb));
+ DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area));
+ DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area));
+ DEFINE(__LC_PSW_SAVE_AREA, offsetof(struct _lowcore, psw_save_area));
+ DEFINE(__LC_PREFIX_SAVE_AREA, offsetof(struct _lowcore, prefixreg_save_area));
+ DEFINE(__LC_AREGS_SAVE_AREA, offsetof(struct _lowcore, access_regs_save_area));
+ DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
+ DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
+ DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
+#ifdef CONFIG_32BIT
+ DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params));
+ DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
+#else /* CONFIG_32BIT */
+ DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2));
+ DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));
+ DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
+ DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
+ DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area));
+ DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
+ DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
+#endif /* CONFIG_32BIT */
return 0;
}
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index dc7e5259770f..15e46ca94335 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -6,8 +6,8 @@
* Michael Holzheu <holzheu@de.ibm.com>
*/
+#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
-#include <asm/lowcore.h>
#ifdef CONFIG_64BIT
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index db943a7ec513..b39b27d68b45 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -86,10 +86,17 @@ enum {
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 */
+ U4_32, /* 4 bit unsigned value starting at 32 */
U8_8, /* 8 bit unsigned value starting at 8 */
U8_16, /* 8 bit unsigned value starting at 16 */
+ U8_24, /* 8 bit unsigned value starting at 24 */
+ U8_32, /* 8 bit unsigned value starting at 32 */
+ I8_8, /* 8 bit signed value starting at 8 */
+ I8_32, /* 8 bit signed value starting at 32 */
I16_16, /* 16 bit signed value starting at 16 */
+ I16_32, /* 32 bit signed value starting at 16 */
U16_16, /* 16 bit unsigned value starting at 16 */
+ U16_32, /* 32 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 */
@@ -104,21 +111,37 @@ enum {
*/
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_E,
+ INSTR_RIE_R0IU, INSTR_RIE_R0UU, INSTR_RIE_RRP, INSTR_RIE_RRPU,
+ INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU,
+ INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, INSTR_RIL_UP,
+ INSTR_RIS_R0RDU, INSTR_RIS_R0UU, INSTR_RIS_RURDI, INSTR_RIS_RURDU,
+ 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_RRE_FF, INSTR_RRE_FR, INSTR_RRE_R0, INSTR_RRE_RA, INSTR_RRE_RF,
+ INSTR_RRE_RR, INSTR_RRE_RR_OPT,
+ INSTR_RRF_0UFF, INSTR_RRF_F0FF, INSTR_RRF_F0FF2, INSTR_RRF_F0FR,
+ INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_M0RR, INSTR_RRF_R0RR,
+ INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF, INSTR_RRF_U0RR,
+ INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
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_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_RXY_URRD,
+ INSTR_RX_FRRD, INSTR_RX_RRRD, INSTR_RX_URRD,
+ INSTR_SIL_RDI, INSTR_SIL_RDU,
+ INSTR_SIY_IRD, 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,
};
@@ -129,7 +152,7 @@ struct operand {
};
struct insn {
- const char name[5];
+ const char name[6];
unsigned char opfrag;
unsigned char format;
};
@@ -170,11 +193,16 @@ static const struct operand operands[] =
[U4_12] = { 4, 12, 0 },
[U4_16] = { 4, 16, 0 },
[U4_20] = { 4, 20, 0 },
+ [U4_32] = { 4, 32, 0 },
[U8_8] = { 8, 8, 0 },
[U8_16] = { 8, 16, 0 },
+ [U8_24] = { 8, 24, 0 },
+ [U8_32] = { 8, 32, 0 },
[I16_16] = { 16, 16, OPERAND_SIGNED },
[U16_16] = { 16, 16, 0 },
+ [U16_32] = { 16, 32, 0 },
[J16_16] = { 16, 16, OPERAND_PCREL },
+ [I16_32] = { 16, 32, OPERAND_SIGNED },
[J32_16] = { 32, 16, OPERAND_PCREL },
[I32_16] = { 32, 16, OPERAND_SIGNED },
[U32_16] = { 32, 16, 0 },
@@ -183,82 +211,93 @@ static const struct operand operands[] =
};
static const unsigned char formats[][7] = {
- [INSTR_E] = { 0xff, 0,0,0,0,0,0 }, /* e.g. pr */
- [INSTR_RIE_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 }, /* e.g. brxhg */
- [INSTR_RIL_RP] = { 0x0f, R_8,J32_16,0,0,0,0 }, /* e.g. brasl */
- [INSTR_RIL_UP] = { 0x0f, U4_8,J32_16,0,0,0,0 }, /* e.g. brcl */
- [INSTR_RIL_RI] = { 0x0f, R_8,I32_16,0,0,0,0 }, /* e.g. afi */
- [INSTR_RIL_RU] = { 0x0f, R_8,U32_16,0,0,0,0 }, /* e.g. alfi */
- [INSTR_RI_RI] = { 0x0f, R_8,I16_16,0,0,0,0 }, /* e.g. ahi */
- [INSTR_RI_RP] = { 0x0f, R_8,J16_16,0,0,0,0 }, /* e.g. brct */
- [INSTR_RI_RU] = { 0x0f, R_8,U16_16,0,0,0,0 }, /* e.g. tml */
- [INSTR_RI_UP] = { 0x0f, U4_8,J16_16,0,0,0,0 }, /* e.g. brc */
- [INSTR_RRE_00] = { 0xff, 0,0,0,0,0,0 }, /* e.g. palb */
- [INSTR_RRE_0R] = { 0xff, R_28,0,0,0,0,0 }, /* e.g. tb */
- [INSTR_RRE_AA] = { 0xff, A_24,A_28,0,0,0,0 }, /* e.g. cpya */
- [INSTR_RRE_AR] = { 0xff, A_24,R_28,0,0,0,0 }, /* e.g. sar */
- [INSTR_RRE_F0] = { 0xff, F_24,0,0,0,0,0 }, /* e.g. sqer */
- [INSTR_RRE_FF] = { 0xff, F_24,F_28,0,0,0,0 }, /* e.g. debr */
- [INSTR_RRE_R0] = { 0xff, R_24,0,0,0,0,0 }, /* e.g. ipm */
- [INSTR_RRE_RA] = { 0xff, R_24,A_28,0,0,0,0 }, /* e.g. ear */
- [INSTR_RRE_RF] = { 0xff, R_24,F_28,0,0,0,0 }, /* e.g. cefbr */
- [INSTR_RRE_RR] = { 0xff, R_24,R_28,0,0,0,0 }, /* e.g. lura */
- [INSTR_RRE_RR_OPT]= { 0xff, R_24,RO_28,0,0,0,0 }, /* efpc, sfpc */
- [INSTR_RRF_F0FF] = { 0xff, F_16,F_24,F_28,0,0,0 }, /* e.g. madbr */
- [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 },/* e.g. didbr */
- [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 },/* e.g. .insn */
- [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 }, /* e.g. idte */
- [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, /* e.g. fixr */
- [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, /* e.g. cfebr */
- [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, /* e.g. sske */
- [INSTR_RR_FF] = { 0xff, F_8,F_12,0,0,0,0 }, /* e.g. adr */
- [INSTR_RR_R0] = { 0xff, R_8, 0,0,0,0,0 }, /* e.g. spm */
- [INSTR_RR_RR] = { 0xff, R_8,R_12,0,0,0,0 }, /* e.g. lr */
- [INSTR_RR_U0] = { 0xff, U8_8, 0,0,0,0,0 }, /* e.g. svc */
- [INSTR_RR_UR] = { 0xff, U4_8,R_12,0,0,0,0 }, /* e.g. bcr */
- [INSTR_RSE_RRRD] = { 0xff, R_8,R_12,D_20,B_16,0,0 }, /* e.g. lmh */
- [INSTR_RSE_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 }, /* e.g. lmh */
- [INSTR_RSE_RURD] = { 0xff, R_8,U4_12,D_20,B_16,0,0 }, /* e.g. icmh */
- [INSTR_RSL_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 }, /* e.g. tp */
- [INSTR_RSI_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 }, /* e.g. brxh */
- [INSTR_RSY_RRRD] = { 0xff, R_8,R_12,D20_20,B_16,0,0 },/* e.g. stmy */
+ [INSTR_E] = { 0xff, 0,0,0,0,0,0 },
+ [INSTR_RIE_R0UU] = { 0xff, R_8,U16_16,U4_32,0,0,0 },
+ [INSTR_RIE_RRPU] = { 0xff, R_8,R_12,U4_32,J16_16,0,0 },
+ [INSTR_RIE_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 },
+ [INSTR_RIE_RRUUU] = { 0xff, R_8,R_12,U8_16,U8_24,U8_32,0 },
+ [INSTR_RIE_RUPI] = { 0xff, R_8,I8_32,U4_12,J16_16,0,0 },
+ [INSTR_RIL_RI] = { 0x0f, R_8,I32_16,0,0,0,0 },
+ [INSTR_RIL_RP] = { 0x0f, R_8,J32_16,0,0,0,0 },
+ [INSTR_RIL_RU] = { 0x0f, R_8,U32_16,0,0,0,0 },
+ [INSTR_RIL_UP] = { 0x0f, U4_8,J32_16,0,0,0,0 },
+ [INSTR_RIS_R0RDU] = { 0xff, R_8,U8_32,D_20,B_16,0,0 },
+ [INSTR_RIS_RURDI] = { 0xff, R_8,I8_32,U4_12,D_20,B_16,0 },
+ [INSTR_RIS_RURDU] = { 0xff, R_8,U8_32,U4_12,D_20,B_16,0 },
+ [INSTR_RI_RI] = { 0x0f, R_8,I16_16,0,0,0,0 },
+ [INSTR_RI_RP] = { 0x0f, R_8,J16_16,0,0,0,0 },
+ [INSTR_RI_RU] = { 0x0f, R_8,U16_16,0,0,0,0 },
+ [INSTR_RI_UP] = { 0x0f, U4_8,J16_16,0,0,0,0 },
+ [INSTR_RRE_00] = { 0xff, 0,0,0,0,0,0 },
+ [INSTR_RRE_0R] = { 0xff, R_28,0,0,0,0,0 },
+ [INSTR_RRE_AA] = { 0xff, A_24,A_28,0,0,0,0 },
+ [INSTR_RRE_AR] = { 0xff, A_24,R_28,0,0,0,0 },
+ [INSTR_RRE_F0] = { 0xff, F_24,0,0,0,0,0 },
+ [INSTR_RRE_FF] = { 0xff, F_24,F_28,0,0,0,0 },
+ [INSTR_RRE_FR] = { 0xff, F_24,R_28,0,0,0,0 },
+ [INSTR_RRE_R0] = { 0xff, R_24,0,0,0,0,0 },
+ [INSTR_RRE_RA] = { 0xff, R_24,A_28,0,0,0,0 },
+ [INSTR_RRE_RF] = { 0xff, R_24,F_28,0,0,0,0 },
+ [INSTR_RRE_RR] = { 0xff, R_24,R_28,0,0,0,0 },
+ [INSTR_RRE_RR_OPT]= { 0xff, R_24,RO_28,0,0,0,0 },
+ [INSTR_RRF_0UFF] = { 0xff, F_24,F_28,U4_20,0,0,0 },
+ [INSTR_RRF_F0FF2] = { 0xff, F_24,F_16,F_28,0,0,0 },
+ [INSTR_RRF_F0FF] = { 0xff, F_16,F_24,F_28,0,0,0 },
+ [INSTR_RRF_F0FR] = { 0xff, F_24,F_16,R_28,0,0,0 },
+ [INSTR_RRF_FFRU] = { 0xff, F_24,F_16,R_28,U4_20,0,0 },
+ [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 },
+ [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 },
+ [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 },
+ [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 },
+ [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 },
+ [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 },
+ [INSTR_RRF_U0RR] = { 0xff, R_24,R_28,U4_16,0,0,0 },
+ [INSTR_RRF_UUFF] = { 0xff, F_24,U4_16,F_28,U4_20,0,0 },
+ [INSTR_RRR_F0FF] = { 0xff, F_24,F_28,F_16,0,0,0 },
+ [INSTR_RRS_RRRDU] = { 0xff, R_8,R_12,U4_32,D_20,B_16,0 },
+ [INSTR_RR_FF] = { 0xff, F_8,F_12,0,0,0,0 },
+ [INSTR_RR_R0] = { 0xff, R_8, 0,0,0,0,0 },
+ [INSTR_RR_RR] = { 0xff, R_8,R_12,0,0,0,0 },
+ [INSTR_RR_U0] = { 0xff, U8_8, 0,0,0,0,0 },
+ [INSTR_RR_UR] = { 0xff, U4_8,R_12,0,0,0,0 },
+ [INSTR_RSE_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 },
+ [INSTR_RSE_RRRD] = { 0xff, R_8,R_12,D_20,B_16,0,0 },
+ [INSTR_RSE_RURD] = { 0xff, R_8,U4_12,D_20,B_16,0,0 },
+ [INSTR_RSI_RRP] = { 0xff, R_8,R_12,J16_16,0,0,0 },
+ [INSTR_RSL_R0RD] = { 0xff, D_20,L4_8,B_16,0,0,0 },
+ [INSTR_RSY_AARD] = { 0xff, A_8,A_12,D20_20,B_16,0,0 },
+ [INSTR_RSY_CCRD] = { 0xff, C_8,C_12,D20_20,B_16,0,0 },
+ [INSTR_RSY_RRRD] = { 0xff, R_8,R_12,D20_20,B_16,0,0 },
[INSTR_RSY_RURD] = { 0xff, R_8,U4_12,D20_20,B_16,0,0 },
- /* e.g. icmh */
- [INSTR_RSY_AARD] = { 0xff, A_8,A_12,D20_20,B_16,0,0 },/* e.g. lamy */
- [INSTR_RSY_CCRD] = { 0xff, C_8,C_12,D20_20,B_16,0,0 },/* e.g. lamy */
- [INSTR_RS_AARD] = { 0xff, A_8,A_12,D_20,B_16,0,0 }, /* e.g. lam */
- [INSTR_RS_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 }, /* e.g. lctl */
- [INSTR_RS_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 }, /* e.g. sll */
- [INSTR_RS_RRRD] = { 0xff, R_8,R_12,D_20,B_16,0,0 }, /* e.g. cs */
- [INSTR_RS_RURD] = { 0xff, R_8,U4_12,D_20,B_16,0,0 }, /* e.g. icm */
- [INSTR_RXE_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. axbr */
- [INSTR_RXE_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. lg */
+ [INSTR_RS_AARD] = { 0xff, A_8,A_12,D_20,B_16,0,0 },
+ [INSTR_RS_CCRD] = { 0xff, C_8,C_12,D_20,B_16,0,0 },
+ [INSTR_RS_R0RD] = { 0xff, R_8,D_20,B_16,0,0,0 },
+ [INSTR_RS_RRRD] = { 0xff, R_8,R_12,D_20,B_16,0,0 },
+ [INSTR_RS_RURD] = { 0xff, R_8,U4_12,D_20,B_16,0,0 },
+ [INSTR_RXE_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 },
+ [INSTR_RXE_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 },
[INSTR_RXF_FRRDF] = { 0xff, F_32,F_8,D_20,X_12,B_16,0 },
- /* e.g. madb */
- [INSTR_RXY_RRRD] = { 0xff, R_8,D20_20,X_12,B_16,0,0 },/* e.g. ly */
- [INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },/* e.g. ley */
- [INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */
- [INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */
- [INSTR_RX_URRD] = { 0xff, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */
- [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */
- [INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */
- [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */
+ [INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },
+ [INSTR_RXY_RRRD] = { 0xff, R_8,D20_20,X_12,B_16,0,0 },
+ [INSTR_RXY_URRD] = { 0xff, U4_8,D20_20,X_12,B_16,0,0 },
+ [INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 },
+ [INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 },
+ [INSTR_RX_URRD] = { 0xff, U4_8,D_20,X_12,B_16,0,0 },
+ [INSTR_SIL_RDI] = { 0xff, D_20,B_16,I16_32,0,0,0 },
+ [INSTR_SIL_RDU] = { 0xff, D_20,B_16,U16_32,0,0,0 },
+ [INSTR_SIY_IRD] = { 0xff, D20_20,B_16,I8_8,0,0,0 },
+ [INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 },
+ [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 },
+ [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 },
+ [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 },
[INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 },
- /* e.g. mvc */
[INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 },
- /* e.g. srp */
[INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 },
- /* e.g. pack */
- [INSTR_SS_RRRDRD] = { 0xff, D_20,R_8,B_16,D_36,B_32,R_12 },
- /* e.g. mvck */
[INSTR_SS_RRRDRD2]= { 0xff, R_8,D_20,B_16,R_12,D_36,B_32 },
- /* e.g. plo */
[INSTR_SS_RRRDRD3]= { 0xff, R_8,R_12,D_20,B_16,D_36,B_32 },
- /* e.g. lmd */
- [INSTR_S_00] = { 0xff, 0,0,0,0,0,0 }, /* e.g. hsch */
- [INSTR_S_RD] = { 0xff, D_20,B_16,0,0,0,0 }, /* e.g. lpsw */
- [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 },
- /* e.g. mvcos */
+ [INSTR_SS_RRRDRD] = { 0xff, D_20,R_8,B_16,D_36,B_32,R_12 },
+ [INSTR_S_00] = { 0xff, 0,0,0,0,0,0 },
+ [INSTR_S_RD] = { 0xff, D_20,B_16,0,0,0,0 },
};
static struct insn opcode[] = {
@@ -454,6 +493,8 @@ static struct insn opcode[] = {
static struct insn opcode_01[] = {
#ifdef CONFIG_64BIT
{ "sam64", 0x0e, INSTR_E },
+ { "pfpo", 0x0a, INSTR_E },
+ { "ptff", 0x04, INSTR_E },
#endif
{ "pr", 0x01, INSTR_E },
{ "upt", 0x02, INSTR_E },
@@ -519,6 +560,8 @@ static struct insn opcode_b2[] = {
{ "cutfu", 0xa7, INSTR_RRF_M0RR },
{ "stfle", 0xb0, INSTR_S_RD },
{ "lpswe", 0xb2, INSTR_S_RD },
+ { "srnmt", 0xb9, INSTR_S_RD },
+ { "lfas", 0xbd, INSTR_S_RD },
#endif
{ "stidp", 0x02, INSTR_S_RD },
{ "sck", 0x04, INSTR_S_RD },
@@ -589,7 +632,6 @@ static struct insn opcode_b2[] = {
{ "clst", 0x5d, INSTR_RRE_RR },
{ "srst", 0x5e, INSTR_RRE_RR },
{ "cmpsc", 0x63, INSTR_RRE_RR },
- { "cmpsc", 0x63, INSTR_RRE_RR },
{ "siga", 0x74, INSTR_S_RD },
{ "xsch", 0x76, INSTR_S_00 },
{ "rp", 0x77, INSTR_S_RD },
@@ -630,6 +672,57 @@ static struct insn opcode_b3[] = {
{ "cger", 0xc8, INSTR_RRF_U0RF },
{ "cgdr", 0xc9, INSTR_RRF_U0RF },
{ "cgxr", 0xca, INSTR_RRF_U0RF },
+ { "lpdfr", 0x70, INSTR_RRE_FF },
+ { "lndfr", 0x71, INSTR_RRE_FF },
+ { "cpsdr", 0x72, INSTR_RRF_F0FF2 },
+ { "lcdfr", 0x73, INSTR_RRE_FF },
+ { "ldgr", 0xc1, INSTR_RRE_FR },
+ { "lgdr", 0xcd, INSTR_RRE_RF },
+ { "adtr", 0xd2, INSTR_RRR_F0FF },
+ { "axtr", 0xda, INSTR_RRR_F0FF },
+ { "cdtr", 0xe4, INSTR_RRE_FF },
+ { "cxtr", 0xec, INSTR_RRE_FF },
+ { "kdtr", 0xe0, INSTR_RRE_FF },
+ { "kxtr", 0xe8, INSTR_RRE_FF },
+ { "cedtr", 0xf4, INSTR_RRE_FF },
+ { "cextr", 0xfc, INSTR_RRE_FF },
+ { "cdgtr", 0xf1, INSTR_RRE_FR },
+ { "cxgtr", 0xf9, INSTR_RRE_FR },
+ { "cdstr", 0xf3, INSTR_RRE_FR },
+ { "cxstr", 0xfb, INSTR_RRE_FR },
+ { "cdutr", 0xf2, INSTR_RRE_FR },
+ { "cxutr", 0xfa, INSTR_RRE_FR },
+ { "cgdtr", 0xe1, INSTR_RRF_U0RF },
+ { "cgxtr", 0xe9, INSTR_RRF_U0RF },
+ { "csdtr", 0xe3, INSTR_RRE_RF },
+ { "csxtr", 0xeb, INSTR_RRE_RF },
+ { "cudtr", 0xe2, INSTR_RRE_RF },
+ { "cuxtr", 0xea, INSTR_RRE_RF },
+ { "ddtr", 0xd1, INSTR_RRR_F0FF },
+ { "dxtr", 0xd9, INSTR_RRR_F0FF },
+ { "eedtr", 0xe5, INSTR_RRE_RF },
+ { "eextr", 0xed, INSTR_RRE_RF },
+ { "esdtr", 0xe7, INSTR_RRE_RF },
+ { "esxtr", 0xef, INSTR_RRE_RF },
+ { "iedtr", 0xf6, INSTR_RRF_F0FR },
+ { "iextr", 0xfe, INSTR_RRF_F0FR },
+ { "ltdtr", 0xd6, INSTR_RRE_FF },
+ { "ltxtr", 0xde, INSTR_RRE_FF },
+ { "fidtr", 0xd7, INSTR_RRF_UUFF },
+ { "fixtr", 0xdf, INSTR_RRF_UUFF },
+ { "ldetr", 0xd4, INSTR_RRF_0UFF },
+ { "lxdtr", 0xdc, INSTR_RRF_0UFF },
+ { "ledtr", 0xd5, INSTR_RRF_UUFF },
+ { "ldxtr", 0xdd, INSTR_RRF_UUFF },
+ { "mdtr", 0xd0, INSTR_RRR_F0FF },
+ { "mxtr", 0xd8, INSTR_RRR_F0FF },
+ { "qadtr", 0xf5, INSTR_RRF_FUFF },
+ { "qaxtr", 0xfd, INSTR_RRF_FUFF },
+ { "rrdtr", 0xf7, INSTR_RRF_FFRU },
+ { "rrxtr", 0xff, INSTR_RRF_FFRU },
+ { "sfasr", 0x85, INSTR_RRE_R0 },
+ { "sdtr", 0xd3, INSTR_RRR_F0FF },
+ { "sxtr", 0xdb, INSTR_RRR_F0FF },
#endif
{ "lpebr", 0x00, INSTR_RRE_FF },
{ "lnebr", 0x01, INSTR_RRE_FF },
@@ -780,6 +873,14 @@ static struct insn opcode_b9[] = {
{ "cu24", 0xb1, INSTR_RRF_M0RR },
{ "cu41", 0xb2, INSTR_RRF_M0RR },
{ "cu42", 0xb3, INSTR_RRF_M0RR },
+ { "crt", 0x72, INSTR_RRF_U0RR },
+ { "cgrt", 0x60, INSTR_RRF_U0RR },
+ { "clrt", 0x73, INSTR_RRF_U0RR },
+ { "clgrt", 0x61, INSTR_RRF_U0RR },
+ { "ptf", 0xa2, INSTR_RRE_R0 },
+ { "pfmf", 0xaf, INSTR_RRE_RR },
+ { "trte", 0xbf, INSTR_RRF_M0RR },
+ { "trtre", 0xbd, INSTR_RRF_M0RR },
#endif
{ "kmac", 0x1e, INSTR_RRE_RR },
{ "lrvr", 0x1f, INSTR_RRE_RR },
@@ -835,6 +936,43 @@ static struct insn opcode_c2[] = {
{ "cfi", 0x0d, INSTR_RIL_RI },
{ "clgfi", 0x0e, INSTR_RIL_RU },
{ "clfi", 0x0f, INSTR_RIL_RU },
+ { "msfi", 0x01, INSTR_RIL_RI },
+ { "msgfi", 0x00, INSTR_RIL_RI },
+#endif
+ { "", 0, INSTR_INVALID }
+};
+
+static struct insn opcode_c4[] = {
+#ifdef CONFIG_64BIT
+ { "lrl", 0x0d, INSTR_RIL_RP },
+ { "lgrl", 0x08, INSTR_RIL_RP },
+ { "lgfrl", 0x0c, INSTR_RIL_RP },
+ { "lhrl", 0x05, INSTR_RIL_RP },
+ { "lghrl", 0x04, INSTR_RIL_RP },
+ { "llgfrl", 0x0e, INSTR_RIL_RP },
+ { "llhrl", 0x02, INSTR_RIL_RP },
+ { "llghrl", 0x06, INSTR_RIL_RP },
+ { "strl", 0x0f, INSTR_RIL_RP },
+ { "stgrl", 0x0b, INSTR_RIL_RP },
+ { "sthrl", 0x07, INSTR_RIL_RP },
+#endif
+ { "", 0, INSTR_INVALID }
+};
+
+static struct insn opcode_c6[] = {
+#ifdef CONFIG_64BIT
+ { "crl", 0x0d, INSTR_RIL_RP },
+ { "cgrl", 0x08, INSTR_RIL_RP },
+ { "cgfrl", 0x0c, INSTR_RIL_RP },
+ { "chrl", 0x05, INSTR_RIL_RP },
+ { "cghrl", 0x04, INSTR_RIL_RP },
+ { "clrl", 0x0f, INSTR_RIL_RP },
+ { "clgrl", 0x0a, INSTR_RIL_RP },
+ { "clgfrl", 0x0e, INSTR_RIL_RP },
+ { "clhrl", 0x07, INSTR_RIL_RP },
+ { "clghrl", 0x06, INSTR_RIL_RP },
+ { "pfdrl", 0x02, INSTR_RIL_UP },
+ { "exrl", 0x00, INSTR_RIL_RP },
#endif
{ "", 0, INSTR_INVALID }
};
@@ -842,6 +980,8 @@ static struct insn opcode_c2[] = {
static struct insn opcode_c8[] = {
#ifdef CONFIG_64BIT
{ "mvcos", 0x00, INSTR_SSF_RRDRD },
+ { "ectg", 0x01, INSTR_SSF_RRDRD },
+ { "csst", 0x02, INSTR_SSF_RRDRD },
#endif
{ "", 0, INSTR_INVALID }
};
@@ -917,6 +1057,12 @@ static struct insn opcode_e3[] = {
{ "llgh", 0x91, INSTR_RXY_RRRD },
{ "llc", 0x94, INSTR_RXY_RRRD },
{ "llh", 0x95, INSTR_RXY_RRRD },
+ { "cgh", 0x34, INSTR_RXY_RRRD },
+ { "laey", 0x75, INSTR_RXY_RRRD },
+ { "ltgf", 0x32, INSTR_RXY_RRRD },
+ { "mfy", 0x5c, INSTR_RXY_RRRD },
+ { "mhy", 0x7c, INSTR_RXY_RRRD },
+ { "pfd", 0x36, INSTR_RXY_URRD },
#endif
{ "lrv", 0x1e, INSTR_RXY_RRRD },
{ "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -931,6 +1077,15 @@ static struct insn opcode_e3[] = {
static struct insn opcode_e5[] = {
#ifdef CONFIG_64BIT
{ "strag", 0x02, INSTR_SSE_RDRD },
+ { "chhsi", 0x54, INSTR_SIL_RDI },
+ { "chsi", 0x5c, INSTR_SIL_RDI },
+ { "cghsi", 0x58, INSTR_SIL_RDI },
+ { "clhhsi", 0x55, INSTR_SIL_RDU },
+ { "clfhsi", 0x5d, INSTR_SIL_RDU },
+ { "clghsi", 0x59, INSTR_SIL_RDU },
+ { "mvhhi", 0x44, INSTR_SIL_RDI },
+ { "mvhi", 0x4c, INSTR_SIL_RDI },
+ { "mvghi", 0x48, INSTR_SIL_RDI },
#endif
{ "lasp", 0x00, INSTR_SSE_RDRD },
{ "tprot", 0x01, INSTR_SSE_RDRD },
@@ -977,6 +1132,11 @@ static struct insn opcode_eb[] = {
{ "lmy", 0x98, INSTR_RSY_RRRD },
{ "lamy", 0x9a, INSTR_RSY_AARD },
{ "stamy", 0x9b, INSTR_RSY_AARD },
+ { "asi", 0x6a, INSTR_SIY_IRD },
+ { "agsi", 0x7a, INSTR_SIY_IRD },
+ { "alsi", 0x6e, INSTR_SIY_IRD },
+ { "algsi", 0x7e, INSTR_SIY_IRD },
+ { "ecag", 0x4c, INSTR_RSY_RRRD },
#endif
{ "rll", 0x1d, INSTR_RSY_RRRD },
{ "mvclu", 0x8e, INSTR_RSY_RRRD },
@@ -988,6 +1148,30 @@ static struct insn opcode_ec[] = {
#ifdef CONFIG_64BIT
{ "brxhg", 0x44, INSTR_RIE_RRP },
{ "brxlg", 0x45, INSTR_RIE_RRP },
+ { "crb", 0xf6, INSTR_RRS_RRRDU },
+ { "cgrb", 0xe4, INSTR_RRS_RRRDU },
+ { "crj", 0x76, INSTR_RIE_RRPU },
+ { "cgrj", 0x64, INSTR_RIE_RRPU },
+ { "cib", 0xfe, INSTR_RIS_RURDI },
+ { "cgib", 0xfc, INSTR_RIS_RURDI },
+ { "cij", 0x7e, INSTR_RIE_RUPI },
+ { "cgij", 0x7c, INSTR_RIE_RUPI },
+ { "cit", 0x72, INSTR_RIE_R0IU },
+ { "cgit", 0x70, INSTR_RIE_R0IU },
+ { "clrb", 0xf7, INSTR_RRS_RRRDU },
+ { "clgrb", 0xe5, INSTR_RRS_RRRDU },
+ { "clrj", 0x77, INSTR_RIE_RRPU },
+ { "clgrj", 0x65, INSTR_RIE_RRPU },
+ { "clib", 0xff, INSTR_RIS_RURDU },
+ { "clgib", 0xfd, INSTR_RIS_RURDU },
+ { "clij", 0x7f, INSTR_RIE_RUPU },
+ { "clgij", 0x7d, INSTR_RIE_RUPU },
+ { "clfit", 0x73, INSTR_RIE_R0UU },
+ { "clgit", 0x71, INSTR_RIE_R0UU },
+ { "rnsbg", 0x54, INSTR_RIE_RRUUU },
+ { "rxsbg", 0x57, INSTR_RIE_RRUUU },
+ { "rosbg", 0x56, INSTR_RIE_RRUUU },
+ { "risbg", 0x55, INSTR_RIE_RRUUU },
#endif
{ "", 0, INSTR_INVALID }
};
@@ -1004,6 +1188,16 @@ static struct insn opcode_ed[] = {
{ "ldy", 0x65, INSTR_RXY_FRRD },
{ "stey", 0x66, INSTR_RXY_FRRD },
{ "stdy", 0x67, INSTR_RXY_FRRD },
+ { "sldt", 0x40, INSTR_RXF_FRRDF },
+ { "slxt", 0x48, INSTR_RXF_FRRDF },
+ { "srdt", 0x41, INSTR_RXF_FRRDF },
+ { "srxt", 0x49, INSTR_RXF_FRRDF },
+ { "tdcet", 0x50, INSTR_RXE_FRRD },
+ { "tdcdt", 0x54, INSTR_RXE_FRRD },
+ { "tdcxt", 0x58, INSTR_RXE_FRRD },
+ { "tdget", 0x51, INSTR_RXE_FRRD },
+ { "tdgdt", 0x55, INSTR_RXE_FRRD },
+ { "tdgxt", 0x59, INSTR_RXE_FRRD },
#endif
{ "ldeb", 0x04, INSTR_RXE_FRRD },
{ "lxdb", 0x05, INSTR_RXE_FRRD },
@@ -1037,6 +1231,7 @@ static struct insn opcode_ed[] = {
{ "mae", 0x2e, INSTR_RXF_FRRDF },
{ "mse", 0x2f, INSTR_RXF_FRRDF },
{ "sqe", 0x34, INSTR_RXE_FRRD },
+ { "sqd", 0x35, INSTR_RXE_FRRD },
{ "mee", 0x37, INSTR_RXE_FRRD },
{ "mad", 0x3e, INSTR_RXF_FRRDF },
{ "msd", 0x3f, INSTR_RXF_FRRDF },
@@ -1117,6 +1312,12 @@ static struct insn *find_insn(unsigned char *code)
case 0xc2:
table = opcode_c2;
break;
+ case 0xc4:
+ table = opcode_c4;
+ break;
+ case 0xc6:
+ table = opcode_c6;
+ break;
case 0xc8:
table = opcode_c8;
break;
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e49e9e0c69fd..31d618a443af 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -214,10 +214,13 @@ static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
static noinline __init void detect_machine_type(void)
{
- /* No VM information? Looks like LPAR */
- if (stsi(&vmms, 3, 2, 2) == -ENOSYS)
+ /* Check current-configuration-level */
+ if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) {
+ S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR;
return;
- if (!vmms.count)
+ }
+ /* Get virtual-machine cpu information. */
+ if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count)
return;
/* Running under KVM? If not we assume z/VM */
@@ -402,8 +405,19 @@ static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t))
static void __init setup_boot_command_line(void)
{
+ int i;
+
+ /* convert arch command line to ascii */
+ for (i = 0; i < ARCH_COMMAND_LINE_SIZE; i++)
+ if (COMMAND_LINE[i] & 0x80)
+ break;
+ if (i < ARCH_COMMAND_LINE_SIZE)
+ EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
+ COMMAND_LINE[ARCH_COMMAND_LINE_SIZE-1] = 0;
+
/* copy arch command line */
- strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
+ strlcpy(boot_command_line, strstrip(COMMAND_LINE),
+ ARCH_COMMAND_LINE_SIZE);
/* append IPL PARM data to the boot command line */
if (MACHINE_IS_VM)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index e8ef21c51bbe..4348f9bc5393 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -13,7 +13,6 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/cache.h>
-#include <asm/lowcore.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index f33658f09dd7..29fd0f1e6ec4 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -9,11 +9,9 @@
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
-#include <linux/sys.h>
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/cache.h>
-#include <asm/lowcore.h>
#include <asm/errno.h>
#include <asm/ptrace.h>
#include <asm/thread_info.h>
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 5a82bc68193e..6a83d0581317 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <trace/syscall.h>
-#include <asm/lowcore.h>
+#include <asm/asm-offsets.h>
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -200,13 +200,3 @@ out:
return parent;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-
-#ifdef CONFIG_FTRACE_SYSCALLS
-
-extern unsigned int sys_call_table[];
-
-unsigned long __init arch_syscall_addr(int nr)
-{
- return (unsigned long)sys_call_table[nr];
-}
-#endif
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index c52b4f7742fa..ca4a62bd862f 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 1999,2009
+ * Copyright IBM Corp. 1999,2010
*
* Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -22,12 +22,9 @@
*/
#include <linux/init.h>
-#include <asm/setup.h>
-#include <asm/lowcore.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
-#include <asm/cpu.h>
#ifdef CONFIG_64BIT
#define ARCH_OFFSET 4
@@ -288,19 +285,7 @@ iplstart:
bz .Lagain1 # skip dateset trailer
la %r5,0(%r4,%r2)
lr %r3,%r2
-.Lidebc:
- tm 0(%r5),0x80 # high order bit set ?
- bo .Ldocv # yes -> convert from EBCDIC
- ahi %r5,-1
- bct %r3,.Lidebc
- b .Lnocv
-.Ldocv:
- l %r3,.Lcvtab
- tr 0(256,%r4),0(%r3) # convert parameters to ascii
- tr 256(256,%r4),0(%r3)
- tr 512(256,%r4),0(%r3)
- tr 768(122,%r4),0(%r3)
-.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
+ la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
mvc 0(256,%r3),0(%r4)
mvc 256(256,%r3),256(%r4)
mvc 512(256,%r3),512(%r4)
@@ -384,7 +369,6 @@ iplstart:
.Linitrd:.long _end + 0x400000 # default address of initrd
.Lparm: .long PARMAREA
.Lstartup: .long startup
-.Lcvtab:.long _ebcasc # ebcdic to ascii table
.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
.byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
.byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
@@ -417,13 +401,10 @@ start:
.sk8x8:
mvc 0(240,%r8),0(%r9) # copy iplparms into buffer
.gotr:
- l %r10,.tbl # EBCDIC to ASCII table
- tr 0(240,%r8),0(%r10)
slr %r0,%r0
st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
j startup # continue with startup
-.tbl: .long _ebcasc # translate table
.cmd: .long COMMAND_LINE # address of command line buffer
.parm: .long PARMAREA
.lowcase:
@@ -467,16 +448,15 @@ start:
# or linload or SALIPL
#
.org 0x10000
-startup:basr %r13,0 # get base
+ .globl startup
+startup:
+ basr %r13,0 # get base
.LPG0:
xc 0x200(256),0x200 # partially clear lowcore
xc 0x300(256),0x300
- l %r1,5f-.LPG0(%r13)
- stck 0(%r1)
- spt 6f-.LPG0(%r13)
- mvc __LC_LAST_UPDATE_CLOCK(8),0(%r1)
- mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
- mvc __LC_EXIT_TIMER(8),5f-.LPG0(%r13)
+ stck __LC_LAST_UPDATE_CLOCK
+ spt 5f-.LPG0(%r13)
+ mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
#ifndef CONFIG_MARCH_G5
# check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
@@ -494,7 +474,6 @@ startup:basr %r13,0 # get base
cl %r0,2f+12-.LPG0(%r13)
je 3f
1: l %r15,.Lstack-.LPG0(%r13)
- ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
ahi %r15,-96
la %r2,.Lals_string-.LPG0(%r13)
l %r3,.Lsclp_print-.LPG0(%r13)
@@ -505,7 +484,7 @@ startup:basr %r13,0 # get base
.Lsclp_print:
.long _sclp_print_early
.Lstack:
- .long init_thread_union
+ .long 0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
.align 16
2: .long 0x000a0000,0x8badcccc
#if defined(CONFIG_64BIT)
@@ -532,13 +511,22 @@ startup:basr %r13,0 # get base
3:
#endif
+#ifdef CONFIG_64BIT
+ mvi __LC_AR_MODE_ID,1 # set esame flag
+ slr %r0,%r0 # set cpuid to zero
+ lhi %r1,2 # mode 2 = esame (dump)
+ sigp %r1,%r0,0x12 # switch to esame mode
+ sam64 # switch to 64 bit mode
+ jg startup_continue
+#else
+ mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
l %r13,4f-.LPG0(%r13)
b 0(%r13)
- .align 4
+ .align 8
4: .long startup_continue
-5: .long sched_clock_base_cc
+#endif
.align 8
-6: .long 0x7fffffff,0xffffffff
+5: .long 0x7fffffff,0xffffffff
#
# params at 10400 (setup.h)
@@ -552,8 +540,4 @@ startup:basr %r13,0 # get base
.byte "root=/dev/ram0 ro"
.byte 0
-#ifdef CONFIG_64BIT
-#include "head64.S"
-#else
-#include "head31.S"
-#endif
+ .org 0x11000
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 602b508cd4c4..1bbcc499d455 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -1,7 +1,7 @@
/*
* arch/s390/kernel/head31.S
*
- * Copyright (C) IBM Corp. 2005,2006
+ * Copyright (C) IBM Corp. 2005,2010
*
* Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -10,13 +10,19 @@
*
*/
- .org 0x11000
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+__HEAD
+ .globl startup_continue
startup_continue:
basr %r13,0 # get base
.LPG1:
- mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
+ l %r1,.Lbase_cc-.LPG1(%r13)
+ mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK
lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore
@@ -69,10 +75,12 @@ startup_continue:
.Lduald:.rept 8
.long 0x80000000,0,0,0 # invalid access-list entries
.endr
+.Lbase_cc:
+ .long sched_clock_base_cc
- .org 0x12000
.globl _ehead
_ehead:
+
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
#endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index d984a2a380c3..39580e768658 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -1,7 +1,7 @@
/*
* arch/s390/kernel/head64.S
*
- * Copyright (C) IBM Corp. 1999,2006
+ * Copyright (C) IBM Corp. 1999,2010
*
* Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -10,80 +10,17 @@
*
*/
- .org 0x11000
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+__HEAD
+ .globl startup_continue
startup_continue:
- basr %r13,0 # get base
-.LPG1: sll %r13,1 # remove high order bit
- srl %r13,1
-
-#ifdef CONFIG_ZFCPDUMP
-
- # check if we have been ipled using zfcp dump:
-
- tm 0xb9,0x01 # test if subchannel is enabled
- jno .nodump # subchannel disabled
- l %r1,0xb8
- la %r5,.Lipl_schib-.LPG1(%r13)
- stsch 0(%r5) # get schib of subchannel
- jne .nodump # schib not available
- tm 5(%r5),0x01 # devno valid?
- jno .nodump
- tm 4(%r5),0x80 # qdio capable device?
- jno .nodump
- l %r2,20(%r0) # address of ipl parameter block
- lhi %r3,0
- ic %r3,0x148(%r2) # get opt field
- chi %r3,0x20 # load with dump?
- jne .nodump
-
- # store all prefix registers in case of load with dump:
-
- la %r7,0 # base register for 0 page
- la %r8,0 # first cpu
- l %r11,.Lpref_arr_ptr-.LPG1(%r13) # address of prefix array
- ahi %r11,4 # skip boot cpu
- lr %r12,%r11
- ahi %r12,(CONFIG_NR_CPUS*4) # end of prefix array
- stap .Lcurrent_cpu+2-.LPG1(%r13) # store current cpu addr
-1:
- cl %r8,.Lcurrent_cpu-.LPG1(%r13) # is ipl cpu ?
- je 4f # if yes get next cpu
-2:
- lr %r9,%r7
- sigp %r9,%r8,0x9 # stop & store status of cpu
- brc 8,3f # accepted
- brc 4,4f # status stored: next cpu
- brc 2,2b # busy: try again
- brc 1,4f # not op: next cpu
-3:
- mvc 0(4,%r11),264(%r7) # copy prefix register to prefix array
- ahi %r11,4 # next element in prefix array
- clr %r11,%r12
- je 5f # no more space in prefix array
-4:
- ahi %r8,1 # next cpu (r8 += 1)
- chi %r8,MAX_CPU_ADDRESS # is last possible cpu ?
- jle 1b # jump if not last cpu
-5:
- lhi %r1,2 # mode 2 = esame (dump)
- j 6f
- .align 4
-.Lipl_schib:
- .rept 13
- .long 0
- .endr
-.nodump:
- lhi %r1,1 # mode 1 = esame (normal ipl)
-6:
-#else
- lhi %r1,1 # mode 1 = esame (normal ipl)
-#endif /* CONFIG_ZFCPDUMP */
- mvi __LC_AR_MODE_ID,1 # set esame flag
- slr %r0,%r0 # set cpuid to zero
- sigp %r1,%r0,0x12 # switch to esame mode
- sam64 # switch to 64 bit mode
- llgfr %r13,%r13 # clear high-order half of base reg
+ larl %r1,sched_clock_base_cc
+ mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK
+ larl %r13,.LPG1 # get base
lmh %r0,%r15,.Lzero64-.LPG1(%r13) # clear high-order half
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
@@ -108,6 +45,7 @@ startup_continue:
lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
# virtual and never return ...
.align 16
+.LPG1:
.Lentry:.quad 0x0000000180000000,_stext
.Lctl: .quad 0x04350002 # cr0: various things
.quad 0 # cr1: primary space segment table
@@ -130,12 +68,6 @@ startup_continue:
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
.Lnop: .long 0x07000700
.Lzero64:.fill 16,4,0x0
-#ifdef CONFIG_ZFCPDUMP
-.Lcurrent_cpu:
- .long 0x0
-.Lpref_arr_ptr:
- .long zfcpdump_prefix_array
-#endif /* CONFIG_ZFCPDUMP */
.Lparmaddr:
.quad PARMAREA
.align 64
@@ -146,9 +78,9 @@ startup_continue:
.long 0x80000000,0,0,0 # invalid access-list entries
.endr
- .org 0x12000
.globl _ehead
_ehead:
+
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
#endif
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 4d73296fed74..7eedbbcb54aa 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -553,7 +553,7 @@ out:
return rc;
}
-static void ipl_run(struct shutdown_trigger *trigger)
+static void __ipl_run(void *unused)
{
diag308(DIAG308_IPL, NULL);
if (MACHINE_IS_VM)
@@ -562,6 +562,11 @@ static void ipl_run(struct shutdown_trigger *trigger)
reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
}
+static void ipl_run(struct shutdown_trigger *trigger)
+{
+ smp_switch_to_ipl_cpu(__ipl_run, NULL);
+}
+
static int __init ipl_init(void)
{
int rc;
@@ -1039,7 +1044,7 @@ static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
sprintf(dst + pos, " PARM %s", vmparm);
}
-static void reipl_run(struct shutdown_trigger *trigger)
+static void __reipl_run(void *unused)
{
struct ccw_dev_id devid;
static char buf[128];
@@ -1087,6 +1092,11 @@ static void reipl_run(struct shutdown_trigger *trigger)
disabled_wait((unsigned long) __builtin_return_address(0));
}
+static void reipl_run(struct shutdown_trigger *trigger)
+{
+ smp_switch_to_ipl_cpu(__reipl_run, NULL);
+}
+
static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
{
ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
@@ -1369,20 +1379,18 @@ static struct kobj_attribute dump_type_attr =
static struct kset *dump_kset;
-static void dump_run(struct shutdown_trigger *trigger)
+static void __dump_run(void *unused)
{
struct ccw_dev_id devid;
static char buf[100];
switch (dump_method) {
case DUMP_METHOD_CCW_CIO:
- smp_send_stop();
devid.devno = dump_block_ccw->ipl_info.ccw.devno;
devid.ssid = 0;
reipl_ccw_dev(&devid);
break;
case DUMP_METHOD_CCW_VM:
- smp_send_stop();
sprintf(buf, "STORE STATUS");
__cpcmd(buf, NULL, 0, NULL);
sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
@@ -1396,10 +1404,17 @@ static void dump_run(struct shutdown_trigger *trigger)
diag308(DIAG308_SET, dump_block_fcp);
diag308(DIAG308_DUMP, NULL);
break;
- case DUMP_METHOD_NONE:
- return;
+ default:
+ break;
}
- printk(KERN_EMERG "Dump failed!\n");
+}
+
+static void dump_run(struct shutdown_trigger *trigger)
+{
+ if (dump_method == DUMP_METHOD_NONE)
+ return;
+ smp_send_stop();
+ smp_switch_to_ipl_cpu(__dump_run, NULL);
}
static int __init dump_ccw_init(void)
@@ -1577,7 +1592,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger)
static int vmcmd_init(void)
{
if (!MACHINE_IS_VM)
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
if (!vmcmd_kset)
return -ENOMEM;
@@ -1595,7 +1610,7 @@ static void stop_run(struct shutdown_trigger *trigger)
{
if (strcmp(trigger->name, ON_PANIC_STR) == 0)
disabled_wait((unsigned long) __builtin_return_address(0));
- while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+ while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
cpu_relax();
for (;;);
}
@@ -1902,7 +1917,6 @@ void __init ipl_update_parameters(void)
void __init ipl_save_parameters(void)
{
struct cio_iplinfo iplinfo;
- unsigned int *ipl_ptr;
void *src, *dst;
if (cio_get_iplinfo(&iplinfo))
@@ -1913,11 +1927,10 @@ void __init ipl_save_parameters(void)
if (!iplinfo.is_qdio)
return;
ipl_flags |= IPL_PARMBLOCK_VALID;
- ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR;
- src = (void *)(unsigned long)*ipl_ptr;
+ src = (void *)(unsigned long)S390_lowcore.ipl_parmblock_ptr;
dst = (void *)IPL_PARMBLOCK_ORIGIN;
memmove(dst, src, PAGE_SIZE);
- *ipl_ptr = IPL_PARMBLOCK_ORIGIN;
+ S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
}
static LIST_HEAD(rcall);
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 131d7ee8b416..a922d51df6bf 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -54,11 +54,11 @@ void machine_shutdown(void)
{
}
-void machine_kexec(struct kimage *image)
+static void __machine_kexec(void *data)
{
relocate_kernel_t data_mover;
+ struct kimage *image = data;
- smp_send_stop();
pfault_fini();
s390_reset_system();
@@ -68,3 +68,9 @@ void machine_kexec(struct kimage *image)
(*data_mover)(&image->head, image->start);
for (;;);
}
+
+void machine_kexec(struct kimage *image)
+{
+ smp_send_stop();
+ smp_switch_to_ipl_cpu(__machine_kexec, image);
+}
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 7cf464234419..33fdc5a79764 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -992,3 +992,61 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
#endif
return &user_s390_view;
}
+
+static const char *gpr_names[NUM_GPRS] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+};
+
+unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset)
+{
+ if (offset >= NUM_GPRS)
+ return 0;
+ return regs->gprs[offset];
+}
+
+int regs_query_register_offset(const char *name)
+{
+ unsigned long offset;
+
+ if (!name || *name != 'r')
+ return -EINVAL;
+ if (strict_strtoul(name + 1, 10, &offset))
+ return -EINVAL;
+ if (offset >= NUM_GPRS)
+ return -EINVAL;
+ return offset;
+}
+
+const char *regs_query_register_name(unsigned int offset)
+{
+ if (offset >= NUM_GPRS)
+ return NULL;
+ return gpr_names[offset];
+}
+
+static int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
+{
+ unsigned long ksp = kernel_stack_pointer(regs);
+
+ return (addr & ~(THREAD_SIZE - 1)) == (ksp & ~(THREAD_SIZE - 1));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs:pt_regs which contains kernel stack pointer.
+ * @n:stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specifined by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
+{
+ unsigned long addr;
+
+ addr = kernel_stack_pointer(regs) + n * sizeof(long);
+ if (!regs_within_kernel_stack(regs, addr))
+ return 0;
+ return *(unsigned long *)addr;
+}
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index 2f481cc3d1c9..cb899d9f8505 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -6,7 +6,7 @@
* Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
*/
-#include <asm/lowcore.h>
+#include <asm/asm-offsets.h>
#
# do_reipl_asm
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index 774147824c3d..5e73dee63baa 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -4,7 +4,7 @@
* Denis Joseph Barrow,
*/
-#include <asm/lowcore.h>
+#include <asm/asm-offsets.h>
#
# do_reipl_asm
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index e27ca63076d1..27af3bf3a009 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -9,8 +9,10 @@
*/
LC_EXT_NEW_PSW = 0x58 # addr of ext int handler
+LC_EXT_NEW_PSW_64 = 0x1b0 # addr of ext int handler 64 bit
LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter
LC_EXT_INT_CODE = 0x86 # addr of ext int code
+LC_AR_MODE_ID = 0xa3
#
# Subroutine which waits synchronously until either an external interruption
@@ -30,8 +32,16 @@ _sclp_wait_int:
.LbaseS1:
ahi %r15,-96 # create stack frame
la %r8,LC_EXT_NEW_PSW # register int handler
- mvc .LoldpswS1-.LbaseS1(8,%r13),0(%r8)
- mvc 0(8,%r8),.LextpswS1-.LbaseS1(%r13)
+ la %r9,.LextpswS1-.LbaseS1(%r13)
+#ifdef CONFIG_64BIT
+ tm LC_AR_MODE_ID,1
+ jno .Lesa1
+ la %r8,LC_EXT_NEW_PSW_64 # register int handler 64 bit
+ la %r9,.LextpswS1_64-.LbaseS1(%r13)
+.Lesa1:
+#endif
+ mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
+ mvc 0(16,%r8),0(%r9)
lhi %r6,0x0200 # cr mask for ext int (cr0.54)
ltr %r2,%r2
jz .LsetctS1
@@ -64,15 +74,19 @@ _sclp_wait_int:
.LtimeoutS1:
lctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # restore interrupt setting
# restore old handler
- mvc 0(8,%r8),.LoldpswS1-.LbaseS1(%r13)
+ mvc 0(16,%r8),.LoldpswS1-.LbaseS1(%r13)
lm %r6,%r15,120(%r15) # restore registers
br %r14 # return to caller
.align 8
.LoldpswS1:
- .long 0, 0 # old ext int PSW
+ .long 0, 0, 0, 0 # old ext int PSW
.LextpswS1:
.long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
+#ifdef CONFIG_64BIT
+.LextpswS1_64:
+ .quad 0x0000000180000000, .LwaitS1 # PSW to handle ext int, 64 bit
+#endif
.LwaitpswS1:
.long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
.LtimeS1:
@@ -250,6 +264,13 @@ _sclp_print:
_sclp_print_early:
stm %r6,%r15,24(%r15) # save registers
ahi %r15,-96 # create stack frame
+#ifdef CONFIG_64BIT
+ tm LC_AR_MODE_ID,1
+ jno .Lesa2
+ ahi %r15,-80
+ stmh %r6,%r15,96(%r15) # store upper register halves
+.Lesa2:
+#endif
lr %r10,%r2 # save string pointer
lhi %r2,0
bras %r14,_sclp_setup # enable console
@@ -262,6 +283,13 @@ _sclp_print_early:
lhi %r2,1
bras %r14,_sclp_setup # disable console
.LendS5:
+#ifdef CONFIG_64BIT
+ tm LC_AR_MODE_ID,1
+ jno .Lesa3
+ lmh %r6,%r15,96(%r15) # store upper register halves
+ ahi %r15,80
+.Lesa3:
+#endif
lm %r6,%r15,120(%r15) # restore registers
br %r14
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 8d8957b38ab3..77a63ae419f0 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -396,15 +396,12 @@ static void __init
setup_lowcore(void)
{
struct _lowcore *lc;
- int lc_pages;
/*
* Setup lowcore for boot cpu
*/
- lc_pages = sizeof(void *) == 8 ? 2 : 1;
- lc = (struct _lowcore *)
- __alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0);
- memset(lc, 0, lc_pages * PAGE_SIZE);
+ BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
+ lc = __alloc_bootmem(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
@@ -804,7 +801,7 @@ setup_arch(char **cmdline_p)
if (MACHINE_IS_VM)
pr_info("Linux is running as a z/VM "
"guest operating system in 31-bit mode\n");
- else
+ else if (MACHINE_IS_LPAR)
pr_info("Linux is running natively in 31-bit mode\n");
if (MACHINE_HAS_IEEE)
pr_info("The hardware system has IEEE compatible "
@@ -818,7 +815,7 @@ setup_arch(char **cmdline_p)
"guest operating system in 64-bit mode\n");
else if (MACHINE_IS_KVM)
pr_info("Linux is running under KVM in 64-bit mode\n");
- else
+ else if (MACHINE_IS_LPAR)
pr_info("Linux is running natively in 64-bit mode\n");
#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 76a6fdd46c45..29f65bce55e1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -36,6 +36,7 @@
#include <linux/cpu.h>
#include <linux/timex.h>
#include <linux/bootmem.h>
+#include <asm/asm-offsets.h>
#include <asm/ipl.h>
#include <asm/setup.h>
#include <asm/sigp.h>
@@ -53,7 +54,7 @@
#include "entry.h"
/* logical cpu to cpu address */
-int __cpu_logical_map[NR_CPUS];
+unsigned short __cpu_logical_map[NR_CPUS];
static struct task_struct *current_set[NR_CPUS];
@@ -72,13 +73,13 @@ static int cpu_management;
static DEFINE_PER_CPU(struct cpu, cpu_devices);
-static void smp_ext_bitcall(int, ec_bit_sig);
+static void smp_ext_bitcall(int, int);
-static int cpu_stopped(int cpu)
+static int raw_cpu_stopped(int cpu)
{
- __u32 status;
+ u32 status;
- switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
+ switch (raw_sigp_ps(&status, 0, cpu, sigp_sense)) {
case sigp_status_stored:
/* Check for stopped and check stop state */
if (status & 0x50)
@@ -90,6 +91,44 @@ static int cpu_stopped(int cpu)
return 0;
}
+static inline int cpu_stopped(int cpu)
+{
+ return raw_cpu_stopped(cpu_logical_map(cpu));
+}
+
+void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
+{
+ struct _lowcore *lc, *current_lc;
+ struct stack_frame *sf;
+ struct pt_regs *regs;
+ unsigned long sp;
+
+ if (smp_processor_id() == 0)
+ func(data);
+ __load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY);
+ /* Disable lowcore protection */
+ __ctl_clear_bit(0, 28);
+ current_lc = lowcore_ptr[smp_processor_id()];
+ lc = lowcore_ptr[0];
+ if (!lc)
+ lc = current_lc;
+ lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+ lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
+ if (!cpu_online(0))
+ smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
+ while (sigp(0, sigp_stop_and_store_status) == sigp_busy)
+ cpu_relax();
+ sp = lc->panic_stack;
+ sp -= sizeof(struct pt_regs);
+ regs = (struct pt_regs *) sp;
+ memcpy(&regs->gprs, &current_lc->gpregs_save_area, sizeof(regs->gprs));
+ regs->psw = lc->psw_save_area;
+ sp -= STACK_FRAME_OVERHEAD;
+ sf = (struct stack_frame *) sp;
+ sf->back_chain = regs->gprs[15];
+ smp_switch_to_cpu(func, data, sp, stap(), __cpu_logical_map[0]);
+}
+
void smp_send_stop(void)
{
int cpu, rc;
@@ -103,7 +142,7 @@ void smp_send_stop(void)
if (cpu == smp_processor_id())
continue;
do {
- rc = signal_processor(cpu, sigp_stop);
+ rc = sigp(cpu, sigp_stop);
} while (rc == sigp_busy);
while (!cpu_stopped(cpu))
@@ -139,13 +178,13 @@ static void do_ext_call_interrupt(__u16 code)
* Send an external call sigp to another cpu and return without waiting
* for its completion.
*/
-static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
+static void smp_ext_bitcall(int cpu, int sig)
{
/*
* Set signaling bit in lowcore of target cpu and kick it
*/
set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
- while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
+ while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
udelay(10);
}
@@ -239,24 +278,8 @@ void smp_ctl_clear_bit(int cr, int bit)
}
EXPORT_SYMBOL(smp_ctl_clear_bit);
-/*
- * In early ipl state a temp. logically cpu number is needed, so the sigp
- * functions can be used to sense other cpus. Since NR_CPUS is >= 2 on
- * CONFIG_SMP and the ipl cpu is logical cpu 0, it must be 1.
- */
-#define CPU_INIT_NO 1
-
#ifdef CONFIG_ZFCPDUMP
-/*
- * zfcpdump_prefix_array holds prefix registers for the following scenario:
- * 64 bit zfcpdump kernel and 31 bit kernel which is to be dumped. We have to
- * save its prefix registers, since they get lost, when switching from 31 bit
- * to 64 bit.
- */
-unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
- __attribute__((__section__(".data")));
-
static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
{
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
@@ -266,21 +289,15 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
"the dump\n", cpu, NR_CPUS - 1);
return;
}
- zfcpdump_save_areas[cpu] = kmalloc(sizeof(union save_area), GFP_KERNEL);
- __cpu_logical_map[CPU_INIT_NO] = (__u16) phy_cpu;
- while (signal_processor(CPU_INIT_NO, sigp_stop_and_store_status) ==
- sigp_busy)
+ zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL);
+ while (raw_sigp(phy_cpu, sigp_stop_and_store_status) == sigp_busy)
cpu_relax();
memcpy(zfcpdump_save_areas[cpu],
(void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
- SAVE_AREA_SIZE);
-#ifdef CONFIG_64BIT
- /* copy original prefix register */
- zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu];
-#endif
+ sizeof(struct save_area));
}
-union save_area *zfcpdump_save_areas[NR_CPUS + 1];
+struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
#else
@@ -389,8 +406,7 @@ static void __init smp_detect_cpus(void)
for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) {
if (cpu == boot_cpu_addr)
continue;
- __cpu_logical_map[CPU_INIT_NO] = cpu;
- if (!cpu_stopped(CPU_INIT_NO))
+ if (!raw_cpu_stopped(cpu))
continue;
smp_get_save_area(c_cpus, cpu);
c_cpus++;
@@ -413,8 +429,7 @@ static void __init smp_detect_cpus(void)
cpu_addr = info->cpu[cpu].address;
if (cpu_addr == boot_cpu_addr)
continue;
- __cpu_logical_map[CPU_INIT_NO] = cpu_addr;
- if (!cpu_stopped(CPU_INIT_NO)) {
+ if (!raw_cpu_stopped(cpu_addr)) {
s_cpus++;
continue;
}
@@ -533,18 +548,18 @@ static void smp_free_lowcore(int cpu)
/* Upping and downing of CPUs */
int __cpuinit __cpu_up(unsigned int cpu)
{
- struct task_struct *idle;
struct _lowcore *cpu_lowcore;
+ struct task_struct *idle;
struct stack_frame *sf;
- sigp_ccode ccode;
u32 lowcore;
+ int ccode;
if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
return -EIO;
if (smp_alloc_lowcore(cpu))
return -ENOMEM;
do {
- ccode = signal_processor(cpu, sigp_initial_cpu_reset);
+ ccode = sigp(cpu, sigp_initial_cpu_reset);
if (ccode == sigp_busy)
udelay(10);
if (ccode == sigp_not_operational)
@@ -552,7 +567,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
} while (ccode == sigp_busy);
lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
- while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
+ while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
udelay(10);
idle = current_set[cpu];
@@ -578,7 +593,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
eieio();
- while (signal_processor(cpu, sigp_restart) == sigp_busy)
+ while (sigp(cpu, sigp_restart) == sigp_busy)
udelay(10);
while (!cpu_online(cpu))
@@ -640,7 +655,7 @@ void __cpu_die(unsigned int cpu)
/* Wait until target cpu is down */
while (!cpu_stopped(cpu))
cpu_relax();
- while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy)
+ while (sigp_p(0, cpu, sigp_set_prefix) == sigp_busy)
udelay(10);
smp_free_lowcore(cpu);
pr_info("Processor %d stopped\n", cpu);
@@ -649,7 +664,7 @@ void __cpu_die(unsigned int cpu)
void cpu_die(void)
{
idle_task_exit();
- while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+ while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
cpu_relax();
for (;;);
}
@@ -765,7 +780,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev,
get_online_cpus();
mutex_lock(&smp_cpu_state_mutex);
rc = -EBUSY;
- if (cpu_online(cpu))
+ /* disallow configuration changes of online cpus and cpu 0 */
+ if (cpu_online(cpu) || cpu == 0)
goto out;
rc = 0;
switch (val) {
@@ -1004,7 +1020,9 @@ out:
return rc;
}
-static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf,
+static ssize_t __ref rescan_store(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ const char *buf,
size_t count)
{
int rc;
@@ -1015,7 +1033,9 @@ static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf,
static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store);
#endif /* CONFIG_HOTPLUG_CPU */
-static ssize_t dispatching_show(struct sysdev_class *class, char *buf)
+static ssize_t dispatching_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
ssize_t count;
@@ -1025,7 +1045,9 @@ static ssize_t dispatching_show(struct sysdev_class *class, char *buf)
return count;
}
-static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf,
+static ssize_t dispatching_store(struct sysdev_class *dev,
+ struct sysdev_class_attribute *attr,
+ const char *buf,
size_t count)
{
int val, rc;
diff --git a/arch/s390/kernel/switch_cpu.S b/arch/s390/kernel/switch_cpu.S
new file mode 100644
index 000000000000..469f11b574fa
--- /dev/null
+++ b/arch/s390/kernel/switch_cpu.S
@@ -0,0 +1,58 @@
+/*
+ * 31-bit switch cpu code
+ *
+ * Copyright IBM Corp. 2009
+ *
+ */
+
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
+
+# smp_switch_to_cpu switches to destination cpu and executes the passed function
+# Parameter: %r2 - function to call
+# %r3 - function parameter
+# %r4 - stack poiner
+# %r5 - current cpu
+# %r6 - destination cpu
+
+ .section .text
+ .align 4
+ .globl smp_switch_to_cpu
+smp_switch_to_cpu:
+ stm %r6,%r15,__SF_GPRS(%r15)
+ lr %r1,%r15
+ ahi %r15,-STACK_FRAME_OVERHEAD
+ st %r1,__SF_BACKCHAIN(%r15)
+ basr %r13,0
+0: la %r1,.gprregs_addr-0b(%r13)
+ l %r1,0(%r1)
+ stm %r0,%r15,0(%r1)
+1: sigp %r0,%r6,__SIGP_RESTART /* start destination CPU */
+ brc 2,1b /* busy, try again */
+2: sigp %r0,%r5,__SIGP_STOP /* stop current CPU */
+ brc 2,2b /* busy, try again */
+3: j 3b
+
+ .globl smp_restart_cpu
+smp_restart_cpu:
+ basr %r13,0
+0: la %r1,.gprregs_addr-0b(%r13)
+ l %r1,0(%r1)
+ lm %r0,%r15,0(%r1)
+1: sigp %r0,%r5,__SIGP_SENSE /* Wait for calling CPU */
+ brc 10,1b /* busy, accepted (status 0), running */
+ tmll %r0,0x40 /* Test if calling CPU is stopped */
+ jz 1b
+ ltr %r4,%r4 /* New stack ? */
+ jz 1f
+ lr %r15,%r4
+1: basr %r14,%r2
+
+.gprregs_addr:
+ .long .gprregs
+
+ .section .data,"aw",@progbits
+.gprregs:
+ .rept 16
+ .long 0
+ .endr
diff --git a/arch/s390/kernel/switch_cpu64.S b/arch/s390/kernel/switch_cpu64.S
new file mode 100644
index 000000000000..d94aacc898cb
--- /dev/null
+++ b/arch/s390/kernel/switch_cpu64.S
@@ -0,0 +1,51 @@
+/*
+ * 64-bit switch cpu code
+ *
+ * Copyright IBM Corp. 2009
+ *
+ */
+
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
+
+# smp_switch_to_cpu switches to destination cpu and executes the passed function
+# Parameter: %r2 - function to call
+# %r3 - function parameter
+# %r4 - stack poiner
+# %r5 - current cpu
+# %r6 - destination cpu
+
+ .section .text
+ .align 4
+ .globl smp_switch_to_cpu
+smp_switch_to_cpu:
+ stmg %r6,%r15,__SF_GPRS(%r15)
+ lgr %r1,%r15
+ aghi %r15,-STACK_FRAME_OVERHEAD
+ stg %r1,__SF_BACKCHAIN(%r15)
+ larl %r1,.gprregs
+ stmg %r0,%r15,0(%r1)
+1: sigp %r0,%r6,__SIGP_RESTART /* start destination CPU */
+ brc 2,1b /* busy, try again */
+2: sigp %r0,%r5,__SIGP_STOP /* stop current CPU */
+ brc 2,2b /* busy, try again */
+3: j 3b
+
+ .globl smp_restart_cpu
+smp_restart_cpu:
+ larl %r1,.gprregs
+ lmg %r0,%r15,0(%r1)
+1: sigp %r0,%r5,__SIGP_SENSE /* Wait for calling CPU */
+ brc 10,1b /* busy, accepted (status 0), running */
+ tmll %r0,0x40 /* Test if calling CPU is stopped */
+ jz 1b
+ ltgr %r4,%r4 /* New stack ? */
+ jz 1f
+ lgr %r15,%r4
+1: basr %r14,%r2
+
+ .section .data,"aw",@progbits
+.gprregs:
+ .rept 16
+ .quad 0
+ .endr
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index 0c26cc1898ec..b354427e03b7 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -176,7 +176,7 @@ pgm_check_entry:
cgr %r1,%r2
je restore_registers /* r1 = r2 -> nothing to do */
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
- mvc __LC_RESTART_PSW(16,%r0),0(%r4)
+ mvc __LC_RST_NEW_PSW(16,%r0),0(%r4)
3:
sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET
brc 8,4f /* accepted */
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 65065ac48ed3..aa2483e460f3 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -51,14 +51,6 @@
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
-/*
- * Create a small time difference between the timer interrupts
- * on the different cpus to avoid lock contention.
- */
-#define CPU_DEVIATION (smp_processor_id() << 12)
-
-#define TICK_SIZE tick
-
u64 sched_clock_base_cc = -1; /* Force to data section. */
EXPORT_SYMBOL_GPL(sched_clock_base_cc);
@@ -81,15 +73,15 @@ unsigned long long monotonic_clock(void)
}
EXPORT_SYMBOL(monotonic_clock);
-void tod_to_timeval(__u64 todval, struct timespec *xtime)
+void tod_to_timeval(__u64 todval, struct timespec *xt)
{
unsigned long long sec;
sec = todval >> 12;
do_div(sec, 1000000);
- xtime->tv_sec = sec;
+ xt->tv_sec = sec;
todval -= (sec * 1000000) << 12;
- xtime->tv_nsec = ((todval * 1000) >> 12);
+ xt->tv_nsec = ((todval * 1000) >> 12);
}
EXPORT_SYMBOL(tod_to_timeval);
@@ -224,8 +216,8 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
++vdso_data->tb_update_count;
smp_wmb();
vdso_data->xtime_tod_stamp = clock->cycle_last;
- vdso_data->xtime_clock_sec = xtime.tv_sec;
- vdso_data->xtime_clock_nsec = xtime.tv_nsec;
+ vdso_data->xtime_clock_sec = wall_time->tv_sec;
+ vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
smp_wmb();
@@ -1124,14 +1116,18 @@ static struct sys_device etr_port1_dev = {
/*
* ETR class attributes
*/
-static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf)
+static ssize_t etr_stepping_port_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%i\n", etr_port0.esw.p);
}
static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL);
-static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf)
+static ssize_t etr_stepping_mode_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
char *mode_str;
@@ -1592,7 +1588,9 @@ static struct sysdev_class stp_sysclass = {
.name = "stp",
};
-static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_ctn_id_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1602,7 +1600,9 @@ static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
-static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_ctn_type_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1611,7 +1611,9 @@ static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
-static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_dst_offset_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x2000))
return -ENODATA;
@@ -1620,7 +1622,9 @@ static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
-static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_leap_seconds_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x8000))
return -ENODATA;
@@ -1629,7 +1633,9 @@ static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
-static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_stratum_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1638,7 +1644,9 @@ static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL);
-static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_time_offset_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x0800))
return -ENODATA;
@@ -1647,7 +1655,9 @@ static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
-static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_time_zone_offset_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x4000))
return -ENODATA;
@@ -1657,7 +1667,9 @@ static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(time_zone_offset, 0400,
stp_time_zone_offset_show, NULL);
-static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_timing_mode_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1666,7 +1678,9 @@ static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
-static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_timing_state_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1675,12 +1689,15 @@ static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
-static ssize_t stp_online_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_online_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%i\n", stp_online);
}
static ssize_t stp_online_store(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
const char *buf, size_t count)
{
unsigned int value;
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 5f99e66c51c3..6bc9c197aa91 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -23,6 +23,7 @@
#include <linux/security.h>
#include <linux/bootmem.h>
#include <linux/compat.h>
+#include <asm/asm-offsets.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>