[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] RE: [PATCH] Support physical CPU hot-add in xen hypervisor



This patch depends on the "Update pcpu_info hypercall interface"  patch I sent 
just now. Sorry that I should sent them out as series.

Thanks
Yunhong Jiang


Jiang, Yunhong wrote:
> This patch add CPU hot-add in system.
> a) It mark all CPU as possible when booting, if
> CONFIG_HOTPLUG_CPU is set. BTW, this will increase per_cpu area.
> 
> b) When a CPU is added through hypercall, the CPU will be
> marked as present and offline, and the numa information is
> setup if numa is supported. The CPU will be brought to online
> by dom0 online explicitly.
> 
> Signed-off-by: Jiang, Yunhong <yunhong.jiang@xxxxxxxxx>
> 
> 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;
> };
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.