x86/cpu: Factor out common CPU initialization code, fix 32-bit Xen PV guests
Some of x86 bare-metal and Xen CPU initialization code is common
between the two and therefore can be factored out to avoid code
duplication.
As a side effect, doing so will also extend the fix provided by
commit a7fcf28d43
("x86/asm/entry: Replace this_cpu_sp0() with
current_top_of_stack() to x86_32") to 32-bit Xen PV guests.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: David Vrabel <david.vrabel@citrix.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: konrad.wilk@oracle.com
Cc: xen-devel@lists.xenproject.org
Link: http://lkml.kernel.org/r/1427897534-5086-1-git-send-email-boris.ostrovsky@oracle.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Родитель
40e4f2d177
Коммит
3f85483bd8
|
@ -154,6 +154,7 @@ void cpu_die_common(unsigned int cpu);
|
||||||
void native_smp_prepare_boot_cpu(void);
|
void native_smp_prepare_boot_cpu(void);
|
||||||
void native_smp_prepare_cpus(unsigned int max_cpus);
|
void native_smp_prepare_cpus(unsigned int max_cpus);
|
||||||
void native_smp_cpus_done(unsigned int max_cpus);
|
void native_smp_cpus_done(unsigned int max_cpus);
|
||||||
|
void common_cpu_up(unsigned int cpunum, struct task_struct *tidle);
|
||||||
int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
|
int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
|
||||||
int native_cpu_disable(void);
|
int native_cpu_disable(void);
|
||||||
void native_cpu_die(unsigned int cpu);
|
void native_cpu_die(unsigned int cpu);
|
||||||
|
|
|
@ -779,6 +779,26 @@ out:
|
||||||
return boot_error;
|
return boot_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void common_cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||||
|
{
|
||||||
|
/* Just in case we booted with a single CPU. */
|
||||||
|
alternatives_enable_smp();
|
||||||
|
|
||||||
|
per_cpu(current_task, cpu) = idle;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
/* Stack for startup_32 can be just as for start_secondary onwards */
|
||||||
|
irq_ctx_init(cpu);
|
||||||
|
per_cpu(cpu_current_top_of_stack, cpu) =
|
||||||
|
(unsigned long)task_stack_page(idle) + THREAD_SIZE;
|
||||||
|
#else
|
||||||
|
clear_tsk_thread_flag(idle, TIF_FORK);
|
||||||
|
initial_gs = per_cpu_offset(cpu);
|
||||||
|
#endif
|
||||||
|
per_cpu(kernel_stack, cpu) =
|
||||||
|
(unsigned long)task_stack_page(idle) + THREAD_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
|
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
|
||||||
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
|
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
|
||||||
|
@ -796,24 +816,9 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
|
||||||
int cpu0_nmi_registered = 0;
|
int cpu0_nmi_registered = 0;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
/* Just in case we booted with a single CPU. */
|
|
||||||
alternatives_enable_smp();
|
|
||||||
|
|
||||||
idle->thread.sp = (unsigned long) (((struct pt_regs *)
|
idle->thread.sp = (unsigned long) (((struct pt_regs *)
|
||||||
(THREAD_SIZE + task_stack_page(idle))) - 1);
|
(THREAD_SIZE + task_stack_page(idle))) - 1);
|
||||||
per_cpu(current_task, cpu) = idle;
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
/* Stack for startup_32 can be just as for start_secondary onwards */
|
|
||||||
irq_ctx_init(cpu);
|
|
||||||
per_cpu(cpu_current_top_of_stack, cpu) =
|
|
||||||
(unsigned long)task_stack_page(idle) + THREAD_SIZE;
|
|
||||||
#else
|
|
||||||
clear_tsk_thread_flag(idle, TIF_FORK);
|
|
||||||
initial_gs = per_cpu_offset(cpu);
|
|
||||||
#endif
|
|
||||||
per_cpu(kernel_stack, cpu) =
|
|
||||||
(unsigned long)task_stack_page(idle) + THREAD_SIZE;
|
|
||||||
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
|
early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
|
||||||
initial_code = (unsigned long)start_secondary;
|
initial_code = (unsigned long)start_secondary;
|
||||||
stack_start = idle->thread.sp;
|
stack_start = idle->thread.sp;
|
||||||
|
@ -954,6 +959,8 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
|
||||||
/* the FPU context is blank, nobody can own it */
|
/* the FPU context is blank, nobody can own it */
|
||||||
__cpu_disable_lazy_restore(cpu);
|
__cpu_disable_lazy_restore(cpu);
|
||||||
|
|
||||||
|
common_cpu_up(cpu, tidle);
|
||||||
|
|
||||||
err = do_boot_cpu(apicid, cpu, tidle);
|
err = do_boot_cpu(apicid, cpu, tidle);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu);
|
pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu);
|
||||||
|
|
|
@ -445,14 +445,7 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
per_cpu(current_task, cpu) = idle;
|
common_cpu_up(cpu, idle);
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
irq_ctx_init(cpu);
|
|
||||||
#else
|
|
||||||
clear_tsk_thread_flag(idle, TIF_FORK);
|
|
||||||
#endif
|
|
||||||
per_cpu(kernel_stack, cpu) =
|
|
||||||
(unsigned long)task_stack_page(idle) + THREAD_SIZE;
|
|
||||||
|
|
||||||
xen_setup_runstate_info(cpu);
|
xen_setup_runstate_info(cpu);
|
||||||
xen_setup_timer(cpu);
|
xen_setup_timer(cpu);
|
||||||
|
@ -467,10 +460,6 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (num_online_cpus() == 1)
|
|
||||||
/* Just in case we booted with a single CPU. */
|
|
||||||
alternatives_enable_smp();
|
|
||||||
|
|
||||||
rc = xen_smp_intr_init(cpu);
|
rc = xen_smp_intr_init(cpu);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче