2008-08-22 10:52:33

by Alex Nixon

[permalink] [raw]
Subject: [PATCH 1/5] x86: Add cpu hotplug hooks into smp_ops

Signed-off-by: Alex Nixon <[email protected]>
Cc: Jeremy Fitzhardinge <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
arch/x86/kernel/process_32.c | 4 ++--
arch/x86/kernel/process_64.c | 4 ++--
arch/x86/kernel/smp.c | 6 +++++-
arch/x86/kernel/smpboot.c | 8 ++++----
include/asm-x86/smp.h | 28 ++++++++++++++++++++++++----
5 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 593b73e..ae376af 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -93,7 +93,7 @@ static void cpu_exit_clear(void)
}

/* We don't actually take CPU down, just spin without interrupts. */
-static inline void play_dead(void)
+void native_play_dead(void)
{
/* This must be done before dead CPU ack */
cpu_exit_clear();
@@ -109,7 +109,7 @@ static inline void play_dead(void)
wbinvd_halt();
}
#else
-static inline void play_dead(void)
+void native_play_dead(void)
{
BUG();
}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 8248dc0..1cca50c 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -92,7 +92,7 @@ DECLARE_PER_CPU(int, cpu_state);

#include <linux/nmi.h>
/* We halt the CPU with physical CPU hotplug */
-static inline void play_dead(void)
+void native_play_dead(void)
{
idle_task_exit();
mb();
@@ -104,7 +104,7 @@ static inline void play_dead(void)
wbinvd_halt();
}
#else
-static inline void play_dead(void)
+void native_play_dead(void)
{
BUG();
}
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 361b7a4..18f9b19 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -214,12 +214,16 @@ void smp_call_function_single_interrupt(struct pt_regs *regs)
struct smp_ops smp_ops = {
.smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
.smp_prepare_cpus = native_smp_prepare_cpus,
- .cpu_up = native_cpu_up,
.smp_cpus_done = native_smp_cpus_done,

.smp_send_stop = native_smp_send_stop,
.smp_send_reschedule = native_smp_send_reschedule,

+ .cpu_up = native_cpu_up,
+ .cpu_die = native_cpu_die,
+ .cpu_disable = native_cpu_disable,
+ .play_dead = native_play_dead,
+
.send_call_func_ipi = native_send_call_func_ipi,
.send_call_func_single_ipi = native_send_call_func_single_ipi,
};
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 2ff0bbc..c6832ca 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1343,7 +1343,7 @@ static void __ref remove_cpu_from_maps(int cpu)
numa_remove_cpu(cpu);
}

-int __cpu_disable(void)
+int native_cpu_disable(void)
{
int cpu = smp_processor_id();

@@ -1382,7 +1382,7 @@ int __cpu_disable(void)
return 0;
}

