aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/lowcore.h100
-rw-r--r--arch/s390/include/asm/sigp.h132
-rw-r--r--arch/s390/include/asm/smp.h63
-rw-r--r--arch/s390/include/asm/vdso.h4
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/asm-offsets.c17
-rw-r--r--arch/s390/kernel/entry.S81
-rw-r--r--arch/s390/kernel/entry.h9
-rw-r--r--arch/s390/kernel/entry64.S72
-rw-r--r--arch/s390/kernel/ipl.c21
-rw-r--r--arch/s390/kernel/machine_kexec.c43
-rw-r--r--arch/s390/kernel/setup.c56
-rw-r--r--arch/s390/kernel/smp.c1083
-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.S12
-rw-r--r--arch/s390/kernel/topology.c8
-rw-r--r--arch/s390/kernel/vdso.c28
-rw-r--r--arch/s390/kernel/vtime.c3
-rw-r--r--arch/s390/lib/spinlock.c30
-rw-r--r--drivers/s390/char/sclp_quiesce.c1
-rw-r--r--drivers/s390/char/zcore.c1
22 files changed, 739 insertions, 1136 deletions
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 0831449e87a..4e69563bc95 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 1999,2010
+ * Copyright IBM Corp. 1999,2012
* Author(s): Hartmut Penner <hp@de.ibm.com>,
* Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Denis Joseph Barrow,
@@ -12,14 +12,6 @@
#include <asm/ptrace.h>
#include <asm/cpu.h>
-void restart_int_handler(void);
-void ext_int_handler(void);
-void system_call(void);
-void pgm_check_handler(void);
-void mcck_int_handler(void);
-void io_int_handler(void);
-void psw_restart_int_handler(void);
-
#ifdef CONFIG_32BIT
#define LC_ORDER 0
@@ -117,32 +109,37 @@ struct _lowcore {
__u64 steal_timer; /* 0x0288 */
__u64 last_update_timer; /* 0x0290 */
__u64 last_update_clock; /* 0x0298 */
+ __u64 int_clock; /* 0x02a0 */
+ __u64 mcck_clock; /* 0x02a8 */
+ __u64 clock_comparator; /* 0x02b0 */
/* Current process. */
- __u32 current_task; /* 0x02a0 */
- __u32 thread_info; /* 0x02a4 */
- __u32 kernel_stack; /* 0x02a8 */
+ __u32 current_task; /* 0x02b8 */
+ __u32 thread_info; /* 0x02bc */
+ __u32 kernel_stack; /* 0x02c0 */
+
+ /* Interrupt, panic and restart stack. */
+ __u32 async_stack; /* 0x02c4 */
+ __u32 panic_stack; /* 0x02c8 */
+ __u32 restart_stack; /* 0x02cc */
- /* Interrupt and panic stack. */
- __u32 async_stack; /* 0x02ac */
- __u32 panic_stack; /* 0x02b0 */
+ /* Restart function and parameter. */
+ __u32 restart_fn; /* 0x02d0 */
+ __u32 restart_data; /* 0x02d4 */
+ __u32 restart_source; /* 0x02d8 */
/* Address space pointer. */
- __u32 kernel_asce; /* 0x02b4 */
- __u32 user_asce; /* 0x02b8 */
- __u32 current_pid; /* 0x02bc */
+ __u32 kernel_asce; /* 0x02dc */
+ __u32 user_asce; /* 0x02e0 */
+ __u32 current_pid; /* 0x02e4 */
/* SMP info area */
- __u32 cpu_nr; /* 0x02c0 */
- __u32 softirq_pending; /* 0x02c4 */
- __u32 percpu_offset; /* 0x02c8 */
- __u32 ext_call_fast; /* 0x02cc */
- __u64 int_clock; /* 0x02d0 */
- __u64 mcck_clock; /* 0x02d8 */
- __u64 clock_comparator; /* 0x02e0 */
- __u32 machine_flags; /* 0x02e8 */
- __u32 ftrace_func; /* 0x02ec */
- __u8 pad_0x02f8[0x0300-0x02f0]; /* 0x02f0 */
+ __u32 cpu_nr; /* 0x02e8 */
+ __u32 softirq_pending; /* 0x02ec */
+ __u32 percpu_offset; /* 0x02f0 */
+ __u32 machine_flags; /* 0x02f4 */
+ __u32 ftrace_func; /* 0x02f8 */
+ __u8 pad_0x02fc[0x0300-0x02fc]; /* 0x02fc */
/* Interrupt response block */
__u8 irb[64]; /* 0x0300 */
@@ -254,34 +251,39 @@ struct _lowcore {
__u64 steal_timer; /* 0x02e0 */
__u64 last_update_timer; /* 0x02e8 */
__u64 last_update_clock; /* 0x02f0 */
+ __u64 int_clock; /* 0x02f8 */
+ __u64 mcck_clock; /* 0x0300 */
+ __u64 clock_comparator; /* 0x0308 */
/* Current process. */
- __u64 current_task; /* 0x02f8 */
- __u64 thread_info; /* 0x0300 */
- __u64 kernel_stack; /* 0x0308 */
+ __u64 current_task; /* 0x0310 */
+ __u64 thread_info; /* 0x0318 */
+ __u64 kernel_stack; /* 0x0320 */
+
+ /* Interrupt, panic and restart stack. */
+ __u64 async_stack; /* 0x0328 */
+ __u64 panic_stack; /* 0x0330 */
+ __u64 restart_stack; /* 0x0338 */
- /* Interrupt and panic stack. */
- __u64 async_stack; /* 0x0310 */
- __u64 panic_stack; /* 0x0318 */
+ /* Restart function and parameter. */
+ __u64 restart_fn; /* 0x0340 */
+ __u64 restart_data; /* 0x0348 */
+ __u64 restart_source; /* 0x0350 */
/* Address space pointer. */
- __u64 kernel_asce; /* 0x0320 */
- __u64 user_asce; /* 0x0328 */
- __u64 current_pid; /* 0x0330 */
+ __u64 kernel_asce; /* 0x0358 */
+ __u64 user_asce; /* 0x0360 */
+ __u64 current_pid; /* 0x0368 */
/* SMP info area */
- __u32 cpu_nr; /* 0x0338 */
- __u32 softirq_pending; /* 0x033c */
- __u64 percpu_offset; /* 0x0340 */
- __u64 ext_call_fast; /* 0x0348 */
- __u64 int_clock; /* 0x0350 */
- __u64 mcck_clock; /* 0x0358 */
- __u64 clock_comparator; /* 0x0360 */
- __u64 vdso_per_cpu_data; /* 0x0368 */
- __u64 machine_flags; /* 0x0370 */
- __u64 ftrace_func; /* 0x0378 */
- __u64 gmap; /* 0x0380 */
- __u8 pad_0x0388[0x0400-0x0388]; /* 0x0388 */
+ __u32 cpu_nr; /* 0x0370 */
+ __u32 softirq_pending; /* 0x0374 */
+ __u64 percpu_offset; /* 0x0378 */
+ __u64 vdso_per_cpu_data; /* 0x0380 */
+ __u64 machine_flags; /* 0x0388 */
+ __u64 ftrace_func; /* 0x0390 */
+ __u64 gmap; /* 0x0398 */
+ __u8 pad_0x03a0[0x0400-0x03a0]; /* 0x03a0 */
/* Interrupt response block. */
__u8 irb[64]; /* 0x0400 */
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
deleted file mode 100644
index 7040b8567cd..00000000000
--- a/arch/s390/include/asm/sigp.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Routines and structures for signalling other processors.
- *
- * Copyright IBM Corp. 1999,2010
- * Author(s): Denis Joseph Barrow,
- * Martin Schwidefsky <schwidefsky@de.ibm.com>,
- * Heiko Carstens <heiko.carstens@de.ibm.com>,
- */
-
-#ifndef __ASM_SIGP_H
-#define __ASM_SIGP_H
-
-#include <asm/system.h>
-
-/* Get real cpu address from logical cpu number. */
-extern unsigned short __cpu_logical_map[];
-
-static inline int cpu_logical_map(int cpu)
-{
-#ifdef CONFIG_SMP
- return __cpu_logical_map[cpu];
-#else
- return stap();
-#endif
-}
-
-enum {
- sigp_sense = 1,
- sigp_external_call = 2,
- sigp_emergency_signal = 3,
- sigp_start = 4,
- sigp_stop = 5,
- sigp_restart = 6,
- sigp_stop_and_store_status = 9,
- sigp_initial_cpu_reset = 11,
- sigp_cpu_reset = 12,
- sigp_set_prefix = 13,
- sigp_store_status_at_address = 14,
- sigp_store_extended_status_at_address = 15,
- sigp_set_architecture = 18,
- sigp_conditional_emergency_signal = 19,
- sigp_sense_running = 21,
-};
-
-enum {
- sigp_order_code_accepted = 0,
- sigp_status_stored = 1,
- sigp_busy = 2,
- sigp_not_operational = 3,
-};
-
-/*
- * Definitions for external call.
- */
-enum {
- ec_schedule = 0,
- ec_call_function,
- ec_call_function_single,
- ec_stop_cpu,
-};
-
-/*
- * Signal processor.
- */
-static inline int raw_sigp(u16 cpu, int order)
-{
- register unsigned long reg1 asm ("1") = 0;
- int ccode;
-
- asm volatile(
- " sigp %1,%2,0(%3)\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (ccode)
- : "d" (reg1), "d" (cpu),
- "a" (order) : "cc" , "memory");
- return ccode;
-}
-
-/*
- * Signal processor with parameter.
- */
-static inline int raw_sigp_p(u32 parameter, u16 cpu, int order)
-{
- register unsigned int reg1 asm ("1") = parameter;
- int ccode;
-
- asm volatile(
- " sigp %1,%2,0(%3)\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (ccode)
- : "d" (reg1), "d" (cpu),
- "a" (order) : "cc" , "memory");
- return ccode;
-}
-
-/*
- * Signal processor with parameter and return status.
- */
-static inline int raw_sigp_ps(u32 *status, u32 parm, u16 cpu, int order)
-{
- register unsigned int reg1 asm ("1") = parm;
- int ccode;
-
- asm volatile(
- " sigp %1,%2,0(%3)\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (ccode), "+d" (reg1)
- : "d" (cpu), "a" (order)
- : "cc" , "memory");
- *status = reg1;
- return ccode;
-}
-
-static inline int sigp(int cpu, int order)
-{
- return raw_sigp(cpu_logical_map(cpu), order);
-}
-
-static inline int sigp_p(u32 parameter, int cpu, int order)
-{
- return raw_sigp_p(parameter, cpu_logical_map(cpu), order);
-}
-
-static inline int sigp_ps(u32 *status, u32 parm, int cpu, int order)
-{
- return raw_sigp_ps(status, parm, cpu_logical_map(cpu), order);
-}
-
-#endif /* __ASM_SIGP_H */
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index c32e9123b40..797f7872968 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -1,5 +1,5 @@
/*
- * Copyright IBM Corp. 1999,2009
+ * Copyright IBM Corp. 1999,2012
* Author(s): Denis Joseph Barrow,
* Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Heiko Carstens <heiko.carstens@de.ibm.com>,
@@ -10,71 +10,52 @@
#ifdef CONFIG_SMP
#include <asm/system.h>
-#include <asm/sigp.h>
-
-extern void machine_restart_smp(char *);
-extern void machine_halt_smp(void);
-extern void machine_power_off_smp(void);
#define raw_smp_processor_id() (S390_lowcore.cpu_nr)
-extern int __cpu_disable (void);
-extern void __cpu_die (unsigned int cpu);
-extern int __cpu_up (unsigned int cpu);
-
extern struct mutex smp_cpu_state_mutex;
+extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
+
+extern int __cpu_up(unsigned int cpu);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
-
-extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *);
-extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp,
- int from, int to);
-extern void smp_restart_with_online_cpu(void);
-extern void smp_restart_cpu(void);
+extern void smp_call_online_cpu(void (*func)(void *), void *);
+extern void smp_call_ipl_cpu(void (*func)(void *), void *);
-/*
- * returns 1 if (virtual) cpu is scheduled
- * returns 0 otherwise
- */
-static inline int smp_vcpu_scheduled(int cpu)
-{
- u32 status;
-
- switch (sigp_ps(&status, 0, cpu, sigp_sense_running)) {
- case sigp_status_stored:
- /* Check for running status */
- if (status & 0x400)
- return 0;
- break;
- case sigp_not_operational:
- return 0;
- default:
- break;
- }
- return 1;
-}
+extern int smp_find_processor_id(u16 address);
+extern int smp_store_status(int cpu);
+extern int smp_vcpu_scheduled(int cpu);
+extern void smp_yield_cpu(int cpu);
+extern void smp_yield(void);
+extern void smp_stop_cpu(void);
#else /* CONFIG_SMP */
-static inline void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
+static inline void smp_call_ipl_cpu(void (*func)(void *), void *data)
{
func(data);
}
-static inline void smp_restart_with_online_cpu(void)
+static inline void smp_call_online_cpu(void (*func)(void *), void *data)
{
+ func(data);
}
-#define smp_vcpu_scheduled (1)
+static inline int smp_find_processor_id(int address) { return 0; }
+static inline int smp_vcpu_scheduled(int cpu) { return 1; }
+static inline void smp_yield_cpu(int cpu) { }
+static inline void smp_yield(void) { }
+static inline void smp_stop_cpu(void) { }
#endif /* CONFIG_SMP */
#ifdef CONFIG_HOTPLUG_CPU
extern int smp_rescan_cpus(void);
extern void __noreturn cpu_die(void);
+extern void __cpu_die(unsigned int cpu);
+extern int __cpu_disable(void);
#else
static inline int smp_rescan_cpus(void) { return 0; }
static inline void cpu_die(void) { }
diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h
index 533f35751ae..c4a11cfad3c 100644
--- a/arch/s390/include/asm/vdso.h
+++ b/arch/s390/include/asm/vdso.h
@@ -40,8 +40,8 @@ struct vdso_per_cpu_data {
extern struct vdso_data *vdso_data;
#ifdef CONFIG_64BIT
-int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore);
-void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore);
+int vdso_alloc_per_cpu(struct _lowcore *lowcore);
+void vdso_free_per_cpu(struct _lowcore *lowcore);
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 7d9ec924e7e..d0a48268eb2 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -34,8 +34,6 @@ extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o)
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SCHED_BOOK) += 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 530ae0e8e38..aeeaf896be9 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -9,8 +9,8 @@
#include <linux/kbuild.h>
#include <linux/sched.h>
#include <asm/vdso.h>
-#include <asm/sigp.h>
#include <asm/pgtable.h>
+#include <asm/system.h>
/*
* Make sure that the compiler is new enough. We want a compiler that
@@ -70,12 +70,6 @@ int main(void)
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_EXT_CPU_ADDR, offsetof(struct _lowcore, ext_cpu_addr));
@@ -95,20 +89,19 @@ int main(void)
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_RST_NEW_PSW, offsetof(struct _lowcore, restart_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));
+ BLANK();
DEFINE(__LC_SAVE_AREA_SYNC, offsetof(struct _lowcore, save_area_sync));
DEFINE(__LC_SAVE_AREA_ASYNC, offsetof(struct _lowcore, save_area_async));
DEFINE(__LC_SAVE_AREA_RESTART, offsetof(struct _lowcore, save_area_restart));
@@ -129,12 +122,16 @@ int main(void)
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_RESTART_STACK, offsetof(struct _lowcore, restart_stack));
+ DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn));
DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_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_DUMP_REIPL, offsetof(struct _lowcore, ipib));
+ BLANK();
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));
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 5f437b830da..6143521a4ff 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -2,7 +2,7 @@
* arch/s390/kernel/entry.S
* S390 low-level entry points.
*
- * Copyright (C) IBM Corp. 1999,2006
+ * Copyright (C) IBM Corp. 1999,2012
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Hartmut Penner (hp@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -691,77 +691,30 @@ mcck_panic:
0: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j mcck_skip
-/*
- * Restart interruption handler, kick starter for additional CPUs
- */
-#ifdef CONFIG_SMP
- __CPUINIT
-ENTRY(restart_int_handler)
- basr %r1,0
-restart_base:
- spt restart_vtime-restart_base(%r1)
- stck __LC_LAST_UPDATE_CLOCK
- mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
- mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
- l %r15,__LC_GPREGS_SAVE_AREA+60 # load ksp
- lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
- lam %a0,%a15,__LC_AREGS_SAVE_AREA
- lm %r6,%r15,__SF_GPRS(%r15)# load registers from clone
- l %r1,__LC_THREAD_INFO
- mvc __LC_USER_TIMER(8),__TI_user_timer(%r1)
- mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
- xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER
- ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off
- basr %r14,0
- l %r14,restart_addr-.(%r14)
- basr %r14,%r14 # call start_secondary
-restart_addr:
- .long start_secondary
- .align 8
-restart_vtime:
- .long 0x7fffffff,0xffffffff
- .previous
-#else
-/*
- * If we do not run with SMP enabled, let the new CPU crash ...
- */
-ENTRY(restart_int_handler)
- basr %r1,0
-restart_base:
- lpsw restart_crash-restart_base(%r1)
- .align 8
-restart_crash:
- .long 0x000a0000,0x00000000
-restart_go:
-#endif
-
#
# PSW restart interrupt handler
#
-ENTRY(psw_restart_int_handler)
+ENTRY(restart_int_handler)
st %r15,__LC_SAVE_AREA_RESTART
- basr %r15,0
-0: l %r15,.Lrestart_stack-0b(%r15) # load restart stack
- l %r15,0(%r15)
+ l %r15,__LC_RESTART_STACK
ahi %r15,-__PT_SIZE # create pt_regs on stack
+ xc 0(__PT_SIZE,%r15),0(%r15)
stm %r0,%r14,__PT_R0(%r15)
mvc __PT_R15(4,%r15),__LC_SAVE_AREA_RESTART
mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw
- ahi %r15,-STACK_FRAME_OVERHEAD
- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
- basr %r14,0
-1: l %r14,.Ldo_restart-1b(%r14)
- basr %r14,%r14
- basr %r14,0 # load disabled wait PSW if
-2: lpsw restart_psw_crash-2b(%r14) # do_restart returns
- .align 4
-.Ldo_restart:
- .long do_restart
-.Lrestart_stack:
- .long restart_stack
- .align 8
-restart_psw_crash:
- .long 0x000a0000,0x00000000 + restart_psw_crash
+ ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
+ xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
+ lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu
+ ltr %r3,%r3 # test source cpu address
+ jm 1f # negative -> skip source stop
+0: sigp %r4,%r3,1 # sigp sense to source cpu
+ brc 10,0b # wait for status stored
+1: basr %r14,%r1 # call function
+ stap __SF_EMPTY(%r15) # store cpu address
+ lh %r3,__SF_EMPTY(%r15)
+2: sigp %r4,%r3,5 # sigp stop to current cpu
+ brc 2,2b
+3: j 3b
.section .kprobes.text, "ax"
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index bf538aaf407..92b1617d0c9 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -9,6 +9,14 @@
extern void (*pgm_check_table[128])(struct pt_regs *);
extern void *restart_stack;
+void system_call(void);
+void pgm_check_handler(void);
+void ext_int_handler(void);
+void io_int_handler(void);
+void mcck_int_handler(void);
+void restart_int_handler(void);
+void restart_call_handler(void);
+
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
@@ -26,7 +34,6 @@ void do_notify_resume(struct pt_regs *regs);
void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
void do_restart(void);
-int __cpuinit start_secondary(void *cpuvoid);
void __init startup_init(void);
void die(struct pt_regs *regs, const char *str);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index bacbd2848d4..e33789a4575 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -2,7 +2,7 @@
* arch/s390/kernel/entry64.S
* S390 low-level entry points.
*
- * Copyright (C) IBM Corp. 1999,2010
+ * Copyright (C) IBM Corp. 1999,2012
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Hartmut Penner (hp@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -713,68 +713,30 @@ mcck_panic:
0: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j mcck_skip
-/*
- * Restart interruption handler, kick starter for additional CPUs
- */
-#ifdef CONFIG_SMP
- __CPUINIT
-ENTRY(restart_int_handler)
- basr %r1,0
-restart_base:
- spt restart_vtime-restart_base(%r1)
- stck __LC_LAST_UPDATE_CLOCK
- mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
- mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
- lghi %r10,__LC_GPREGS_SAVE_AREA
- lg %r15,120(%r10) # load ksp
- lghi %r10,__LC_CREGS_SAVE_AREA
- lctlg %c0,%c15,0(%r10) # get new ctl regs
- lghi %r10,__LC_AREGS_SAVE_AREA
- lam %a0,%a15,0(%r10)
- lmg %r6,%r15,__SF_GPRS(%r15)# load registers from clone
- lg %r1,__LC_THREAD_INFO
- mvc __LC_USER_TIMER(8),__TI_user_timer(%r1)
- mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
- xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER
- ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off
- brasl %r14,start_secondary
- .align 8
-restart_vtime:
- .long 0x7fffffff,0xffffffff
- .previous
-#else
-/*
- * If we do not run with SMP enabled, let the new CPU crash ...
- */
-ENTRY(restart_int_handler)
- basr %r1,0
-restart_base:
- lpswe restart_crash-restart_base(%r1)
- .align 8
-restart_crash:
- .long 0x000a0000,0x00000000,0x00000000,0x00000000
-restart_go:
-#endif
-
#
# PSW restart interrupt handler
#
-ENTRY(psw_restart_int_handler)
+ENTRY(restart_int_handler)
stg %r15,__LC_SAVE_AREA_RESTART
- larl %r15,restart_stack # load restart stack
- lg %r15,0(%r15)
+ lg %r15,__LC_RESTART_STACK
aghi %r15,-__PT_SIZE # create pt_regs on stack
+ xc 0(__PT_SIZE,%r15),0(%r15)
stmg %r0,%r14,__PT_R0(%r15)
mvc __PT_R15(8,%r15),__LC_SAVE_AREA_RESTART
mvc __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw
- aghi %r15,-STACK_FRAME_OVERHEAD
- xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
- brasl %r14,do_restart
- larl %r14,restart_psw_crash # load disabled wait PSW if
- lpswe 0(%r14) # do_restart returns
- .align 8
-restart_psw_crash:
- .quad 0x0002000080000000,0x0000000000000000 + restart_psw_crash
+ aghi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
+ xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
+ lmg %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu
+ ltgr %r3,%r3 # test source cpu address
+ jm 1f # negative -> skip source stop
+0: sigp %r4,%r3,1 # sigp sense to source cpu
+ brc 10,0b # wait for status stored
+1: basr %r14,%r1 # call function
+ stap __SF_EMPTY(%r15) # store cpu address
+ llgh %r3,__SF_EMPTY(%r15)
+2: sigp %r4,%r3,5 # sigp stop to current cpu
+ brc 2,2b
+3: j 3b
.section .kprobes.text, "ax"
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index affa8e68124..e5a72a2b0c5 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2,7 +2,7 @@
* arch/s390/kernel/ipl.c
* ipl/reipl/dump support for Linux on s390.
*
- * Copyright IBM Corp. 2005,2007
+ * Copyright IBM Corp. 2005,2012
* Author(s): Michael Holzheu <holzheu@de.ibm.com>
* Heiko Carstens <heiko.carstens@de.ibm.com>
* Volker Sameske <sameske@de.ibm.com>
@@ -25,7 +25,6 @@
#include <asm/ebcdic.h>
#include <asm/reset.h>
#include <asm/sclp.h>
-#include <asm/sigp.h>
#include <asm/checksum.h>
#include "entry.h"
@@ -571,7 +570,7 @@ static void __ipl_run(void *unused)
static void ipl_run(struct shutdown_trigger *trigger)
{
- smp_switch_to_ipl_cpu(__ipl_run, NULL);
+ smp_call_ipl_cpu(__ipl_run, NULL);
}
static int __init ipl_init(void)
@@ -1101,7 +1100,7 @@ static void __reipl_run(void *unused)
static void reipl_run(struct shutdown_trigger *trigger)
{
- smp_switch_to_ipl_cpu(__reipl_run, NULL);
+ smp_call_ipl_cpu(__reipl_run, NULL);
}
static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
@@ -1421,7 +1420,7 @@ 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);
+ smp_call_ipl_cpu(__dump_run, NULL);
}
static int __init dump_ccw_init(void)
@@ -1623,9 +1622,7 @@ static void stop_run(struct shutdown_trigger *trigger)
if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
strcmp(trigger->name, ON_RESTART_STR) == 0)
disabled_wait((unsigned long) __builtin_return_address(0));
- while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
- cpu_relax();
- for (;;);
+ smp_stop_cpu();
}
static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
@@ -1738,9 +1735,8 @@ static ssize_t on_restart_store(struct kobject *kobj,
static struct kobj_attribute on_restart_attr =
__ATTR(on_restart, 0644, on_restart_show, on_restart_store);
-void do_restart(void)
+static void __do_restart(void *ignore)
{
- smp_restart_with_online_cpu();
smp_send_stop();
#ifdef CONFIG_CRASH_DUMP
crash_kexec(NULL);
@@ -1749,6 +1745,11 @@ void do_restart(void)
stop_run(&on_restart_trigger);
}
+void do_restart(void)
+{
+ smp_call_online_cpu(__do_restart, NULL);
+}
+
/* on halt */
static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 47b168fb29c..bf6fbc03eba 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -49,50 +49,21 @@ static void add_elf_notes(int cpu)
}
/*
- * Store status of next available physical CPU
- */
-static int store_status_next(int start_cpu, int this_cpu)
-{
- struct save_area *sa = (void *) 4608 + store_prefix();
- int cpu, rc;
-
- for (cpu = start_cpu; cpu < 65536; cpu++) {
- if (cpu == this_cpu)
- continue;
- do {
- rc = raw_sigp(cpu, sigp_stop_and_store_status);
- } while (rc == sigp_busy);
- if (rc != sigp_order_code_accepted)
- continue;
- if (sa->pref_reg)
- return cpu;
- }
- return -1;
-}
-
-/*
* Initialize CPU ELF notes
*/
void setup_regs(void)
{
unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE;
- int cpu, this_cpu, phys_cpu = 0, first = 1;
+ int cpu, this_cpu;
- this_cpu = stap();
-
- if (!S390_lowcore.prefixreg_save_area)
- first = 0;
+ this_cpu = smp_find_processor_id(stap());
+ add_elf_notes(this_cpu);
for_each_online_cpu(cpu) {
- if (first) {
- add_elf_notes(cpu);
- first = 0;
+ if (cpu == this_cpu)
+ continue;
+ if (smp_store_status(cpu))
continue;
- }
- phys_cpu = store_status_next(phys_cpu, this_cpu);
- if (phys_cpu == -1)
- break;
add_elf_notes(cpu);
- phys_cpu++;
}
/* Copy dump CPU store status info to absolute zero */
memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
@@ -255,5 +226,5 @@ void machine_kexec(struct kimage *image)
return;
tracer_disable();
smp_send_stop();
- smp_switch_to_ipl_cpu(__machine_kexec, image);
+ smp_call_ipl_cpu(__machine_kexec, image);
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 778c100fe31..9a3edb5f2c9 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -2,7 +2,7 @@
* arch/s390/kernel/setup.c
*
* S390 version
- * Copyright (C) IBM Corp. 1999,2010
+ * Copyright (C) IBM Corp. 1999,2012
* Author(s): Hartmut Penner (hp@de.ibm.com),
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
@@ -62,6 +62,7 @@
#include <asm/ebcdic.h>
#include <asm/kvm_virtio.h>
#include <asm/diag.h>
+#include "entry.h"
long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
PSW_MASK_EA | PSW_MASK_BA;
@@ -351,8 +352,9 @@ static void setup_addressing_mode(void)
}
}
-static void __init
-setup_lowcore(void)
+void *restart_stack __attribute__((__section__(".data")));
+
+static void __init setup_lowcore(void)
{
struct _lowcore *lc;
@@ -363,7 +365,7 @@ setup_lowcore(void)
lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
lc->restart_psw.mask = psw_kernel_bits;
lc->restart_psw.addr =
- PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
+ PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
lc->external_new_psw.mask = psw_kernel_bits |
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->external_new_psw.addr =
@@ -412,6 +414,24 @@ setup_lowcore(void)
lc->last_update_timer = S390_lowcore.last_update_timer;
lc->last_update_clock = S390_lowcore.last_update_clock;
lc->ftrace_func = S390_lowcore.ftrace_func;
+
+ restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);