debuggers.hg
changeset 21140:cd6c6c685015
cpuidle: mwait on softirq_pending & remove wakeup ipis
For cpu which enter deep C state via monitor/mwait, wakeup can be done
by writing to the monitored memory. So once monitor softirq_pending,
we can remove the redundant ipis.
Signed-off-by: Yu Ke <ke.yu@intel.com>
Signed-off-by: Wei Gang <gang.wei@intel.com>
For cpu which enter deep C state via monitor/mwait, wakeup can be done
by writing to the monitored memory. So once monitor softirq_pending,
we can remove the redundant ipis.
Signed-off-by: Yu Ke <ke.yu@intel.com>
Signed-off-by: Wei Gang <gang.wei@intel.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Tue Apr 06 06:52:11 2010 +0100 (2010-04-06) |
parents | 4a3e131f7498 |
children | fe30bd463e84 |
files | xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/hpet.c xen/include/xen/cpuidle.h |
line diff
1.1 --- a/xen/arch/x86/acpi/cpu_idle.c Tue Apr 06 06:51:04 2010 +0100 1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c Tue Apr 06 06:52:11 2010 +0100 1.3 @@ -69,6 +69,14 @@ boolean_param("lapic_timer_c2_ok", local 1.4 1.5 static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS]; 1.6 1.7 +static char* acpi_cstate_method_name[] = 1.8 +{ 1.9 + "NONE", 1.10 + "SYSIO", 1.11 + "FFH", 1.12 + "HALT" 1.13 +}; 1.14 + 1.15 static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power) 1.16 { 1.17 uint32_t i, idle_usage = 0; 1.18 @@ -92,6 +100,7 @@ static void print_acpi_power(uint32_t cp 1.19 printk("type[C%d] ", power->states[i].type); 1.20 printk("latency[%03d] ", power->states[i].latency); 1.21 printk("usage[%08d] ", power->states[i].usage); 1.22 + printk("method[%5s] ", acpi_cstate_method_name[power->states[i].entry_method]); 1.23 printk("duration[%"PRId64"]\n", res); 1.24 } 1.25 printk(" C0:\tusage[%08d] duration[%"PRId64"]\n", 1.26 @@ -140,11 +149,43 @@ static void acpi_safe_halt(void) 1.27 1.28 #define MWAIT_ECX_INTERRUPT_BREAK (0x1) 1.29 1.30 +/* 1.31 + * The bit is set iff cpu use monitor/mwait to enter C state 1.32 + * with this flag set, CPU can be waken up from C state 1.33 + * by writing to specific memory address, instead of sending IPI 1.34 + */ 1.35 +static cpumask_t cpuidle_mwait_flags; 1.36 + 1.37 +void cpuidle_wakeup_mwait(cpumask_t *mask) 1.38 +{ 1.39 + cpumask_t target; 1.40 + int cpu; 1.41 + 1.42 + cpus_and(target, *mask, cpuidle_mwait_flags); 1.43 + 1.44 + /* cpu is 'mwait'ing at softirq_pending, 1.45 + writing to it will wake up CPU */ 1.46 + for_each_cpu_mask(cpu, target) 1.47 + set_bit(TIMER_SOFTIRQ, &softirq_pending(cpu)); 1.48 + 1.49 + cpus_andnot(*mask, *mask, cpuidle_mwait_flags); 1.50 +} 1.51 + 1.52 static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) 1.53 { 1.54 - __monitor((void *)current, 0, 0); 1.55 + int cpu = smp_processor_id(); 1.56 + 1.57 + __monitor((void *)&softirq_pending(cpu), 0, 0); 1.58 + 1.59 smp_mb(); 1.60 - __mwait(eax, ecx); 1.61 + if (!softirq_pending(cpu)) 1.62 + { 1.63 + cpu_set(cpu, cpuidle_mwait_flags); 1.64 + 1.65 + __mwait(eax, ecx); 1.66 + 1.67 + cpu_clear(cpu, cpuidle_mwait_flags); 1.68 + } 1.69 } 1.70 1.71 static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
2.1 --- a/xen/arch/x86/hpet.c Tue Apr 06 06:51:04 2010 +0100 2.2 +++ b/xen/arch/x86/hpet.c Tue Apr 06 06:52:11 2010 +0100 2.3 @@ -166,6 +166,8 @@ static int evt_do_broadcast(cpumask_t ma 2.4 ret = 1; 2.5 } 2.6 2.7 + cpuidle_wakeup_mwait(&mask); 2.8 + 2.9 if ( !cpus_empty(mask) ) 2.10 { 2.11 cpumask_raise_softirq(mask, TIMER_SOFTIRQ);
3.1 --- a/xen/include/xen/cpuidle.h Tue Apr 06 06:51:04 2010 +0100 3.2 +++ b/xen/include/xen/cpuidle.h Tue Apr 06 06:52:11 2010 +0100 3.3 @@ -86,6 +86,8 @@ struct cpuidle_governor 3.4 extern struct cpuidle_governor *cpuidle_current_governor; 3.5 void cpuidle_disable_deep_cstate(void); 3.6 3.7 +extern void cpuidle_wakeup_mwait(cpumask_t *mask); 3.8 + 3.9 #define CPUIDLE_DRIVER_STATE_START 1 3.10 3.11 #endif /* _XEN_CPUIDLE_H */