aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/acpi/boot.c1
-rw-r--r--xen/arch/x86/mpparse.c16
-rw-r--r--xen/arch/x86/numa.c8
-rw-r--r--xen/arch/x86/platform_hypercall.c6
-rw-r--r--xen/arch/x86/setup.c6
-rw-r--r--xen/arch/x86/smpboot.c77
-rw-r--r--xen/arch/x86/srat.c7
-rw-r--r--xen/include/asm-x86/acpi.h1
-rw-r--r--xen/include/asm-x86/numa.h6
-rw-r--r--xen/include/asm-x86/smp.h2
-rw-r--r--xen/include/public/platform.h9
11 files changed, 126 insertions, 13 deletions
diff --git a/xen/arch/x86/acpi/boot.c b/xen/arch/x86/acpi/boot.c
index e6cc2de6f2..8e67cde539 100644
--- a/xen/arch/x86/acpi/boot.c
+++ b/xen/arch/x86/acpi/boot.c
@@ -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 --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c
index 7d65c2abaf..33648562ae 100644
--- a/xen/arch/x86/mpparse.c
+++ b/xen/arch/x86/mpparse.c
@@ -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 --git a/xen/arch/x86/numa.c b/xen/arch/x86/numa.c
index 167373f834..6f06ac1e62 100644
--- a/xen/arch/x86/numa.c
+++ b/xen/arch/x86/numa.c
@@ -42,9 +42,9 @@ cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
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 numa_off __devinitdata = 1;
-int acpi_numa __initdata;
+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 --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index 9bde0d057f..b33cfb8392 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -463,6 +463,12 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
}
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 --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 1dfffca770..a8d254027e 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -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];
@@ -484,6 +484,10 @@ void __init __start_xen(unsigned long mbi_p)
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;
ns16550.irq = 4;
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 5d05c1e5cc..024896fa4a 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -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)
{
@@ -1446,6 +1518,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 */
int __devinit __cpu_up(unsigned int cpu)
diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c
index 9deeda077c..13a035ce45 100644
--- a/xen/arch/x86/srat.c
+++ b/xen/arch/x86/srat.c
@@ -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) {
@@ -93,11 +93,6 @@ static __init void bad_srat(void)
apicid_to_node[i] = NUMA_NO_NODE;
}
-static __init inline int srat_disabled(void)
-{
- return numa_off || acpi_numa < 0;
-}
-
/*
* A lot of BIOS fill in 10 (= no distance) everywhere. This messes
* up the NUMA heuristics which wants the local node to have a smaller
diff --git a/xen/include/asm-x86/acpi.h b/xen/include/asm-x86/acpi.h
index 7666c2cfad..299f56266f 100644
--- a/xen/include/asm-x86/acpi.h
+++ b/xen/include/asm-x86/acpi.h
@@ -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 --git a/xen/include/asm-x86/numa.h b/xen/include/asm-x86/numa.h
index 5486404282..cabb46f935 100644
--- a/xen/include/asm-x86/numa.h
+++ b/xen/include/asm-x86/numa.h
@@ -30,7 +30,13 @@ extern void numa_add_cpu(int cpu);
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 --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h
index 066612c3a3..515cc9a1e0 100644
--- a/xen/include/asm-x86/smp.h
+++ b/xen/include/asm-x86/smp.h
@@ -66,6 +66,8 @@ extern void cpu_exit_clear(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 --git a/xen/include/public/platform.h b/xen/include/public/platform.h
index ff6837ae10..0fce5690d2 100644
--- a/xen/include/public/platform.h
+++ b/xen/include/public/platform.h
@@ -338,6 +338,14 @@ struct 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;
};