-void __cpu_die(unsigned int cpu)
+void native_cpu_die(unsigned int cpu)
{
/* We don't do anything here: idle task is faking death itself. */
unsigned int i;
@@ -1400,12 +1400,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();
diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
index 29324c1..cb1d51d 100644
--- a/include/asm-x86/smp.h
+++ b/include/asm-x86/smp.h
@@ -50,12 +50,16 @@ extern struct {
struct smp_ops {
void (*smp_prepare_boot_cpu)(void);
void (*smp_prepare_cpus)(unsigned max_cpus);
- int (*cpu_up)(unsigned cpu);
void (*smp_cpus_done)(unsigned max_cpus);

void (*smp_send_stop)(void);
void (*smp_send_reschedule)(int cpu);

+ int (*cpu_up)(unsigned cpu);
+ int (*cpu_disable)(void);
+ void (*cpu_die)(unsigned int cpu);
+ void (*play_dead)(void);
+
void (*send_call_func_ipi)(cpumask_t mask);
void (*send_call_func_single_ipi)(int cpu);
};
@@ -94,6 +98,21 @@ static inline int __cpu_up(unsigned int cpu)
return smp_ops.cpu_up(cpu);
}

+static inline int __cpu_disable(void)
+{
+ return smp_ops.cpu_disable();
+}
+
+static inline void __cpu_die(unsigned int cpu)
+{
+ smp_ops.cpu_die(cpu);
+}
+
+static inline void play_dead(void)
+{
+ smp_ops.play_dead();
+}
+
static inline void smp_send_reschedule(int cpu)
{
smp_ops.smp_send_reschedule(cpu);
@@ -113,12 +132,13 @@ void native_smp_prepare_boot_cpu(void);
void native_smp_prepare_cpus(unsigned int max_cpus);
void native_smp_cpus_done(unsigned int max_cpus);
int native_cpu_up(unsigned int cpunum);
+int native_cpu_disable(void);
+void native_cpu_die(unsigned int cpu);
+void native_play_dead(void);
+
void native_send_call_func_ipi(cpumask_t mask);
void native_send_call_func_single_ipi(int cpu);

-extern int __cpu_disable(void);
-extern void __cpu_die(unsigned int cpu);
-
void smp_store_cpu_info(int id);
#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)

--
1.5.4.3


2008-08-22 10:52:18

by Alex Nixon

[permalink] [raw]
Subject: [PATCH 2/5] x86_32: Clean up play_dead.

The removal of the CPU from the various maps was redundant as it already happened in cpu_disable.

After cleaning this up, cpu_uninit only resets the tlb state, so rename it and create a noop version for the X86_64 case (so the two play_deads can be unified later).

Signed-off-by: Alex Nixon <[email protected]>
Cc: Jeremy Fitzhardinge <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
arch/x86/kernel/cpu/common.c | 6 +-----
arch/x86/kernel/process_32.c | 17 ++++-------------
include/asm-x86/smp.h | 7 ++++++-
3 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d3bc82f..531e054 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -755,14 +755,10 @@ void __cpuinit cpu_init(void)
xsave_init();
}

-#ifdef CONFIG_HOTPLUG_CPU
-void __cpuinit cpu_uninit(void)
+void reset_lazy_tlbstate(void)
{
int cpu = raw_smp_processor_id();
- cpu_clear(cpu, cpu_initialized);

- /* lazy TLB state */
per_cpu(cpu_tlbstate, cpu).state = 0;
per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm;
}
-#endif
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index ae376af..c4abfab 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -77,26 +77,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
#ifdef CONFIG_HOTPLUG_CPU
#include <asm/nmi.h>

-static void cpu_exit_clear(void)
+/* We don't actually take CPU down, just spin without interrupts. */
+void native_play_dead(void)
{
int cpu = raw_smp_processor_id();

idle_task_exit();

- cpu_uninit();
- irq_ctx_exit(cpu);
+ reset_lazy_tlbstate();

- cpu_clear(cpu, cpu_callout_map);
- cpu_clear(cpu, cpu_callin_map);
-
- numa_remove_cpu(cpu);
-}
+ irq_ctx_exit(cpu);

-/* We don't actually take CPU down, just spin without interrupts. */
-void native_play_dead(void)
-{
- /* This must be done before dead CPU ack */
- cpu_exit_clear();
mb();
/* Ack it */
__get_cpu_var(cpu_state) = CPU_DEAD;
diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
index cb1d51d..dba14d3 100644
--- a/include/asm-x86/smp.h
+++ b/include/asm-x86/smp.h
@@ -226,7 +226,12 @@ static inline int hard_smp_processor_id(void)
#endif /* CONFIG_X86_LOCAL_APIC */

#ifdef CONFIG_HOTPLUG_CPU
-extern void cpu_uninit(void);
+#ifdef CONFIG_X86_32
+extern void reset_lazy_tlbstate(void);
+#else
+static inline void reset_lazy_tlbstate(void)
+{ }
+#endif /* CONFIG_X86_32 */
#endif

#endif /* __ASSEMBLY__ */
--
1.5.4.3

2008-08-22 10:53:08

by Alex Nixon

[permalink] [raw]
Subject: [PATCH 4/5] x86: Separate generic cpu disabling code from APIC writes in cpu_disable

It allows paravirt implementations of cpu_disable to share the cpu_disable_common code, without having to take on board APIC writes, which may not be appropriate.

Signed-off-by: Alex Nixon <[email protected]>
Cc: Jeremy Fitzhardinge <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
arch/x86/kernel/smpboot.c | 40 +++++++++++++++++++++++-----------------
include/asm-x86/smp.h | 1 +
2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 58d8c6c..acac8df 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1343,25 +1343,9 @@ static void __ref remove_cpu_from_maps(int cpu)
numa_remove_cpu(cpu);
}

-int native_cpu_disable(void)
+void cpu_disable_common(void)
{
int cpu = smp_processor_id();
-
- /*
- * Perhaps use cpufreq to drop frequency, but that could go
- * into generic code.
- *
- * We won't take down the boot processor on i386 due to some
- * interrupts only being able to be serviced by the BSP.
- * Especially so if we're not using an IOAPIC -zwane
- */
- if (cpu == 0)
- return -EBUSY;
-
- if (nmi_watchdog == NMI_LOCAL_APIC)
- stop_apic_nmi_watchdog(NULL);
- clear_local_APIC();
-
/*
* HACK:
* Allow any queued timer interrupts to get serviced
@@ -1379,6 +1363,28 @@ int native_cpu_disable(void)
remove_cpu_from_maps(cpu);
unlock_vector_lock();
fixup_irqs(cpu_online_map);
+}
+
+int native_cpu_disable(void)
+{
+ int cpu = smp_processor_id();
+
+ /*
+ * Perhaps use cpufreq to drop frequency, but that could go
+ * into generic code.
+ *
+ * We won't take down the boot processor on i386 due to some
+ * interrupts only being able to be serviced by the BSP.
+ * Especially so if we're not using an IOAPIC -zwane
+ */
+ if (cpu == 0)
+ return -EBUSY;
+
+ if (nmi_watchdog == NMI_LOCAL_APIC)
+ stop_apic_nmi_watchdog(NULL);
+ clear_local_APIC();
+
+ cpu_disable_common();
return 0;
}

diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
index 95b28c1..e0ac06a 100644
--- a/include/asm-x86/smp.h
+++ b/include/asm-x86/smp.h
@@ -128,6 +128,7 @@ static inline void arch_send_call_function_ipi(cpumask_t mask)
smp_ops.send_call_func_ipi(mask);
}

