提交 591bb4f6 编写于 作者: H Heiko Carstens 提交者: Martin Schwidefsky

[S390] Initialize per cpu lowcores on cpu hotplug.

Just copy the first 512 read-only bytes of the current cpu lowcore if
a new cpu gets onlined. The rest is zeroed out and must be explicitly
initialized. Current code just copies the entire lowcore and
initializes the needed fields.
This should reveal bugs in future enhancements quite early.
Also when the lowcore of the first cpu is replaced this is now done
atomically (no interrupts, no machine checks).
Signed-off-by: NHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: NMartin Schwidefsky <schwidefsky@de.ibm.com>
上级 a22fb7ff
...@@ -626,13 +626,17 @@ static int __cpuinit smp_alloc_lowcore(int cpu) ...@@ -626,13 +626,17 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
if (!lowcore) if (!lowcore)
return -ENOMEM; return -ENOMEM;
async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
if (!async_stack)
goto out_async_stack;
panic_stack = __get_free_page(GFP_KERNEL); panic_stack = __get_free_page(GFP_KERNEL);
if (!panic_stack) if (!panic_stack || !async_stack)
goto out_panic_stack; goto out;
/*
*lowcore = S390_lowcore; * Only need to copy the first 512 bytes from address 0. But since
* the compiler emits a warning if src == NULL for memcpy use copy_page
* instead. Copies more than needed but this code is not performance
* critical.
*/
copy_page(lowcore, &S390_lowcore);
memset((void *)lowcore + 512, 0, sizeof(*lowcore) - 512);
lowcore->async_stack = async_stack + ASYNC_SIZE; lowcore->async_stack = async_stack + ASYNC_SIZE;
lowcore->panic_stack = panic_stack + PAGE_SIZE; lowcore->panic_stack = panic_stack + PAGE_SIZE;
...@@ -653,9 +657,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu) ...@@ -653,9 +657,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
out_save_area: out_save_area:
free_page(panic_stack); free_page(panic_stack);
#endif #endif
out_panic_stack: out:
free_pages(async_stack, ASYNC_ORDER); free_pages(async_stack, ASYNC_ORDER);
out_async_stack:
free_pages((unsigned long) lowcore, lc_order); free_pages((unsigned long) lowcore, lc_order);
return -ENOMEM; return -ENOMEM;
} }
...@@ -719,8 +722,8 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -719,8 +722,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
cpu_lowcore->current_task = (unsigned long) idle; cpu_lowcore->current_task = (unsigned long) idle;
cpu_lowcore->cpu_data.cpu_nr = cpu; cpu_lowcore->cpu_data.cpu_nr = cpu;
cpu_lowcore->softirq_pending = 0; cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
cpu_lowcore->ext_call_fast = 0; cpu_lowcore->ipl_device = S390_lowcore.ipl_device;
eieio(); eieio();
while (signal_processor(cpu, sigp_restart) == sigp_busy) while (signal_processor(cpu, sigp_restart) == sigp_busy)
...@@ -797,23 +800,43 @@ void cpu_die(void) ...@@ -797,23 +800,43 @@ void cpu_die(void)
void __init smp_prepare_cpus(unsigned int max_cpus) void __init smp_prepare_cpus(unsigned int max_cpus)
{ {
#ifndef CONFIG_64BIT
unsigned long save_area = 0;
#endif
unsigned long async_stack, panic_stack;
struct _lowcore *lowcore;
unsigned int cpu; unsigned int cpu;
int lc_order;
smp_detect_cpus(); smp_detect_cpus();
/* request the 0x1201 emergency signal external interrupt */ /* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201"); panic("Couldn't request external interrupt 0x1201");
memset(lowcore_ptr, 0, sizeof(lowcore_ptr));
print_cpu_info(&S390_lowcore.cpu_data); print_cpu_info(&S390_lowcore.cpu_data);
smp_alloc_lowcore(smp_processor_id());
/* Reallocate current lowcore, but keep its contents. */
lc_order = sizeof(long) == 8 ? 1 : 0;
lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order);
panic_stack = __get_free_page(GFP_KERNEL);
async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE) if (MACHINE_HAS_IEEE)
ctl_set_bit(14, 29); /* enable extended save area */ save_area = get_zeroed_page(GFP_KERNEL);
#endif #endif
set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); local_irq_disable();
local_mcck_disable();
lowcore_ptr[smp_processor_id()] = lowcore;
*lowcore = S390_lowcore;
lowcore->panic_stack = panic_stack + PAGE_SIZE;
lowcore->async_stack = async_stack + ASYNC_SIZE;
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE)
lowcore->extended_save_area_addr = (u32) save_area;
#endif
set_prefix((u32)(unsigned long) lowcore);
local_mcck_enable();
local_irq_enable();
for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
if (cpu != smp_processor_id()) if (cpu != smp_processor_id())
smp_create_idle(cpu); smp_create_idle(cpu);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册