ia64/xen-unstable

changeset 13249:bf25488db8eb

[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>
author kfraser@localhost.localdomain
date Wed Jan 03 14:08:42 2007 +0000 (2007-01-03)
parents 55be48549bb1
children 60f91c9f1a24
files linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c	Wed Jan 03 13:55:53 2007 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c	Wed Jan 03 14:08:42 2007 +0000
     1.3 @@ -101,8 +101,24 @@ void enable_hlt(void)
     1.4  
     1.5  EXPORT_SYMBOL(enable_hlt);
     1.6  
     1.7 -/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
     1.8 -void xen_idle(void)
     1.9 +/*
    1.10 + * On SMP it's slightly faster (but much more power-consuming!)
    1.11 + * to poll the ->work.need_resched flag instead of waiting for the
    1.12 + * cross-CPU IPI to arrive. Use this option with caution.
    1.13 + */
    1.14 +static void poll_idle(void)
    1.15 +{
    1.16 +	local_irq_enable();
    1.17 +
    1.18 +	asm volatile(
    1.19 +		"2:"
    1.20 +		"testl %0, %1;"
    1.21 +		"rep; nop;"
    1.22 +		"je 2b;"
    1.23 +		: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
    1.24 +}
    1.25 +
    1.26 +static void xen_idle(void)
    1.27  {
    1.28  	local_irq_disable();
    1.29  
    1.30 @@ -162,7 +178,7 @@ void cpu_idle(void)
    1.31  				play_dead();
    1.32  
    1.33  			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
    1.34 -			xen_idle();
    1.35 +			pm_idle();
    1.36  		}
    1.37  		preempt_enable_no_resched();
    1.38  		schedule();
    1.39 @@ -198,9 +214,24 @@ void cpu_idle_wait(void)
    1.40  }
    1.41  EXPORT_SYMBOL_GPL(cpu_idle_wait);
    1.42  
    1.43 -/* XXX XEN doesn't use mwait_idle(), select_idle_routine(), idle_setup(). */
    1.44 -/* Always use xen_idle() instead. */
    1.45 -void __devinit select_idle_routine(const struct cpuinfo_x86 *c) {}
    1.46 +void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
    1.47 +{
    1.48 +	if (!pm_idle)
    1.49 +		pm_idle = xen_idle;
    1.50 +}
    1.51 +
    1.52 +static int __init idle_setup (char *str)
    1.53 +{
    1.54 +	if (!strncmp(str, "poll", 4)) {
    1.55 +		printk("using polling idle threads.\n");
    1.56 +		pm_idle = poll_idle;
    1.57 +	}
    1.58 +
    1.59 +	boot_option_idle_override = 1;
    1.60 +	return 1;
    1.61 +}
    1.62 +
    1.63 +__setup("idle=", idle_setup);
    1.64  
    1.65  void show_regs(struct pt_regs * regs)
    1.66  {
     2.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c	Wed Jan 03 13:55:53 2007 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c	Wed Jan 03 14:08:42 2007 +0000
     2.3 @@ -119,8 +119,26 @@ void exit_idle(void)
     2.4  	__exit_idle();
     2.5  }
     2.6  
     2.7 -/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
     2.8 -void xen_idle(void)
     2.9 +/*
    2.10 + * On SMP it's slightly faster (but much more power-consuming!)
    2.11 + * to poll the ->need_resched flag instead of waiting for the
    2.12 + * cross-CPU IPI to arrive. Use this option with caution.
    2.13 + */
    2.14 +static void poll_idle(void)
    2.15 +{
    2.16 +	local_irq_enable();
    2.17 +
    2.18 +	asm volatile(
    2.19 +		"2:"
    2.20 +		"testl %0,%1;"
    2.21 +		"rep; nop;"
    2.22 +		"je 2b;"
    2.23 +		: :
    2.24 +		"i" (_TIF_NEED_RESCHED),
    2.25 +		"m" (current_thread_info()->flags));
    2.26 +}
    2.27 +
    2.28 +static void xen_idle(void)
    2.29  {
    2.30  	local_irq_disable();
    2.31  
    2.32 @@ -171,7 +189,7 @@ void cpu_idle (void)
    2.33  			if (cpu_is_offline(smp_processor_id()))
    2.34  				play_dead();
    2.35  			enter_idle();
    2.36 -			xen_idle();
    2.37 +			pm_idle();
    2.38  			__exit_idle();
    2.39  		}
    2.40  
    2.41 @@ -210,9 +228,24 @@ void cpu_idle_wait(void)
    2.42  }
    2.43  EXPORT_SYMBOL_GPL(cpu_idle_wait);
    2.44  
    2.45 -/* XXX XEN doesn't use mwait_idle(), select_idle_routine(), idle_setup(). */
    2.46 -/* Always use xen_idle() instead. */
    2.47 -void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) {}
    2.48 +void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) 
    2.49 +{
    2.50 +	if (!pm_idle)
    2.51 +		pm_idle = xen_idle;
    2.52 +}
    2.53 +
    2.54 +static int __init idle_setup (char *str)
    2.55 +{
    2.56 +	if (!strncmp(str, "poll", 4)) {
    2.57 +		printk("using polling idle threads.\n");
    2.58 +		pm_idle = poll_idle;
    2.59 +	}
    2.60 +
    2.61 +	boot_option_idle_override = 1;
    2.62 +	return 1;
    2.63 +}
    2.64 +
    2.65 +__setup("idle=", idle_setup);
    2.66  
    2.67  /* Prints also some state that isn't saved in the pt_regs */ 
    2.68  void __show_regs(struct pt_regs * regs)