+void cpu_disable_common(void);
void native_smp_prepare_boot_cpu(void);
void native_smp_prepare_cpus(unsigned int max_cpus);
void native_smp_cpus_done(unsigned int max_cpus);
--
1.5.4.3

2008-08-22 10:52:49

by Alex Nixon

[permalink] [raw]
Subject: [PATCH 3/5] x86: Unify x86_32 and x86_64 play_dead into one function

Add the new play_dead into smpboot.c, as it fits more cleanly in there alongside other CONFIG_HOTPLUG functions.
Separate out the common code into its own function.

Signed-off-by: Alex Nixon <[email protected]>
Cc: Jeremy Fitzhardinge <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
arch/x86/kernel/process_32.c | 32 --------------------------------
arch/x86/kernel/process_64.c | 23 -----------------------
arch/x86/kernel/smpboot.c | 29 +++++++++++++++++++++++++++++
include/asm-x86/smp.h | 1 +
4 files changed, 30 insertions(+), 55 deletions(-)

diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index c4abfab..aff137c 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -74,38 +74,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
return ((unsigned long *)tsk->thread.sp)[3];
}

-#ifdef CONFIG_HOTPLUG_CPU
-#include <asm/nmi.h>
-
-/* We don't actually take CPU down, just spin without interrupts. */
-void native_play_dead(void)
-{
- int cpu = raw_smp_processor_id();
-
- idle_task_exit();
-
- reset_lazy_tlbstate();
-
- irq_ctx_exit(cpu);
-
- mb();
- /* Ack it */
- __get_cpu_var(cpu_state) = CPU_DEAD;
-
- /*
- * With physical CPU hotplug, we should halt the cpu
- */
- local_irq_disable();
- /* mask all interrupts, flush any and all caches, and halt */
- wbinvd_halt();
-}
-#else
-void native_play_dead(void)
-{
- BUG();
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 1cca50c..b2bab8e 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -87,29 +87,6 @@ void exit_idle(void)
__exit_idle();
}

