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;
};
pcpu_hotadd.patch
Description: pcpu_hotadd.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|