From 74df0974b207189ac8335ae8113a8c1019a6ef5f Mon Sep 17 00:00:00 2001 From: ouyangxiangzhen Date: Mon, 17 Jun 2024 18:31:06 +0800 Subject: [PATCH] arch/x86_64: Add ARCH_X86_64_IDLE_NOP and ARCH_X86_64_IDLE_MWAIT Using the HLT instruction in VM usually traps into the Hypervisor and releases CPU control. This will result in real-time performance degradation. Using the NOP or MWAIT instruction for an IDLE loop can reduce energy consumption while not trapping into the Hypervisor. Signed-off-by: ouyangxiangzhen --- arch/x86_64/src/common/Kconfig | 32 ++++++++++++++++++++++++++ arch/x86_64/src/intel64/intel64_idle.c | 20 +++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/x86_64/src/common/Kconfig b/arch/x86_64/src/common/Kconfig index a20a456a31..9effd0d296 100644 --- a/arch/x86_64/src/common/Kconfig +++ b/arch/x86_64/src/common/Kconfig @@ -35,6 +35,38 @@ config ARCH_X86_64_ACPI_BIOS endif # ARCH_X86_64_ACPI +choice + prompt "x86_64 Idle Loop Options" + default ARCH_X86_64_IDLE_DEFAULT + +config ARCH_X86_64_IDLE_DEFAULT + bool "Idle Loop - HLT" + ---help--- + Use HLT instruction in IDLE loop. + +config ARCH_X86_64_IDLE_NOP + bool "Idle Loop - NOP" + ---help--- + Use NOP instruction in IDLE loop. + This can prevent VM exit in some virtualized environments, + thereby improving real-time performance. + +config ARCH_X86_64_IDLE_MWAIT + bool "Idle Loop - MWAIT" + ---help--- + Use MONITOR/MWAIT instruction in IDLE loop. + +endchoice # x86_64 Idle Loop Options + +config ARCH_X86_64_IDLE_MWAIT_ECX + hex "Idle MWAIT ECX value" + default 0x0 + range 0x0 0xF + depends on ARCH_X86_64_IDLE_MWAIT + ---help--- + MWAIT ECX indicates the C-States + (0x0 for C1, 0x1 for C1E and so on). + config ARCH_X86_64_HAVE_XSAVE bool "XSAVE support" default y diff --git a/arch/x86_64/src/intel64/intel64_idle.c b/arch/x86_64/src/intel64/intel64_idle.c index 2f56fdf1c0..53ed6db048 100644 --- a/arch/x86_64/src/intel64/intel64_idle.c +++ b/arch/x86_64/src/intel64/intel64_idle.c @@ -64,7 +64,25 @@ void up_idle(void) * "fake" timer interrupts. Hopefully, something will wake up. */ - sched_process_timer(); + nxsched_process_timer(); +#elif defined(CONFIG_ARCH_X86_64_IDLE_NOP) + asm volatile("nop"); +#elif defined(CONFIG_ARCH_X86_64_IDLE_MWAIT_ECX) + /* Dummy value to make MONITOR/MWAIT work */ + + int dummy; + + /* MONITOR eax, ecx, edx */ + + asm volatile(".byte 0x0f, 0x01, 0xc8" :: + "a"(&dummy), "c"(0), "d"(0)); + + /* We enable sub C-state here and wait for interrupts */ + + /* MWAIT eax, ecx */ + + asm volatile(".byte 0x0f, 0x01, 0xc9" :: + "a"(0), "c"(CONFIG_ARCH_X86_64_IDLE_MWAIT_ECX)); #else __asm__ volatile("hlt"); #endif