-#ifdef CONFIG_HOTPLUG_CPU
-DECLARE_PER_CPU(int, cpu_state);
-
-#include <linux/nmi.h>
-/* We halt the CPU with physical CPU hotplug */
-void native_play_dead(void)
-{
- idle_task_exit();
- mb();
- /* Ack it */
- __get_cpu_var(cpu_state) = CPU_DEAD;
-
- local_irq_disable();
- /* mask all interrupts, flush any and all caches, and halt */
- wbinvd_halt();
-}
-#else
-void native_play_dead(void)
-{
- BUG();
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index c6832ca..58d8c6c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1399,6 +1399,29 @@ void native_cpu_die(unsigned int cpu)
}
printk(KERN_ERR "CPU %u didn't die...\n", cpu);
}
+
+void play_dead_common(void)
+{
+ idle_task_exit();
+ reset_lazy_tlbstate();
+ irq_ctx_exit(raw_smp_processor_id());
+
+ mb();
+ /* Ack it */
+ __get_cpu_var(cpu_state) = CPU_DEAD;
+
+ /*
+ * With physical CPU hotplug, we should halt the cpu
+ */
+ local_irq_disable();
+}
+
+void native_play_dead(void)
+{
+ play_dead_common();
+ wbinvd_halt();
+}
+
#else /* ... !CONFIG_HOTPLUG_CPU */
int native_cpu_disable(void)
{
@@ -1410,4 +1433,10 @@ void native_cpu_die(unsigned int cpu)
/* We said "no" in __cpu_disable */
BUG();
}
+
+void native_play_dead(void)
+{
+ BUG();
+}
+
#endif
diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
index dba14d3..95b28c1 100644
--- a/include/asm-x86/smp.h
+++ b/include/asm-x86/smp.h
@@ -135,6 +135,7 @@ int native_cpu_up(unsigned int cpunum);
int native_cpu_disable(void);
void native_cpu_die(unsigned int cpu);
void native_play_dead(void);
+void play_dead_common(void);

void native_send_call_func_ipi(cpumask_t mask);
void native_send_call_func_single_ipi(int cpu);
--
1.5.4.3

2008-08-22 10:53:36

by Alex Nixon

[permalink] [raw]
Subject: [PATCH 5/5] Xen: Implement CPU hotplugging

Note the changes from 2.6.18-xen CPU hotplugging:

A vcpu_down request from the remote admin via Xenbus both hotunplugs the CPU, and disables it by removing it from the cpu_present map, and removing its entry in /sys

A vcpu_up request from the remote admin only re-enables the CPU, and does not immediately bring the CPU up. A udev event is emitted, which can be caught by the user if he wishes to automatically re-up CPUs when available, or implement a more complex policy.

Signed-off-by: Alex Nixon <[email protected]>
Cc: Jeremy Fitzhardinge <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
arch/x86/xen/smp.c | 60 +++++++++++++++++++++++++++++++++++++---------
arch/x86/xen/spinlock.c | 5 ++++
arch/x86/xen/time.c | 8 ++++++
arch/x86/xen/xen-ops.h | 6 ++++
drivers/xen/Makefile | 2 +-
drivers/xen/events.c | 4 +++
6 files changed, 72 insertions(+), 13 deletions(-)

diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index baca7f2..be5cbb2 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -11,8 +11,6 @@
* useful topology information for the kernel to make use of. As a
* result, all CPUs are treated as if they're single-core and
* single-threaded.
- *
- * This does not handle HOTPLUG_CPU yet.
*/
#include <linux/sched.h>
#include <linux/err.h>
@@ -61,11 +59,12 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}

