mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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>
This commit is contained in:
1 parent
4e8bf17138
commit
3d521e933e
3 files changed
+47
-2
No files matched your search
@@ -69,6 +69,14 @@ boolean_param("lapic_timer_c2_ok", local_apic_timer_c2_ok);
|
||||
|
||||
static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS];
|
||||
|
||||
static char* acpi_cstate_method_name[] =
|
||||
{
|
||||
"NONE",
|
||||
"SYSIO",
|
||||
"FFH",
|
||||
"HALT"
|
||||
};
|
||||
|
||||
static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power)
|
||||
{
|
||||
uint32_t i, idle_usage = 0;
|
||||
@@ -92,6 +100,7 @@ static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power)
|
||||
printk("type[C%d] ", power->states[i].type);
|
||||
printk("latency[%03d] ", power->states[i].latency);
|
||||
printk("usage[%08d] ", power->states[i].usage);
|
||||
printk("method[%5s] ", acpi_cstate_method_name[power->states[i].entry_method]);
|
||||
printk("duration[%"PRId64"]\n", res);
|
||||
}
|
||||
printk(" C0:\tusage[%08d] duration[%"PRId64"]\n",
|
||||
@@ -140,11 +149,43 @@ static void acpi_safe_halt(void)
|
||||
|
||||
#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
|
||||
|
||||
/*
|
||||
* The bit is set iff cpu use monitor/mwait to enter C state
|
||||
* with this flag set, CPU can be waken up from C state
|
||||
* by writing to specific memory address, instead of sending IPI
|
||||
*/
|
||||
static cpumask_t cpuidle_mwait_flags;
|
||||
|
||||
void cpuidle_wakeup_mwait(cpumask_t *mask)
|
||||
{
|
||||
cpumask_t target;
|
||||
int cpu;
|
||||
|
||||
cpus_and(target, *mask, cpuidle_mwait_flags);
|
||||
|
||||
/* cpu is 'mwait'ing at softirq_pending,
|
||||
writing to it will wake up CPU */
|
||||
for_each_cpu_mask(cpu, target)
|
||||
set_bit(TIMER_SOFTIRQ, &softirq_pending(cpu));
|
||||
|
||||
cpus_andnot(*mask, *mask, cpuidle_mwait_flags);
|
||||
}
|
||||
|
||||
static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
||||
{
|
||||
__monitor((void *)current, 0, 0);
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
__monitor((void *)&softirq_pending(cpu), 0, 0);
|
||||
|
||||
smp_mb();
|
||||
__mwait(eax, ecx);
|
||||
if (!softirq_pending(cpu))
|
||||
{
|
||||
cpu_set(cpu, cpuidle_mwait_flags);
|
||||
|
||||
__mwait(eax, ecx);
|
||||
|
||||
cpu_clear(cpu, cpuidle_mwait_flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
|
||||
|
||||
@@ -166,6 +166,8 @@ static int evt_do_broadcast(cpumask_t mask)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
cpuidle_wakeup_mwait(&mask);
|
||||
|
||||
if ( !cpus_empty(mask) )
|
||||
{
|
||||
cpumask_raise_softirq(mask, TIMER_SOFTIRQ);
|
||||
|
||||
@@ -86,6 +86,8 @@ struct cpuidle_governor
|
||||
extern struct cpuidle_governor *cpuidle_current_governor;
|
||||
void cpuidle_disable_deep_cstate(void);
|
||||
|
||||
extern void cpuidle_wakeup_mwait(cpumask_t *mask);
|
||||
|
||||
#define CPUIDLE_DRIVER_STATE_START 1
|
||||
|
||||
#endif /* _XEN_CPUIDLE_H */
|
||||