--- arch/x86/kernel/smp_32.c | 2 + arch/x86/kernel/smpboot_32.c | 6 ++-- arch/x86/xen/enlighten.c | 15 ++++++++++- arch/x86/xen/smp.c | 54 ++++++++++++++++++++++++++++-------------- arch/x86/xen/xen-ops.h | 1 include/asm-x86/smp_32.h | 18 ++++++++++++-- 6 files changed, 72 insertions(+), 24 deletions(-) =================================================================== --- a/arch/x86/kernel/smp_32.c +++ b/arch/x86/kernel/smp_32.c @@ -704,4 +704,6 @@ struct smp_ops smp_ops = { .smp_send_stop = native_smp_send_stop, .smp_send_reschedule = native_smp_send_reschedule, .smp_call_function_mask = native_smp_call_function_mask, + + .cpu_disable = native_cpu_disable, }; =================================================================== --- a/arch/x86/kernel/smpboot_32.c +++ b/arch/x86/kernel/smpboot_32.c @@ -1166,7 +1166,7 @@ void remove_siblinginfo(int cpu) cpu_clear(cpu, cpu_sibling_setup_map); } -int __cpu_disable(void) +int native_cpu_disable(void) { cpumask_t map = cpu_online_map; int cpu = smp_processor_id(); @@ -1216,12 +1216,12 @@ void __cpu_die(unsigned int cpu) printk(KERN_ERR "CPU %u didn't die...\n", cpu); } #else /* ... !CONFIG_HOTPLUG_CPU */ -int __cpu_disable(void) +int native_cpu_disable(void) { return -ENOSYS; } -void __cpu_die(unsigned int cpu) +void native_cpu_die(unsigned int cpu) { /* We said "no" in __cpu_disable */ BUG(); =================================================================== --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -254,10 +254,21 @@ static void xen_safe_halt(void) BUG(); } +static void xen_shutdown_cpu(void) +{ + int cpu = smp_processor_id(); + + /* make sure we're not pinning something down */ + load_cr3(swapper_pg_dir); + /* GDT too? */ + + HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL); +} + static void xen_halt(void) { if (irqs_disabled()) - HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); + xen_shutdown_cpu(); else xen_safe_halt(); } @@ -1069,6 +1080,8 @@ static const struct smp_ops xen_smp_ops .smp_send_stop = xen_smp_send_stop, .smp_send_reschedule = xen_smp_send_reschedule, .smp_call_function_mask = xen_smp_call_function_mask, + + .cpu_disable = xen_cpu_disable, }; #endif /* CONFIG_SMP */ =================================================================== --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -189,8 +189,14 @@ void __init xen_smp_prepare_cpus(unsigne panic("failed fork for CPU %d", cpu); cpu_set(cpu, cpu_present_map); - } - + + smp_store_cpu_info(cpu); + init_gdt(cpu); + irq_ctx_init(cpu); + xen_setup_timer(cpu); + xen_smp_intr_init(cpu); + } + //init_xenbus_allowed_cpumask(); } @@ -198,7 +204,7 @@ cpu_initialize_context(unsigned int cpu, cpu_initialize_context(unsigned int cpu, struct task_struct *idle) { struct vcpu_guest_context *ctxt; - struct gdt_page *gdt = &per_cpu(gdt_page, cpu); + struct desc_struct *gdt = get_cpu_gdt_table(cpu); if (cpu_test_and_set(cpu, cpu_initialized_map)) return 0; @@ -222,11 +228,11 @@ cpu_initialize_context(unsigned int cpu, ctxt->ldt_ents = 0; - BUG_ON((unsigned long)gdt->gdt & ~PAGE_MASK); - make_lowmem_page_readonly(gdt->gdt); - - ctxt->gdt_frames[0] = virt_to_mfn(gdt->gdt); - ctxt->gdt_ents = ARRAY_SIZE(gdt->gdt); + BUG_ON((unsigned long)gdt & ~PAGE_MASK); + make_lowmem_page_readonly(gdt); + + ctxt->gdt_frames[0] = virt_to_mfn(gdt); + ctxt->gdt_ents = GDT_ENTRIES; ctxt->user_regs.cs = __KERNEL_CS; ctxt->user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs); @@ -260,26 +266,20 @@ int __cpuinit xen_cpu_up(unsigned int cp return rc; #endif - init_gdt(cpu); per_cpu(current_task, cpu) = idle; - irq_ctx_init(cpu); - xen_setup_timer(cpu); /* make sure interrupts start blocked */ per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1; rc = cpu_initialize_context(cpu, idle); if (rc) - return rc; + goto out; if (num_online_cpus() == 1) alternatives_smp_switch(1); - rc = xen_smp_intr_init(cpu); - if (rc) - return rc; - - smp_store_cpu_info(cpu); + get_cpu(); /* set_cpu_sibling_map wants no preempt */ + set_cpu_sibling_map(cpu); /* This must be done before setting cpu_online_map */ wmb(); @@ -289,7 +289,10 @@ int __cpuinit xen_cpu_up(unsigned int cp rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); BUG_ON(rc); - return 0; + put_cpu(); + + out: + return rc; } void xen_smp_cpus_done(unsigned int max_cpus) @@ -408,3 +411,18 @@ int xen_smp_call_function_mask(cpumask_t return 0; } + +int xen_cpu_disable(void) +{ + cpumask_t map = cpu_online_map; + int cpu = smp_processor_id(); + + remove_siblinginfo(cpu); + + cpu_clear(cpu, map); + fixup_irqs(map); + /* It's now safe to remove this processor from the online map */ + cpu_clear(cpu, cpu_online_map); + + return 0; +} =================================================================== --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -39,6 +39,7 @@ void xen_smp_prepare_cpus(unsigned int m void xen_smp_prepare_cpus(unsigned int max_cpus); int xen_cpu_up(unsigned int cpu); void xen_smp_cpus_done(unsigned int max_cpus); +int xen_cpu_disable(void); void xen_smp_send_stop(void); void xen_smp_send_reschedule(int cpu); =================================================================== --- a/include/asm-x86/smp_32.h +++ b/include/asm-x86/smp_32.h @@ -63,6 +63,9 @@ struct smp_ops int (*smp_call_function_mask)(cpumask_t mask, void (*func)(void *info), void *info, int wait); + + int (*cpu_disable)(void); + void (*cpu_die)(unsigned int cpu); }; extern struct smp_ops smp_ops; @@ -71,14 +74,17 @@ static inline void smp_prepare_boot_cpu( { smp_ops.smp_prepare_boot_cpu(); } + static inline void smp_prepare_cpus(unsigned int max_cpus) { smp_ops.smp_prepare_cpus(max_cpus); } + static inline int __cpu_up(unsigned int cpu) { return smp_ops.cpu_up(cpu); } + static inline void smp_cpus_done(unsigned int max_cpus) { smp_ops.smp_cpus_done(max_cpus); @@ -88,10 +94,12 @@ static inline void smp_send_stop(void) { smp_ops.smp_send_stop(); } + static inline void smp_send_reschedule(int cpu) { smp_ops.smp_send_reschedule(cpu); } + static inline int smp_call_function_mask(cpumask_t mask, void (*func) (void *info), void *info, int wait) @@ -99,10 +107,18 @@ static inline int smp_call_function_mask return smp_ops.smp_call_function_mask(mask, func, info, wait); } +static inline int __cpu_disable(void) +{ + return smp_ops.cpu_disable(); +} + + void native_smp_prepare_boot_cpu(void); void native_smp_prepare_cpus(unsigned int max_cpus); int native_cpu_up(unsigned int cpunum); void native_smp_cpus_done(unsigned int max_cpus); +extern int native_cpu_disable(void); +extern void __cpu_die(unsigned int cpu); #ifndef CONFIG_PARAVIRT #define startup_ipi_hook(phys_apicid, start_eip, start_esp) \ @@ -128,8 +144,6 @@ static inline int num_booting_cpus(void) } extern int safe_smp_processor_id(void); -extern int __cpu_disable(void); -extern void __cpu_die(unsigned int cpu); extern unsigned int num_processors; void __cpuinit smp_store_cpu_info(int id);