Re: [PATCH] dm: add _CPC to guest ACPI when HWP is enabled


Zhao, Yakui
 

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(" }");
}
}

Join {acrn-dev@lists.projectacrn.org to automatically receive all group messages.