]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg CpuCommFeaturesLib: Reduce to set MSR_IA32_CLOCK_MODULATION
authorStar Zeng <star.zeng@intel.com>
Sat, 18 May 2019 08:55:27 +0000 (16:55 +0800)
committerStar Zeng <star.zeng@intel.com>
Thu, 6 Jun 2019 10:52:35 +0000 (18:52 +0800)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1810

This patch covers two problems.

1. Current code gets CPUID_THERMAL_POWER_MANAGEMENT in
ClockModulationInitialize() and uses its ECMD bit for all processors.
But ClockModulationInitialize() is only executed by BSP, that means
the bit is just for BSP.
It may have no functionality issue as all processors may have same
bit value in a great possibility. But for good practice, the code
should get CPUID_THERMAL_POWER_MANAGEMENT in ClockModulationSupport
(executed by all processors), and then use them in
ClockModulationInitialize() for all processors.
We can see that Aesni.c (and others) have used this good practice.

2. Current code uses 3 CPU_REGISTER_TABLE_WRITE_FIELD for
MSR_IA32_CLOCK_MODULATION in ClockModulationInitialize(), they can
be reduced to 1 CPU_REGISTER_TABLE_WRITE64 by getting
MSR_IA32_CLOCK_MODULATION for all processors in
ClockModulationSupport() and then update fields for register table
write in ClockModulationInitialize().

We may argue that there may be more times of MSR_IA32_CLOCK_MODULATION
getting. But actually the times of MSR_IA32_CLOCK_MODULATION getting
could be also reduced.

The reason is in ProgramProcessorRegister() of CpuFeaturesInitialize.c,
AsmMsrBitFieldWrite64 (AsmReadMsr64 + AsmWriteMsr64) will be used for
CPU_REGISTER_TABLE_WRITE_FIELD, and AsmWriteMsr64 will be used for
CPU_REGISTER_TABLE_WRITE64.

The times of MSR accessing could be reduced with this patch.
Without the patch:
3 CPU_REGISTER_TABLE_WRITE_FIELD (in ClockModulationInitialize)
  ==> 3 AsmMsrBitFieldWrite64
    ==> 3 AsmReadMsr64 + 3 AsmWriteMsr64

With the patch:
1 AsmReadMsr64 (in ClockModulationSupport) +
1 CPU_REGISTER_TABLE_WRITE64 (in ClockModulationInitialize)
  ==> 1 AsmWriteMsr64

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Chandana Kumar <chandana.c.kumar@intel.com>
Cc: Kevin Li <kevin.y.li@intel.com>
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
UefiCpuPkg/Library/CpuCommonFeaturesLib/ClockModulation.c
UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeatures.h
UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.c