-static __cpuinit void cpu_bringup_and_idle(void)
+static __cpuinit void cpu_bringup(void)
{
int cpu = smp_processor_id();

cpu_init();
+ touch_softlockup_watchdog();
preempt_disable();

xen_enable_sysenter();
@@ -86,6 +85,11 @@ static __cpuinit void cpu_bringup_and_idle(void)
local_irq_enable();

wmb(); /* make sure everything is out */
+}
+
+static __cpuinit void cpu_bringup_and_idle(void)
+{
+ cpu_bringup();
cpu_idle();
}

@@ -209,8 +213,6 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)

cpu_set(cpu, cpu_present_map);
}
-
- //init_xenbus_allowed_cpumask();
}

static __cpuinit int
@@ -278,12 +280,6 @@ static int __cpuinit xen_cpu_up(unsigned int cpu)
struct task_struct *idle = idle_task(cpu);
int rc;

-#if 0
- rc = cpu_up_check(cpu);
- if (rc)
- return rc;
-#endif
-
#ifdef CONFIG_X86_64
/* Allocate node local memory for AP pdas */
WARN_ON(cpu == 0);
@@ -336,6 +332,42 @@ static void xen_smp_cpus_done(unsigned int max_cpus)
{
}

+int xen_cpu_disable(void)
+{
+ unsigned int cpu = smp_processor_id();
+ if (cpu == 0)
+ return -EBUSY;
+
+ cpu_disable_common();
+
+ load_cr3(swapper_pg_dir);
+ return 0;
+}
+
+void xen_cpu_die(unsigned int cpu)
+{
+ while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ/10);
+ }
+ unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+ unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
+ unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL);
+ xen_uninit_lock_cpu(cpu);
+ xen_teardown_timer(cpu);
+
+ if (num_online_cpus() == 1)
+ alternatives_smp_switch(0);
+}
+
+void xen_play_dead(void)
+{
+ play_dead_common();
+ HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
+ cpu_bringup();
+}
+
static void stop_self(void *v)
{
int cpu = smp_processor_id();
@@ -419,9 +451,13 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id)
static const struct smp_ops xen_smp_ops __initdata = {
.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
.smp_prepare_cpus = xen_smp_prepare_cpus,
- .cpu_up = xen_cpu_up,
.smp_cpus_done = xen_smp_cpus_done,

+ .cpu_up = xen_cpu_up,
+ .cpu_die = xen_cpu_die,
+ .cpu_disable = xen_cpu_disable,
+ .play_dead = xen_play_dead,
+
.smp_send_stop = xen_smp_send_stop,
.smp_send_reschedule = xen_smp_send_reschedule,

diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index f8fea68..bb6bc72 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -357,6 +357,11 @@ void __cpuinit xen_init_lock_cpu(int cpu)
printk("cpu %d spinlock event irq %d\n", cpu, irq);
}

+void xen_uninit_lock_cpu(int cpu)
+{
+ unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL);
+}
+
void __init xen_init_spinlocks(void)
{
pv_lock_ops.spin_is_locked = xen_spin_is_locked;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 20182d9..004ba86 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -450,6 +450,14 @@ void xen_setup_timer(int cpu)
setup_runstate_info(cpu);
}

