When running WaaG, we need to enable HWP to boost performance in some scenarios. But when HWP is enabled in BIOS, windows does not turn on HWP driver automatically just like Linux does. It requires _CPC table in ACPI as well.
The _CPC table contains information about the HWP baseline registers. Those regs are defined as architectural MSRs, so they should be the same on different CPU models. Thus we can hard code the _CPC table.
When we turn off HWP in BIOS, windows's HWP driver will still be loaded based on the _CPC table. This will cause the guest fail to boot. So here we need read CPUID first, only add _CPC when HWP is enabled.
Tracked-On: #7695 Signed-off-by: Wu Zhou <wu.zhou@...> --- devicemodel/hw/platform/acpi/acpi_pm.c | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/devicemodel/hw/platform/acpi/acpi_pm.c b/devicemodel/hw/platform/acpi/acpi_pm.c index 5d953717ff..1e1a27b629 100644 --- a/devicemodel/hw/platform/acpi/acpi_pm.c +++ b/devicemodel/hw/platform/acpi/acpi_pm.c @@ -316,6 +316,51 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id) return 0; } +/* _CPC: Continuous Performance Control + * Hard code a V3 CPC table, describing HWP register interface. + */ +static void dsdt_write_cpc(void) +{ + dsdt_line(""); + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (Package (0x17)"); + dsdt_line(" {"); + dsdt_line(" 0x17,"); + dsdt_line(" 0x03,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x00000000000000CE, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E7, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E8, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x02, 0x01, 0x0000000000000777, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x01, 0x00, 0x0000000000000770, 0x04, )},"); + dsdt_line(" One,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x0A, 0x20, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000774, 0x04, )},"); + dsdt_line(" Zero,"); + dsdt_line(" Zero,"); + dsdt_line(" Zero"); + dsdt_line(" })"); + dsdt_line(" }"); +} + +static bool is_hwp_enabled(void) +{ + uint32_t eax, ebx, ecx, edx; + do_cpuid(0x6, 0, &eax, &ebx, &ecx, &edx); + + return ((eax & (0x1U << 7)) != 0); +} + void pm_write_dsdt(struct vmctx *ctx, int ncpu) { int i; @@ -364,6 +409,18 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu) } } + if (is_hwp_enabled()) { + if (i == 0) { + dsdt_write_cpc(); + } else { + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (^^PR00._CPC)"); + dsdt_line(" }"); + dsdt_line(""); + } + } + dsdt_line(" }"); } }
|
|
Better to have a comment, that the patch has a pre-condition: host CPUID.06H:EAX.[7] can't be hidden by vCPUID of Service VM.
toggle quoted messageShow quoted text
-----Original Message----- From: acrn-dev@... <acrn-dev@...> On Behalf Of Zhou, Wu Sent: Monday, June 6, 2022 9:17 PM To: acrn-dev@... Subject: [acrn-dev] [PATCH] dm: add _CPC to guest ACPI when HWP is enabled
When running WaaG, we need to enable HWP to boost performance in some scenarios. But when HWP is enabled in BIOS, windows does not turn on HWP driver automatically just like Linux does. It requires _CPC table in ACPI as well.
The _CPC table contains information about the HWP baseline registers. Those regs are defined as architectural MSRs, so they should be the same on different CPU models. Thus we can hard code the _CPC table.
When we turn off HWP in BIOS, windows's HWP driver will still be loaded based on the _CPC table. This will cause the guest fail to boot. So here we need read CPUID first, only add _CPC when HWP is enabled.
Tracked-On: #7695 Signed-off-by: Wu Zhou <wu.zhou@...> --- devicemodel/hw/platform/acpi/acpi_pm.c | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/devicemodel/hw/platform/acpi/acpi_pm.c b/devicemodel/hw/platform/acpi/acpi_pm.c index 5d953717ff..1e1a27b629 100644 --- a/devicemodel/hw/platform/acpi/acpi_pm.c +++ b/devicemodel/hw/platform/acpi/acpi_pm.c @@ -316,6 +316,51 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id) return 0; }
+/* _CPC: Continuous Performance Control + * Hard code a V3 CPC table, describing HWP register interface. + */ +static void dsdt_write_cpc(void) +{ + dsdt_line(""); + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (Package (0x17)"); + dsdt_line(" {"); + dsdt_line(" 0x17,"); + dsdt_line(" 0x03,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x00000000000000CE, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E7, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E8, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x02, 0x01, 0x0000000000000777, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x01, 0x00, 0x0000000000000770, 0x04, )},"); + dsdt_line(" One,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x0A, 0x20, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000774, 0x04, )},"); + dsdt_line(" Zero,"); + dsdt_line(" Zero,"); + dsdt_line(" Zero"); + dsdt_line(" })"); + dsdt_line(" }"); +} + +static bool is_hwp_enabled(void) +{ + uint32_t eax, ebx, ecx, edx; + do_cpuid(0x6, 0, &eax, &ebx, &ecx, &edx); + + return ((eax & (0x1U << 7)) != 0); +} + void pm_write_dsdt(struct vmctx *ctx, int ncpu) { int i; @@ -364,6 +409,18 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu) } }
+ if (is_hwp_enabled()) { + if (i == 0) { + dsdt_write_cpc(); + } else { + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (^^PR00._CPC)"); + dsdt_line(" }"); + dsdt_line(""); + } + } + dsdt_line(" }"); } }
|
|
On 2022/6/6 21:16, Zhou, Wu wrote: When running WaaG, we need to enable HWP to boost performance in some scenarios. But when HWP is enabled in BIOS, windows does not turn on HWP driver automatically just like Linux does. It requires _CPC table in ACPI as well. The _CPC table contains information about the HWP baseline registers. Those regs are defined as architectural MSRs, so they should be the same on different CPU models. Thus we can hard code the _CPC table. When we turn off HWP in BIOS, windows's HWP driver will still be loaded based on the _CPC table. This will cause the guest fail to boot. So here we need read CPUID first, only add _CPC when HWP is enabled. Tracked-On: #7695 Signed-off-by: Wu Zhou <wu.zhou@...> --- devicemodel/hw/platform/acpi/acpi_pm.c | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/devicemodel/hw/platform/acpi/acpi_pm.c b/devicemodel/hw/platform/acpi/acpi_pm.c index 5d953717ff..1e1a27b629 100644 --- a/devicemodel/hw/platform/acpi/acpi_pm.c +++ b/devicemodel/hw/platform/acpi/acpi_pm.c @@ -316,6 +316,51 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id) return 0; } +/* _CPC: Continuous Performance Control + * Hard code a V3 CPC table, describing HWP register interface. + */ +static void dsdt_write_cpc(void) +{ + dsdt_line(""); + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (Package (0x17)"); + dsdt_line(" {"); + dsdt_line(" 0x17,"); + dsdt_line(" 0x03,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x00000000000000CE, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E7, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E8, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x02, 0x01, 0x0000000000000777, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x01, 0x00, 0x0000000000000770, 0x04, )},"); + dsdt_line(" One,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x0A, 0x20, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000774, 0x04, )},"); + dsdt_line(" Zero,"); + dsdt_line(" Zero,"); + dsdt_line(" Zero"); + dsdt_line(" })"); + dsdt_line(" }"); +} + +static bool is_hwp_enabled(void) +{ + uint32_t eax, ebx, ecx, edx; + do_cpuid(0x6, 0, &eax, &ebx, &ecx, &edx); + + return ((eax & (0x1U << 7)) != 0); +} This is used to check whether the HWP is supported. Can we use the function name of is_hwp_supported? + void pm_write_dsdt(struct vmctx *ctx, int ncpu) { int i; @@ -364,6 +409,18 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu) } } + if (is_hwp_enabled()) { + if (i == 0) { + dsdt_write_cpc(); + } else { + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (^^PR00._CPC)"); + dsdt_line(" }"); + dsdt_line(""); + } + } + dsdt_line(" }"); } }
|
|
On Mon, Jun 06, 2022 at 01:16:50PM +0000, Zhou, Wu wrote: When running WaaG, we need to enable HWP to boost performance in some scenarios. But when HWP is enabled in BIOS, windows does not turn on HWP driver automatically just like Linux does. It requires _CPC table in ACPI as well.
The _CPC table contains information about the HWP baseline registers. Those regs are defined as architectural MSRs, so they should be the same on different CPU models. Thus we can hard code the _CPC table.
When we turn off HWP in BIOS, windows's HWP driver will still be loaded based on the _CPC table. This will cause the guest fail to boot. So here we need read CPUID first, only add _CPC when HWP is enabled.
Tracked-On: #7695 Signed-off-by: Wu Zhou <wu.zhou@...> --- devicemodel/hw/platform/acpi/acpi_pm.c | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/devicemodel/hw/platform/acpi/acpi_pm.c b/devicemodel/hw/platform/acpi/acpi_pm.c index 5d953717ff..1e1a27b629 100644 --- a/devicemodel/hw/platform/acpi/acpi_pm.c +++ b/devicemodel/hw/platform/acpi/acpi_pm.c @@ -316,6 +316,51 @@ static int dsdt_write_pss(struct vmctx *ctx, int vcpu_id) return 0; } +/* _CPC: Continuous Performance Control + * Hard code a V3 CPC table, describing HWP register interface. + */ +static void dsdt_write_cpc(void) +{ + dsdt_line(""); + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (Package (0x17)"); + dsdt_line(" {"); + dsdt_line(" 0x17,"); + dsdt_line(" 0x03,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x00000000000000CE, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000771, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x10, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x00, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x08, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(SystemMemory, 0x00, 0x00, 0x0000000000000000, , )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E7, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x40, 0x00, 0x00000000000000E8, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x02, 0x01, 0x0000000000000777, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x01, 0x00, 0x0000000000000770, 0x04, )},"); + dsdt_line(" One,"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x0A, 0x20, 0x0000000000000774, 0x04, )},"); + dsdt_line(" ResourceTemplate() {Register(FFixedHW, 0x08, 0x18, 0x0000000000000774, 0x04, )},"); Please add comments to explain the detailed fields of each MSR like like IA32_HWP_CAP(771H), MSR_PLATFORM_INFO, IA32_MPERF, etc. + dsdt_line(" Zero,"); + dsdt_line(" Zero,"); + dsdt_line(" Zero"); + dsdt_line(" })"); + dsdt_line(" }"); +} + +static bool is_hwp_enabled(void) +{ + uint32_t eax, ebx, ecx, edx; + do_cpuid(0x6, 0, &eax, &ebx, &ecx, &edx); + + return ((eax & (0x1U << 7)) != 0); Please define macros for 0x6, and (0x1U << 7) It is hard to understand w/o checking spec. +} + void pm_write_dsdt(struct vmctx *ctx, int ncpu) { int i; @@ -364,6 +409,18 @@ void pm_write_dsdt(struct vmctx *ctx, int ncpu) } } + if (is_hwp_enabled()) { + if (i == 0) { + dsdt_write_cpc(); + } else { + dsdt_line(" Method (_CPC, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (^^PR00._CPC)"); + dsdt_line(" }"); + dsdt_line(""); + } + } Let's print a log by pr_info to shows the HWP is enabled or disabled. + dsdt_line(" }"); } }
|
|