aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-01-03 14:08:42 +0000
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-01-03 14:08:42 +0000
commit0550678b74b1afac96ff8e823bf50b436f66dc57 (patch)
treefdff9abbc9543e8e9022f02a2c1084ff9ba9672a
parent49f1cd42a181a4123c28e8262bc3c219e2dc74d4 (diff)
downloadxen-0550678b74b1afac96ff8e823bf50b436f66dc57.tar.gz
xen-0550678b74b1afac96ff8e823bf50b436f66dc57.tar.bz2
xen-0550678b74b1afac96ff8e823bf50b436f66dc57.zip
[LINUX] Implement the idle=poll option in the kernel when running on Xen.
This causes the kernel to use a polling loop rather than hypercall down to block. I have found this useful to profile the amount of sleep cycles when using xenoprof, there may be other uses. Signed-off-by: Amitabha Roy <amitabha.roy@gmail.com>
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c43
-rw-r--r--linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c45
2 files changed, 76 insertions, 12 deletions
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
index e6724a00b1..00a8d8a8eb 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
@@ -101,8 +101,24 @@ void enable_hlt(void)
EXPORT_SYMBOL(enable_hlt);
-/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-void xen_idle(void)
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->work.need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle(void)
+{
+ local_irq_enable();
+
+ asm volatile(
+ "2:"
+ "testl %0, %1;"
+ "rep; nop;"
+ "je 2b;"
+ : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
+}
+
+static void xen_idle(void)
{
local_irq_disable();
@@ -162,7 +178,7 @@ void cpu_idle(void)
play_dead();
__get_cpu_var(irq_stat).idle_timestamp = jiffies;
- xen_idle();
+ pm_idle();
}
preempt_enable_no_resched();
schedule();
@@ -198,9 +214,24 @@ void cpu_idle_wait(void)
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
-/* XXX XEN doesn't use mwait_idle(), select_idle_routine(), idle_setup(). */
-/* Always use xen_idle() instead. */
-void __devinit select_idle_routine(const struct cpuinfo_x86 *c) {}
+void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
+{
+ if (!pm_idle)
+ pm_idle = xen_idle;
+}
+
+static int __init idle_setup (char *str)
+{
+ if (!strncmp(str, "poll", 4)) {
+ printk("using polling idle threads.\n");
+ pm_idle = poll_idle;
+ }
+
+ boot_option_idle_override = 1;
+ return 1;
+}
+
+__setup("idle=", idle_setup);
void show_regs(struct pt_regs * regs)
{
diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c
index 65ba83c625..c12ebe0e01 100644
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c
@@ -119,8 +119,26 @@ void exit_idle(void)
__exit_idle();
}
-/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-void xen_idle(void)
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle(void)
+{
+ local_irq_enable();
+
+ asm volatile(
+ "2:"
+ "testl %0,%1;"
+ "rep; nop;"
+ "je 2b;"
+ : :
+ "i" (_TIF_NEED_RESCHED),
+ "m" (current_thread_info()->flags));
+}
+
+static void xen_idle(void)
{
local_irq_disable();
@@ -171,7 +189,7 @@ void cpu_idle (void)
if (cpu_is_offline(smp_processor_id()))
play_dead();
enter_idle();
- xen_idle();
+ pm_idle();
__exit_idle();
}
@@ -210,9 +228,24 @@ void cpu_idle_wait(void)
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
-/* XXX XEN doesn't use mwait_idle(), select_idle_routine(), idle_setup(). */
-/* Always use xen_idle() instead. */
-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) {}
+void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+{
+ if (!pm_idle)
+ pm_idle = xen_idle;
+}
+
+static int __init idle_setup (char *str)
+{
+ if (!strncmp(str, "poll", 4)) {
+ printk("using polling idle threads.\n");
+ pm_idle = poll_idle;
+ }
+
+ boot_option_idle_override = 1;
+ return 1;
+}
+
+__setup("idle=", idle_setup);
/* Prints also some state that isn't saved in the pt_regs */
void __show_regs(struct pt_regs * regs)