Matt Delco has uploaded this change for review. ( https://review.coreboot.org/27673
Change subject: soc/intel/skylake: add CPPC support ......................................................................
soc/intel/skylake: add CPPC support
ACPI defines a method _CPC for "Continuous Performance Control" (CPPC). Linux has a driver that enables features like speed shift without consulting ACPI. Other OSes instead rely on this information and need a _CPC present. Prior to this change performance in Win10 never exceeds 80% and MSR 0x770 is 0, while with this change higher speeds can be achieved and the MSR value is now 1.
Rather than add a large package to each processor I have the code add one global instance and each processor has a method that references that instance. I'm open to suggestions on a different place to place the package.
Change-Id: Ib7e0ae13f4b664b51e42f963e53c71f8832be062 Signed-off-by: Matt Delco delco@chromium.org --- M src/soc/intel/skylake/acpi.c 1 file changed, 152 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/73/27673/1
diff --git a/src/soc/intel/skylake/acpi.c b/src/soc/intel/skylake/acpi.c index 5bed118..d2d41c9 100644 --- a/src/soc/intel/skylake/acpi.c +++ b/src/soc/intel/skylake/acpi.c @@ -501,6 +501,151 @@ acpigen_pop_len(); }
+#define CPPC_PACKAGE_NAME "\GCPC" + +static void generate_CPPC_method(void) +{ + acpigen_write_method("_CPC", 0); + acpigen_emit_byte(RETURN_OP); + acpigen_emit_namestring(CPPC_PACKAGE_NAME); + acpigen_pop_len(); +} + +static void generate_CPPC_package(bool version2) +{ + acpi_addr_t msr = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + .bit_width = 8, + .bit_offset = 0, + { + .access_size = 4 + }, + .addrl = 0, + .addrh = 0, + }; + static const acpi_addr_t unsupported = { + .space_id = ACPI_ADDRESS_SPACE_MEMORY, + .bit_width = 0, + .bit_offset = 0, + { + .resv = 0 + }, + .addrl = 0, + .addrh = 0, + }; + + acpigen_write_name(CPPC_PACKAGE_NAME); + acpigen_write_package(version2 ? 21 : 17); + + acpigen_write_dword(version2 ? 21 : 17); + acpigen_write_byte(version2 ? 2 : 1); + + // 0x771 is IA32_HWP_CAPABILITIES (RO) + msr.addrl = 0x771; + + // Highest Performance: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x00, 0x771, 0x04,)}, + acpigen_write_register_resource(&msr); + + // Nominal Performance -> Guaranteed Performance: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x771, 0x04,)}, + msr.bit_offset = 8; + acpigen_write_register_resource(&msr); + + // Lowest Nonlinear Performance -> Most Efficient Performance: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x10, 0x771, 0x04,)}, + msr.bit_offset = 16; + acpigen_write_register_resource(&msr); + + // Lowest Performance: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x18, 0x771, 0x04,)}, + msr.bit_offset = 24; + acpigen_write_register_resource(&msr); + + // Guaranteed Performance Register: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x771, 0x04,)}, + msr.bit_offset = 8; + acpigen_write_register_resource(&msr); + + // 0x774 is IA32_HWP_REQUEST (RW) + msr.addrl = 0x774; + + // Desired Performance Register: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x10, 0x774, 0x04,)}, + msr.bit_offset = 16; + acpigen_write_register_resource(&msr); + + // Minimum Performance Register: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x00, 0x774, 0x04,)}, + msr.bit_offset = 0; + acpigen_write_register_resource(&msr); + + // Maximum Performance Register: + // ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x774, 0x04,)}, + msr.bit_offset = 8; + acpigen_write_register_resource(&msr); + + // Performance Reduction Tolerance Register: + // ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)}, + acpigen_write_register_resource(&unsupported); + + // Time Window Register: + // ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)}, + acpigen_write_register_resource(&unsupported); + + // Counter Wraparound Time: + // ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)}, + acpigen_write_register_resource(&unsupported); + + // 0xE7 is IA32_MPERF + msr.addrl = 0xe7; + + // Reference Performance Counter Register: + // ResourceTemplate(){Register(FFixedHW, 0x40, 0x00, 0x0E7, 0x04,)}, + msr.bit_width = 64; + msr.bit_offset = 0; + acpigen_write_register_resource(&msr); + + // 0xE8 is IA32_APERF + msr.addrl = 0xe8; + + // Delivered Performance Counter Register: + // ResourceTemplate(){Register(FFixedHW, 0x40, 0x00, 0x0E8, 0x04,)}, + acpigen_write_register_resource(&msr); + + // 0x777 is IA32_HWP_STATUS + msr.addrl = 0x777; + + // Performance Limited Register: + // ResourceTemplate(){Register(FFixedHW, 0x01, 0x02, 0x777, 0x04,)}, + msr.bit_width = 1; + msr.bit_offset = 2; + acpigen_write_register_resource(&msr); + + // 0x770 is IA32_PM_ENABLE + msr.addrl = 0x770; + + // CPPC Enable Register: + // ResourceTemplate(){Register(FFixedHW, 0x01, 0x00, 0x770, 0x04,)}, + msr.bit_offset = 0; + acpigen_write_register_resource(&msr); + + if (version2) { + // Autonomous Selection Enable = 1 + acpigen_write_dword(1); + + // Autonomous Activity Window Register + acpigen_write_register_resource(&unsupported); + + // Energy Performance Preference Register + acpigen_write_register_resource(&unsupported); + + // Reference Performance + acpigen_write_register_resource(&unsupported); + } + acpigen_pop_len(); +} + void generate_cpu_entries(struct device *device) { int core_id, cpu_id, pcontrol_blk = ACPI_BASE_ADDRESS, plen = 6; @@ -520,6 +665,9 @@ printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n", numcpus, cores_per_package);
+ if (config->eist_enable && config->speed_shift_enable) + generate_CPPC_package(TRUE); + for (cpu_id = 0; cpu_id < numcpus; cpu_id++) { for (core_id = 0; core_id < cores_per_package; core_id++) { if (core_id > 0) { @@ -535,11 +683,13 @@ generate_c_state_entries(is_s0ix_enable, max_c_state);
- if (config->eist_enable) + if (config->eist_enable) { /* Generate P-state tables */ generate_p_state_entries(core_id, cores_per_package); - + if (config->speed_shift_enable) + generate_CPPC_method(); + } acpigen_pop_len(); } }