diff -r 68b6bf9b5c8b xen/arch/x86/acpi/boot.c --- a/xen/arch/x86/acpi/boot.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/acpi/boot.c Thu Nov 12 04:08:43 2009 +0800 @@ -81,7 +81,6 @@ u8 acpi_enable_value, acpi_disable_value #warning ACPI uses CMPXCHG, i486 and later hardware #endif -#define MAX_MADT_ENTRIES 256 u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] = {[0 ... MAX_MADT_ENTRIES - 1] = 0xff }; EXPORT_SYMBOL(x86_acpiid_to_apicid); diff -r 68b6bf9b5c8b xen/arch/x86/mpparse.c --- a/xen/arch/x86/mpparse.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/mpparse.c Thu Nov 12 04:08:43 2009 +0800 @@ -35,7 +35,7 @@ /* Have we found an MP table */ int smp_found_config; -unsigned int __initdata maxcpus = NR_CPUS; +unsigned int __devinitdata maxcpus = NR_CPUS; /* * Various Linux-internal data structures created from the @@ -868,6 +868,20 @@ int __devinit mp_register_lapic ( return MP_processor_info(&processor); } +void mp_unregister_lapic(uint32_t apic_id, uint32_t cpu) +{ + if (!cpu || (apic_id == boot_cpu_physical_apicid)) + return; + + if (x86_cpu_to_apicid[cpu] != apic_id) + return; + + physid_clear(apic_id, phys_cpu_present_map); + + x86_cpu_to_apicid[cpu] = BAD_APICID; + cpu_clear(cpu, cpu_present_map); + } + #ifdef CONFIG_X86_IO_APIC #define MP_ISA_BUS 0 diff -r 68b6bf9b5c8b xen/arch/x86/numa.c --- a/xen/arch/x86/numa.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/numa.c Thu Nov 12 04:08:43 2009 +0800 @@ -42,9 +42,9 @@ nodemask_t __read_mostly node_online_map nodemask_t __read_mostly node_online_map = { { [0] = 1UL } }; /* Default NUMA to off for now. acpi=on required to enable it. */ -int numa_off __initdata = 1; - -int acpi_numa __initdata; +int numa_off __devinitdata = 1; + +int acpi_numa __devinitdata; /* * Given a shift value, try to populate memnodemap[] @@ -53,7 +53,7 @@ int acpi_numa __initdata; * 0 if memnodmap[] too small (of shift too small) * -1 if node overlap or lost ram (shift too big) */ -static int __init +static int __devinit populate_memnodemap(const struct node *nodes, int numnodes, int shift) { int i; @@ -259,7 +259,7 @@ static __init int numa_setup(char *opt) * prior to this call, and this initialization is good enough * for the fake NUMA cases. */ -void __init init_cpu_to_node(void) +void __devinit init_cpu_to_node(void) { int i; for (i = 0; i < NR_CPUS; i++) { diff -r 68b6bf9b5c8b xen/arch/x86/platform_hypercall.c --- a/xen/arch/x86/platform_hypercall.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/platform_hypercall.c Thu Nov 12 04:08:43 2009 +0800 @@ -463,6 +463,12 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe } break; + case XENPF_cpu_hotadd: + ret = cpu_add(op->u.cpu_add.apic_id, + op->u.cpu_add.acpi_id, + op->u.cpu_add.pxm); + break; + default: ret = -ENOSYS; break; diff -r 68b6bf9b5c8b xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/setup.c Thu Nov 12 04:08:43 2009 +0800 @@ -246,7 +246,7 @@ static void __init init_idle_domain(void setup_idle_pagetable(); } -static void __init srat_detect_node(int cpu) +void __devinit srat_detect_node(int cpu) { unsigned node; u32 apicid = x86_cpu_to_apicid[cpu]; @@ -483,6 +483,10 @@ void __init __start_xen(unsigned long mb asm volatile ( "mov %%cr4,%0" : "=r" (this_cpu(cr4)) ); smp_prepare_boot_cpu(); + +#ifdef CONFIG_HOTPLUG_CPU + prefill_possible_map(); +#endif /* We initialise the serial devices very early so we can get debugging. */ ns16550.io_base = 0x3f8; diff -r 68b6bf9b5c8b xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/smpboot.c Thu Nov 12 04:08:43 2009 +0800 @@ -1435,6 +1435,78 @@ void enable_nonboot_cpus(void) */ smpboot_restore_warm_reset_vector(); } + +int prefill_possible_map(void) +{ + int i; + + for (i = 0; i < NR_CPUS; i++) + cpu_set(i, cpu_possible_map); + return 0; +} + +int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm) +{ + int cpu = -1; + +#ifndef CONFIG_ACPI + return -ENOSYS; +#endif + + dprintk(XENLOG_DEBUG, "cpu_add apic_id %x acpi_id %x pxm %x\n", + apic_id, acpi_id, pxm); + + if ( acpi_id > MAX_MADT_ENTRIES || apic_id > MAX_APICS || pxm > 256 ) + return -EINVAL; + + /* Detect if the cpu has been added before */ + if ( x86_acpiid_to_apicid[acpi_id] != 0xff) + { + if (x86_acpiid_to_apicid[acpi_id] != apic_id) + return -EINVAL; + else + return -EEXIST; + } + + if ( physid_isset(apic_id, phys_cpu_present_map) ) + return -EEXIST; + + spin_lock(&cpu_add_remove_lock); + + cpu = mp_register_lapic(apic_id, 1); + + if (cpu < 0) + { + spin_unlock(&cpu_add_remove_lock); + return cpu; + } + + x86_acpiid_to_apicid[acpi_id] = apic_id; + + if ( !srat_disabled() ) + { + int node; + + node = setup_node(pxm); + if (node < 0) + { + dprintk(XENLOG_WARNING, "Setup node failed for pxm %x\n", pxm); + x86_acpiid_to_apicid[acpi_id] = 0xff; + mp_unregister_lapic(apic_id, cpu); + spin_unlock(&cpu_add_remove_lock); + return node; + } + apicid_to_node[apic_id] = node; + } + + srat_detect_node(cpu); + numa_add_cpu(cpu); + spin_unlock(&cpu_add_remove_lock); + dprintk(XENLOG_INFO, "Add CPU %x with index %x\n", apic_id, cpu); + return cpu; +} + + #else /* ... !CONFIG_HOTPLUG_CPU */ int __cpu_disable(void) { @@ -1445,6 +1517,11 @@ void __cpu_die(unsigned int cpu) { /* We said "no" in __cpu_disable */ BUG(); +} + +int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm) +{ + return -ENOSYS; } #endif /* CONFIG_HOTPLUG_CPU */ diff -r 68b6bf9b5c8b xen/arch/x86/srat.c --- a/xen/arch/x86/srat.c Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/arch/x86/srat.c Thu Nov 12 04:08:43 2009 +0800 @@ -41,7 +41,7 @@ int pxm_to_node(int pxm) return (signed char)pxm2node[pxm]; } -static __init int setup_node(int pxm) +__devinit int setup_node(int pxm) { unsigned node = pxm2node[pxm]; if (node == 0xff) { @@ -91,11 +91,6 @@ static __init void bad_srat(void) acpi_numa = -1; for (i = 0; i < MAX_LOCAL_APIC; i++) apicid_to_node[i] = NUMA_NO_NODE; -} - -static __init inline int srat_disabled(void) -{ - return numa_off || acpi_numa < 0; } /* diff -r 68b6bf9b5c8b xen/include/asm-x86/acpi.h --- a/xen/include/asm-x86/acpi.h Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/include/asm-x86/acpi.h Thu Nov 12 04:08:43 2009 +0800 @@ -150,6 +150,7 @@ struct acpi_sleep_info { #endif /* CONFIG_ACPI_SLEEP */ +#define MAX_MADT_ENTRIES 256 extern u8 x86_acpiid_to_apicid[]; #define MAX_LOCAL_APIC 256 diff -r 68b6bf9b5c8b xen/include/asm-x86/numa.h --- a/xen/include/asm-x86/numa.h Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/include/asm-x86/numa.h Thu Nov 12 04:08:43 2009 +0800 @@ -30,7 +30,13 @@ extern void numa_init_array(void); extern void numa_init_array(void); extern int numa_off; +static __devinit inline int srat_disabled(void) +{ + return numa_off || acpi_numa < 0; +} extern void numa_set_node(int cpu, int node); +extern int setup_node(int pxm); +extern void srat_detect_node(int cpu); extern void setup_node_bootmem(int nodeid, u64 start, u64 end); extern unsigned char apicid_to_node[256]; diff -r 68b6bf9b5c8b xen/include/asm-x86/smp.h --- a/xen/include/asm-x86/smp.h Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/include/asm-x86/smp.h Thu Nov 12 04:08:43 2009 +0800 @@ -66,6 +66,8 @@ extern void cpu_uninit(void); extern void cpu_uninit(void); extern void disable_nonboot_cpus(void); extern void enable_nonboot_cpus(void); +int prefill_possible_map(void); +int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm); #else static inline int cpu_is_offline(int cpu) {return 0;} static inline void disable_nonboot_cpus(void) {} diff -r 68b6bf9b5c8b xen/include/public/platform.h --- a/xen/include/public/platform.h Thu Nov 12 04:08:25 2009 +0800 +++ b/xen/include/public/platform.h Thu Nov 12 04:08:43 2009 +0800 @@ -338,6 +338,14 @@ typedef struct xenpf_cpu_ol xenpf_cpu_ol typedef struct xenpf_cpu_ol xenpf_cpu_ol_t; DEFINE_XEN_GUEST_HANDLE(xenpf_cpu_ol_t); +#define XENPF_cpu_hotadd 58 +struct xenpf_cpu_hotadd +{ + uint32_t apic_id; + uint32_t acpi_id; + uint32_t pxm; +}; + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -355,6 +363,7 @@ struct xen_platform_op { struct xenpf_set_processor_pminfo set_pminfo; struct xenpf_pcpuinfo pcpu_info; struct xenpf_cpu_ol cpu_ol; + struct xenpf_cpu_hotadd cpu_add; uint8_t pad[128]; } u; };