index 61476858750138a95f793bc0ad291a80db47e174..b1c6bf6148f30ae270b69c6293956a6d4869b231 100644 (file)
@@ -1,13 +1,40 @@
 /** @file\r
   Clock Modulation feature.\r
 \r
-  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "CpuCommonFeatures.h"\r
 \r
+typedef struct  {\r
+  CPUID_THERMAL_POWER_MANAGEMENT_EAX  ThermalPowerManagementEax;\r
+  MSR_IA32_CLOCK_MODULATION_REGISTER  ClockModulation;\r
+} CLOCK_MODULATION_CONFIG_DATA;\r
+\r
+/**\r
+  Prepares for the data used by CPU feature detection and initialization.\r
+\r
+  @param[in]  NumberOfProcessors  The number of CPUs in the platform.\r
+\r
+  @return  Pointer to a buffer of CPU related configuration data.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+VOID *\r
+EFIAPI\r
+ClockModulationGetConfigData (\r
+  IN UINTN  NumberOfProcessors\r
+  )\r
+{\r
+  UINT32    *ConfigData;\r
+\r
+  ConfigData = AllocateZeroPool (sizeof (CLOCK_MODULATION_CONFIG_DATA) * NumberOfProcessors);\r
+  ASSERT (ConfigData != NULL);\r
+  return ConfigData;\r
+}\r
+\r
 /**\r
   Detects if Clock Modulation feature supported on current processor.\r
 \r
@@ -32,7 +59,22 @@ ClockModulationSupport (
   IN VOID                              *ConfigData  OPTIONAL\r
   )\r
 {\r
-  return (CpuInfo->CpuIdVersionInfoEdx.Bits.ACPI == 1);\r
+  CLOCK_MODULATION_CONFIG_DATA         *CmConfigData;\r
+\r
+  if (CpuInfo->CpuIdVersionInfoEdx.Bits.ACPI == 1) {\r
+    CmConfigData = (CLOCK_MODULATION_CONFIG_DATA *) ConfigData;\r
+    ASSERT (CmConfigData != NULL);\r
+    AsmCpuid (\r
+      CPUID_THERMAL_POWER_MANAGEMENT,\r
+      &CmConfigData[ProcessorNumber].ThermalPowerManagementEax.Uint32,\r
+      NULL,\r
+      NULL,\r
+      NULL\r
+      );\r
+    CmConfigData[ProcessorNumber].ClockModulation.Uint64 = AsmReadMsr64 (MSR_IA32_CLOCK_MODULATION);\r
+    return TRUE;\r
+  }\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -61,34 +103,29 @@ ClockModulationInitialize (
   IN BOOLEAN                           State\r
   )\r
 {\r
-  CPUID_THERMAL_POWER_MANAGEMENT_EAX   ThermalPowerManagementEax;\r
-  AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &ThermalPowerManagementEax.Uint32, NULL, NULL, NULL);\r
+  CLOCK_MODULATION_CONFIG_DATA         *CmConfigData;\r
+  MSR_IA32_CLOCK_MODULATION_REGISTER   *ClockModulation;\r
 \r
-  CPU_REGISTER_TABLE_WRITE_FIELD (\r
-    ProcessorNumber,\r
-    Msr,\r
-    MSR_IA32_CLOCK_MODULATION,\r
-    MSR_IA32_CLOCK_MODULATION_REGISTER,\r
-    Bits.OnDemandClockModulationDutyCycle,\r
-    PcdGet8 (PcdCpuClockModulationDutyCycle) >> 1\r
-    );\r
-  if (ThermalPowerManagementEax.Bits.ECMD == 1) {\r
-    CPU_REGISTER_TABLE_WRITE_FIELD (\r
-      ProcessorNumber,\r
-      Msr,\r
-      MSR_IA32_CLOCK_MODULATION,\r
-      MSR_IA32_CLOCK_MODULATION_REGISTER,\r
-      Bits.ExtendedOnDemandClockModulationDutyCycle,\r
-      PcdGet8 (PcdCpuClockModulationDutyCycle) & BIT0\r
-      );\r
+  CmConfigData = (CLOCK_MODULATION_CONFIG_DATA *) ConfigData;\r
+  ASSERT (CmConfigData != NULL);\r
+  ClockModulation = &CmConfigData[ProcessorNumber].ClockModulation;\r
+\r
+  if (State) {\r
+    ClockModulation->Bits.OnDemandClockModulationEnable = 1;\r
+    ClockModulation->Bits.OnDemandClockModulationDutyCycle = PcdGet8 (PcdCpuClockModulationDutyCycle) >> 1;\r
+    if (CmConfigData[ProcessorNumber].ThermalPowerManagementEax.Bits.ECMD == 1) {\r
+      ClockModulation->Bits.ExtendedOnDemandClockModulationDutyCycle = PcdGet8 (PcdCpuClockModulationDutyCycle) & BIT0;\r
+    }\r
+  } else {\r
+    ClockModulation->Bits.OnDemandClockModulationEnable = 0;\r
   }\r
-  CPU_REGISTER_TABLE_WRITE_FIELD (\r
+\r
+  CPU_REGISTER_TABLE_WRITE64 (\r
     ProcessorNumber,\r
     Msr,\r
     MSR_IA32_CLOCK_MODULATION,\r
-    MSR_IA32_CLOCK_MODULATION_REGISTER,\r
-    Bits.OnDemandClockModulationEnable,\r
-    (State) ? 1 : 0\r
+    ClockModulation->Uint64\r
     );\r
+\r
   return RETURN_SUCCESS;\r
 }\r
index af2fc41f759af31f2c6ef3080ccb62ab4f48ee61..9e784e916a858c9acd23f33a735867ce7ac41254 100644 (file)
@@ -87,6 +87,21 @@ AesniInitialize (
   IN BOOLEAN                           State\r
   );\r
 \r
+/**\r
+  Prepares for the data used by CPU feature detection and initialization.\r
+\r
+  @param[in]  NumberOfProcessors  The number of CPUs in the platform.\r
+\r
+  @return  Pointer to a buffer of CPU related configuration data.\r
+\r
+  @note This service could be called by BSP only.\r
+**/\r
+VOID *\r
+EFIAPI\r
+ClockModulationGetConfigData (\r
+  IN UINTN  NumberOfProcessors\r
+  );\r
+\r
 /**\r
   Detects if Clock Modulation feature supported on current processor.\r
 \r
index 9ddc6ce9d4764cfc785b8f7297e5ed2cd06e8e96..7cc692efb649ed1a03ff808c952f9a221456a705 100644 (file)
@@ -47,7 +47,7 @@ CpuCommonFeaturesLibConstructor (
   if (IsCpuFeatureSupported (CPU_FEATURE_ACPI)) {\r
     Status = RegisterCpuFeature (\r
                "ACPI",\r
-               NULL,\r
+               ClockModulationGetConfigData,\r
                ClockModulationSupport,\r
                ClockModulationInitialize,\r
                CPU_FEATURE_ACPI,\r