+void xen_teardown_timer(int cpu)
+{
+ struct clock_event_device *evt;
+ BUG_ON(cpu == 0);
+ evt = &per_cpu(xen_clock_events, cpu);
+ unbind_from_irqhandler(evt->irq, NULL);
+}
+
void xen_setup_cpu_clockevents(void)
{
BUG_ON(preemptible());
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 1e8bfda..8dbd97f 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -34,6 +34,7 @@ void __init xen_build_dynamic_phys_to_machine(void);

void xen_init_irq_ops(void);
void xen_setup_timer(int cpu);
+void xen_teardown_timer(int cpu);
cycle_t xen_clocksource_read(void);
void xen_setup_cpu_clockevents(void);
unsigned long xen_tsc_khz(void);
@@ -50,11 +51,16 @@ void xen_mark_init_mm_pinned(void);

void __init xen_setup_vcpu_info_placement(void);

+void xen_play_dead(void);
+void xen_cpu_die(unsigned int cpu);
+int xen_cpu_disable(void);
+
#ifdef CONFIG_SMP
void xen_smp_init(void);

void __init xen_init_spinlocks(void);
__cpuinit void xen_init_lock_cpu(int cpu);
+void xen_uninit_lock_cpu(int cpu);

extern cpumask_t xen_cpu_initialized_map;
#else
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 363286c..f62d8df 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,4 +1,4 @@
-obj-y += grant-table.o features.o events.o manage.o
+obj-y += grant-table.o features.o events.o manage.o cpu_hotplug.o
obj-y += xenbus/
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += balloon.o
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 792ca6e..e6d47e8 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -364,6 +364,10 @@ static void unbind_from_irq(unsigned int irq)
per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
[index_from_irq(irq)] = -1;
break;
+ case IRQT_IPI:
+ per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
+ [index_from_irq(irq)] = -1;
+ break;
default:
break;
}
--
1.5.4.3

2008-08-25 09:00:17

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 1/5] x86: Add cpu hotplug hooks into smp_ops


* Alex Nixon <[email protected]> wrote:

> Signed-off-by: Alex Nixon <[email protected]>
> Cc: Jeremy Fitzhardinge <[email protected]>
> Cc: Ingo Molnar <[email protected]>

applied to tip/x86/xen, with the Acks of Jeremy added as well - thanks
Alex.

Ingo

2008-08-25 09:26:06

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 5/5] Xen: Implement CPU hotplugging


* Alex Nixon <[email protected]> wrote:

> arch/x86/xen/smp.c | 60 +++++++++++++++++++++++++++++++++++++---------
> arch/x86/xen/spinlock.c | 5 ++++
> arch/x86/xen/time.c | 8 ++++++
> arch/x86/xen/xen-ops.h | 6 ++++
> drivers/xen/Makefile | 2 +-
> drivers/xen/events.c | 4 +++
> 6 files changed, 72 insertions(+), 13 deletions(-)

this was causing:

make[2]: *** No rule to make target `drivers/xen/cpu_hotplug.o', needed by `drivers/xen/built-in.o'. Stop.
make[1]: *** [drivers/xen] Error 2
make[1]: *** Waiting for unfinished jobs....

then i discovered the missing file in a patch you re-sent and which
wasnt in the original series. Please point out the reason for resends.

Ingo

2008-08-25 09:41:40

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 5/5] Xen: Implement CPU hotplugging


-tip testing found this build failure:

arch/x86/kernel/process_32.c: In function ‘cpu_idle’:
arch/x86/kernel/process_32.c:101: error: implicit declaration of function ‘play_dead’

config attached. I've excluded these commits from tip/master for now.

Ingo


Attachments:
(No filename) (267.00 B)
config (62.33 kB)
Download all attachments

2008-08-24 05:57:21

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: [PATCH 3/5] x86: Unify x86_32 and x86_64 play_dead into one function

Alex Nixon wrote:
> Add the new play_dead into smpboot.c, as it fits more cleanly in there alongside other CONFIG_HOTPLUG functions.
> Separate out the common code into its own function.
>

Unfortunately this breaks with !CONFIG_SMP. The fix is a bit awkward,
because the right place to fix it is in asm-x86/smp.h, but that isn't
included by linux/smp.h when CONFIG_SMP isn't set.

