[S390] rework smp code
Define struct pcpu and merge some of the NR_CPUS arrays into it, including __cpu_logical_map, current_set and smp_cpu_state. Split smp related functions to those operating on physical cpus and the functions operating on a logical cpu number. Make the functions for physical cpus use a pointer to a struct pcpu. This hides the knowledge about cpu addresses in smp.c, entry[64].S and swsusp_asm64.S, thus remove the sigp.h header. The PSW restart mechanism is used to start secondary cpus, calling a function on an online cpu, calling a function on the ipl cpu, and for the nmi signal. Replace the different assembler functions with a single function restart_int_handler. The new entry point calls a function whose pointer is stored in the lowcore of the target cpu and it can wait for the source cpu to stop. This covers all existing use cases. Overall the code is now simpler and there are ~380 lines less code. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
@@ -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
|
||||
|
@@ -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));
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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};
|
||||
|
@@ -48,51 +48,22 @@ static void add_elf_notes(int cpu)
|
||||
memset(ptr, 0, sizeof(struct elf_note));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
@@ -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);
|
||||
restart_stack += ASYNC_SIZE;
|
||||
|
||||
/*
|
||||
* Set up PSW restart to call ipl.c:do_restart(). Copy the relevant
|
||||
* restart data to the absolute zero lowcore. This is necesary if
|
||||
* PSW restart is done on an offline CPU that has lowcore zero.
|
||||
*/
|
||||
lc->restart_stack = (unsigned long) restart_stack;
|
||||
lc->restart_fn = (unsigned long) do_restart;
|
||||
lc->restart_data = 0;
|
||||
lc->restart_source = -1UL;
|
||||
memcpy(&S390_lowcore.restart_stack, &lc->restart_stack,
|
||||
4*sizeof(unsigned long));
|
||||
copy_to_absolute_zero(&S390_lowcore.restart_psw,
|
||||
&lc->restart_psw, sizeof(psw_t));
|
||||
|
||||
set_prefix((u32)(unsigned long) lc);
|
||||
lowcore_ptr[0] = lc;
|
||||
}
|
||||
@@ -572,27 +592,6 @@ static void __init setup_memory_end(void)
|
||||
}
|
||||
}
|
||||
|
||||
void *restart_stack __attribute__((__section__(".data")));
|
||||
|
||||
/*
|
||||
* Setup new PSW and allocate stack for PSW restart interrupt
|
||||
*/
|
||||
static void __init setup_restart_psw(void)
|
||||
{
|
||||
psw_t psw;
|
||||
|
||||
restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);
|
||||
restart_stack += ASYNC_SIZE;
|
||||
|
||||
/*
|
||||
* Setup restart PSW for absolute zero lowcore. This is necesary
|
||||
* if PSW restart is done on an offline CPU that has lowcore zero
|
||||
*/
|
||||
psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
|
||||
psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
|
||||
copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
|
||||
}
|
||||
|
||||
static void __init setup_vmcoreinfo(void)
|
||||
{
|
||||
#ifdef CONFIG_KEXEC
|
||||
@@ -782,8 +781,7 @@ static void __init reserve_crashkernel(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init
|
||||
setup_memory(void)
|
||||
static void __init setup_memory(void)
|
||||
{
|
||||
unsigned long bootmap_size;
|
||||
unsigned long start_pfn, end_pfn;
|
||||
@@ -1014,8 +1012,7 @@ static void __init setup_hwcaps(void)
|
||||
* was printed.
|
||||
*/
|
||||
|
||||
void __init
|
||||
setup_arch(char **cmdline_p)
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
/*
|
||||
* print what head.S has found out about the machine
|
||||
@@ -1068,7 +1065,6 @@ setup_arch(char **cmdline_p)
|
||||
setup_memory();
|
||||
setup_resources();
|
||||
setup_vmcoreinfo();
|
||||
setup_restart_psw();
|
||||
setup_lowcore();
|
||||
|
||||
cpu_init();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 31-bit switch cpu code
|
||||
*
|
||||
* Copyright IBM Corp. 2009
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#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
|
||||
ENTRY(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
|
||||
|
||||
ENTRY(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: lr %r14,%r2 /* r14: Function to call */
|
||||
lr %r2,%r3 /* r2 : Parameter for function*/
|
||||
basr %r14,%r14 /* Call function */
|
||||
|
||||
.gprregs_addr:
|
||||
.long .gprregs
|
||||
|
||||
.section .data,"aw",@progbits
|
||||
.gprregs:
|
||||
.rept 16
|
||||
.long 0
|
||||
.endr
|
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 64-bit switch cpu code
|
||||
*
|
||||
* Copyright IBM Corp. 2009
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#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
|
||||
ENTRY(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
|
||||
|
||||
ENTRY(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: lgr %r14,%r2 /* r14: Function to call */
|
||||
lgr %r2,%r3 /* r2 : Parameter for function*/
|
||||
basr %r14,%r14 /* Call function */
|
||||
|
||||
.section .data,"aw",@progbits
|
||||
.gprregs:
|
||||
.rept 16
|
||||
.quad 0
|
||||
.endr
|
@@ -179,9 +179,9 @@ pgm_check_entry:
|
||||
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
|
||||
mvc __LC_RST_NEW_PSW(16,%r0),0(%r4)
|
||||
3:
|
||||
sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET
|
||||
brc 8,4f /* accepted */
|
||||
brc 2,3b /* busy, try again */
|
||||
sigp %r9,%r1,11 /* sigp initial cpu reset */
|
||||
brc 8,4f /* accepted */
|
||||
brc 2,3b /* busy, try again */
|
||||
|
||||
/* Suspend CPU not available -> panic */
|
||||
larl %r15,init_thread_union
|
||||
@@ -196,10 +196,10 @@ pgm_check_entry:
|
||||
lpsw 0(%r3)
|
||||
4:
|
||||
/* Switch to suspend CPU */
|
||||
sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */
|
||||
sigp %r9,%r1,6 /* sigp restart to suspend CPU */
|
||||
brc 2,4b /* busy, try again */
|
||||
5:
|
||||
sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */
|
||||
sigp %r9,%r2,5 /* sigp stop to current resume CPU */
|
||||
brc 2,5b /* busy, try again */
|
||||
6: j 6b
|
||||
|
||||
@@ -207,7 +207,7 @@ restart_suspend:
|
||||
larl %r1,.Lresume_cpu
|
||||
llgh %r2,0(%r1)
|
||||
7:
|
||||
sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */
|
||||
sigp %r9,%r2,1 /* sigp sense, wait for resume CPU */
|
||||
brc 8,7b /* accepted, status 0, still running */
|
||||
brc 2,7b /* busy, try again */
|
||||
tmll %r9,0x40 /* Test if resume CPU is stopped */
|
||||
|
@@ -79,12 +79,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
|
||||
cpu < TOPOLOGY_CPU_BITS;
|
||||
cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1))
|
||||
{
|
||||
unsigned int rcpu, lcpu;
|
||||
unsigned int rcpu;
|
||||
int lcpu;
|
||||
|
||||
rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
|
||||
for_each_present_cpu(lcpu) {
|
||||
if (cpu_logical_map(lcpu) != rcpu)
|
||||
continue;
|
||||
lcpu = smp_find_processor_id(rcpu);
|
||||
if (lcpu >= 0) {
|
||||
cpumask_set_cpu(lcpu, &book->mask);
|
||||
cpu_book_id[lcpu] = book->id;
|
||||
cpumask_set_cpu(lcpu, &core->mask);
|
||||
|
@@ -88,19 +88,12 @@ static void vdso_init_data(struct vdso_data *vd)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/*
|
||||
* Setup per cpu vdso data page.
|
||||
*/
|
||||
static void vdso_init_per_cpu_data(int cpu, struct vdso_per_cpu_data *vpcd)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate/free per cpu vdso data.
|
||||
*/
|
||||
#define SEGMENT_ORDER 2
|
||||
|
||||
int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)
|
||||
int vdso_alloc_per_cpu(struct _lowcore *lowcore)
|
||||
{
|
||||
unsigned long segment_table, page_table, page_frame;
|
||||
u32 *psal, *aste;
|
||||
@@ -139,7 +132,6 @@ int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)
|
||||
aste[4] = (u32)(addr_t) psal;
|
||||
lowcore->vdso_per_cpu_data = page_frame;
|
||||
|
||||
vdso_init_per_cpu_data(cpu, (struct vdso_per_cpu_data *) page_frame);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
@@ -149,7 +141,7 @@ out:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
|
||||
void vdso_free_per_cpu(struct _lowcore *lowcore)
|
||||
{
|
||||
unsigned long segment_table, page_table, page_frame;
|
||||
u32 *psal, *aste;
|
||||
@@ -168,19 +160,15 @@ void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
|
||||
free_pages(segment_table, SEGMENT_ORDER);
|
||||
}
|
||||
|
||||
static void __vdso_init_cr5(void *dummy)
|
||||
static void vdso_init_cr5(void)
|
||||
{
|
||||
unsigned long cr5;
|
||||
|
||||
if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
|
||||
return;
|
||||
cr5 = offsetof(struct _lowcore, paste);
|
||||
__ctl_load(cr5, 5, 5);
|
||||
}
|
||||
|
||||
static void vdso_init_cr5(void)
|
||||
{
|
||||
if (user_mode != HOME_SPACE_MODE && vdso_enabled)
|
||||
on_each_cpu(__vdso_init_cr5, NULL, 1);
|
||||
}
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
/*
|
||||
@@ -322,10 +310,8 @@ static int __init vdso_init(void)
|
||||
}
|
||||
vdso64_pagelist[vdso64_pages - 1] = virt_to_page(vdso_data);
|
||||
vdso64_pagelist[vdso64_pages] = NULL;
|
||||
#ifndef CONFIG_SMP
|
||||
if (vdso_alloc_per_cpu(0, &S390_lowcore))
|
||||
if (vdso_alloc_per_cpu(&S390_lowcore))
|
||||
BUG();
|
||||
#endif
|
||||
vdso_init_cr5();
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
@@ -335,7 +321,7 @@ static int __init vdso_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(vdso_init);
|
||||
early_initcall(vdso_init);
|
||||
|
||||
int in_gate_area_no_mm(unsigned long addr)
|
||||
{
|
||||
|
@@ -570,6 +570,9 @@ void init_cpu_vtimer(void)
|
||||
|
||||
/* enable cpu timer interrupts */
|
||||
__ctl_set_bit(0,10);
|
||||
|
||||
/* set initial cpu timer */
|
||||
set_vtimer(0x7fffffffffffffffULL);
|
||||
}
|
||||
|
||||
static int __cpuinit s390_nohz_notify(struct notifier_block *self,
|
||||
|
Reference in New Issue
Block a user