HV: Use the mwait instead of pause for cpu_idle

Now it will use the pause when cpu is in idle state. It will consume
more power. If the mwait is supported, it will use the monitor/mwait to
enter the deep CPU C-state. It helps to save power.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
This commit is contained in:
Zhao Yakui
2019-08-27 16:25:39 +08:00
parent 21bd1c8bd3
commit a7706e0c39
4 changed files with 49 additions and 17 deletions

View File

@@ -367,9 +367,34 @@ void stop_pcpus(void)
wait_pcpus_offline(mask);
}
static
inline void asm_monitor(const uint64_t *addr, uint64_t ecx, uint64_t edx)
{
asm volatile("monitor\n" : : "a" (addr), "c" (ecx), "d" (edx));
}
static
inline void asm_mwait(uint64_t eax, uint64_t ecx)
{
asm volatile("mwait\n" : : "a" (eax), "c" (ecx));
}
void cpu_do_idle(void)
{
asm_pause();
uint16_t pcpu_id = get_pcpu_id();
struct sched_context *ctx = &per_cpu(sched_ctx, pcpu_id);
if (ctx->mwait_flags) {
CPU_IRQ_DISABLE();
asm_monitor(&ctx->flags, 0UL, 0UL);
if (!bitmap_test(NEED_RESCHEDULE, &ctx->flags))
asm_mwait(0x60UL, 1UL);
CPU_IRQ_ENABLE();
} else {
CPU_IRQ_ENABLE();
asm_pause();
CPU_IRQ_DISABLE();
}
}
/**
@@ -415,18 +440,6 @@ static void print_hv_banner(void)
printf(boot_msg);
}
static
inline void asm_monitor(const uint64_t *addr, uint64_t ecx, uint64_t edx)
{
asm volatile("monitor\n" : : "a" (addr), "c" (ecx), "d" (edx));
}
static
inline void asm_mwait(uint64_t eax, uint64_t ecx)
{
asm volatile("mwait\n" : : "a" (eax), "c" (ecx));
}
/* wait until *sync == wake_sync */
void wait_sync_change(uint64_t *sync, uint64_t wake_sync)
{