J
> Signed-off-by: Alex Nixon <[email protected]>
> Cc: Jeremy Fitzhardinge <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> ---
> arch/x86/kernel/process_32.c | 32 --------------------------------
> arch/x86/kernel/process_64.c | 23 -----------------------
> arch/x86/kernel/smpboot.c | 29 +++++++++++++++++++++++++++++
> include/asm-x86/smp.h | 1 +
> 4 files changed, 30 insertions(+), 55 deletions(-)
>
> diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
> index c4abfab..aff137c 100644
> --- a/arch/x86/kernel/process_32.c
> +++ b/arch/x86/kernel/process_32.c
> @@ -74,38 +74,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
> return ((unsigned long *)tsk->thread.sp)[3];
> }
>
> -#ifdef CONFIG_HOTPLUG_CPU
> -#include <asm/nmi.h>
> -
> -/* We don't actually take CPU down, just spin without interrupts. */
> -void native_play_dead(void)
> -{
> - int cpu = raw_smp_processor_id();
> -
> - idle_task_exit();
> -
> - reset_lazy_tlbstate();
> -
> - irq_ctx_exit(cpu);
> -
> - mb();
> - /* Ack it */
> - __get_cpu_var(cpu_state) = CPU_DEAD;
> -
> - /*
> - * With physical CPU hotplug, we should halt the cpu
> - */
> - local_irq_disable();
> - /* mask all interrupts, flush any and all caches, and halt */
> - wbinvd_halt();
> -}
> -#else
> -void native_play_dead(void)
> -{
> - BUG();
> -}
> -#endif /* CONFIG_HOTPLUG_CPU */
> -
> /*
> * The idle thread. There's no useful work to be
> * done, so just try to conserve power and have a
> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
> index 1cca50c..b2bab8e 100644
> --- a/arch/x86/kernel/process_64.c
> +++ b/arch/x86/kernel/process_64.c
> @@ -87,29 +87,6 @@ void exit_idle(void)
> __exit_idle();
> }
>
> -#ifdef CONFIG_HOTPLUG_CPU
> -DECLARE_PER_CPU(int, cpu_state);
> -
> -#include <linux/nmi.h>
> -/* We halt the CPU with physical CPU hotplug */
> -void native_play_dead(void)
> -{
> - idle_task_exit();
> - mb();
> - /* Ack it */
> - __get_cpu_var(cpu_state) = CPU_DEAD;
> -
> - local_irq_disable();
> - /* mask all interrupts, flush any and all caches, and halt */
> - wbinvd_halt();
> -}
> -#else
> -void native_play_dead(void)
> -{
> - BUG();
> -}
> -#endif /* CONFIG_HOTPLUG_CPU */
> -
> /*
> * The idle thread. There's no useful work to be
> * done, so just try to conserve power and have a
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index c6832ca..58d8c6c 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -1399,6 +1399,29 @@ void native_cpu_die(unsigned int cpu)
> }
> printk(KERN_ERR "CPU %u didn't die...\n", cpu);
> }
> +
> +void play_dead_common(void)
> +{
> + idle_task_exit();
> + reset_lazy_tlbstate();
> + irq_ctx_exit(raw_smp_processor_id());
> +
> + mb();
> + /* Ack it */
> + __get_cpu_var(cpu_state) = CPU_DEAD;
> +
> + /*
> + * With physical CPU hotplug, we should halt the cpu
> + */
> + local_irq_disable();
> +}
> +
> +void native_play_dead(void)
> +{
> + play_dead_common();
> + wbinvd_halt();
> +}
> +
> #else /* ... !CONFIG_HOTPLUG_CPU */
> int native_cpu_disable(void)
> {
> @@ -1410,4 +1433,10 @@ void native_cpu_die(unsigned int cpu)
> /* We said "no" in __cpu_disable */
> BUG();
> }
> +
> +void native_play_dead(void)
> +{
> + BUG();
> +}
> +
> #endif
> diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
> index dba14d3..95b28c1 100644
> --- a/include/asm-x86/smp.h
> +++ b/include/asm-x86/smp.h
> @@ -135,6 +135,7 @@ int native_cpu_up(unsigned int cpunum);
> int native_cpu_disable(void);
> void native_cpu_die(unsigned int cpu);
> void native_play_dead(void);
> +void play_dead_common(void);
>
> void native_send_call_func_ipi(cpumask_t mask);
> void native_send_call_func_single_ipi(int cpu);
>