summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/DTS/Smm
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Haswell/DTS/Smm')
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h46
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h62
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c1536
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif15
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs52
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h477
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf106
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak77
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl25
9 files changed, 2396 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h
new file mode 100644
index 0000000..24149b0
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h
@@ -0,0 +1,46 @@
+/** @file
+ This protocol is used to get the status of Digital Thermal Sensor driver initialization
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+#ifndef _DTS_INIT_STATUS_PROTOCOL_H_
+#define _DTS_INIT_STATUS_PROTOCOL_H_
+
+///
+/// Define protocol GUID
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define DTS_INIT_STATUS_PROTOCOL_GUID \
+ { \
+ 0xf687f441, 0x7dcf, 0x4f45, 0x8f, 0x64, 0xca, 0xf2, 0x88, 0xea, 0x50, 0x4e \
+ }
+#else
+#define DTS_INIT_STATUS_PROTOCOL_GUID \
+ { \
+ 0xf687f441, 0x7dcf, 0x4f45, \
+ { \
+ 0x8f, 0x64, 0xca, 0xf2, 0x88, 0xea, 0x50, 0x4e \
+ } \
+ }
+#endif
+
+typedef struct _DTS_INIT_STATUS_PROTOCOL {
+ BOOLEAN IsDtsInitComplete;
+} DTS_INIT_STATUS_PROTOCOL;
+
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h
new file mode 100644
index 0000000..52fe54c
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h
@@ -0,0 +1,62 @@
+/** @file
+ Defines and prototypes for the DigitalThermalSensor SMM driver
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+
+#ifndef _DIGITAL_THERMAL_SENSOR_LIB_H_
+#define _DIGITAL_THERMAL_SENSOR_LIB_H_
+
+/**
+ Prepare data and protocol for Dts Hooe Lib
+
+ @retval EFI_SUCCESS - Initialize complete
+**/
+EFI_STATUS
+InitializeDtsHookLib (
+ VOID
+ );
+
+/**
+ Platform may need to register some data to private data structure before generate
+ software SMI or SCI.
+**/
+VOID
+PlatformHookBeforeGenerateSCI (
+ VOID
+ );
+
+/**
+ Read CPU temperature from platform diode
+
+ @retval TemperatureOfDiode - Return the CPU temperature of platform diode
+**/
+UINT8
+ReadPlatformThermalDiode (
+ VOID
+ );
+
+/**
+ When system temperature out of specification, do platform specific programming to prevent
+ system damage.
+**/
+VOID
+PlatformEventOutOfSpec (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c
new file mode 100644
index 0000000..38dad6c
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c
@@ -0,0 +1,1536 @@
+/** @file
+ Digital Thermal Sensor (DTS) driver.
+ This SMM driver configures and supports the Digital Thermal Sensor features for the platform.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "DigitalThermalSensorSmm.h"
+#include "KscLib.h"
+//
+// Protocol GUID definition
+//
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu = NULL;
+
+EFI_GUID gDtsInitStatusProtocolGuid = DTS_INIT_STATUS_PROTOCOL_GUID;
+EFI_GUID mEfiGlobalNvsAreaProtocolGuid = EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID;
+EFI_GUID mEfiSmmIoTrapDispatchProtocolGuid = EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL_GUID;
+DTS_INIT_STATUS_PROTOCOL mDtsInitStatusProtocol;
+
+//
+// Global variables
+//
+EFI_SMM_BASE_PROTOCOL *mSmmBase;
+EFI_SMM_SYSTEM_TABLE *mSmst;
+
+EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr;
+UINT8 DTSSetupValue;
+
+BOOLEAN mDtsEnabled;
+UINT8 mDtsTjMax;
+UINT16 mAcpiBaseAddr;
+BOOLEAN mUpdateDtsInEverySmi;
+UINT8 mNoOfThresholdRanges;
+UINT8 (*mDtsThresholdTable)[3];
+UINT8 gIsPackageTempMsrAvailable;
+///
+/// The table is updated for the current CPU.
+///
+UINT8 mDigitalThermalSensorThresholdTable[DTS_NUMBER_THRESHOLD_RANGES][3] = {
+ ///
+ /// TJ_MAX = 110 ///< Current Temp. Low Temp. High Temp.
+ ///
+ {TJ_MAX-80,100,75}, ///< <= 30 10 35
+ {TJ_MAX-70,85,65}, ///< 30 ~ 39 25 45
+ {TJ_MAX-60,75,55}, ///< 40 ~ 49 35 55
+ {TJ_MAX-50,65,45}, ///< 50 ~ 59 45 65
+ {TJ_MAX-40,55,35}, ///< 60 ~ 69 55 75
+ {TJ_MAX-30,45,25}, ///< 70 ~ 79 65 85
+ {TJ_MAX-20,35,15}, ///< 80 ~ 89 75 95
+ {TJ_MAX-10,25,05}, ///< 90 ~ 99 85 105
+ {TJ_MAX-00,15,00} ///< 100 ~ 109 95 110
+};
+
+//
+// Function implementations
+//
+/**
+ Read the temperature data per core/thread.
+ This function must be AP safe.
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor temperature has updated successfully.
+**/
+VOID
+EFIAPI
+DigitalThermalSensorUpdateTemperature (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+ UINT8 Temperature;
+ UINT8 DefApicId;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT8 *TempPointer;
+
+ AsmCpuid (
+ EFI_CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ ///
+ /// Default APIC ID = CPUID Function 01, EBX[31:24]
+ ///
+ DefApicId = (UINT8) RShiftU64 (CpuidRegisters.RegEbx, 24);
+
+ ///
+ /// Read the temperature
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+
+ ///
+ /// Find the DTS temperature.
+ ///
+ Temperature = mDtsTjMax - (MsrData.Bytes.ThirdByte & OFFSET_MASK);
+ ///
+ /// We only update the temperature if it is above the current temperature.
+ ///
+ TempPointer = Buffer;
+ if (Temperature > *((UINT8 *) (TempPointer + DefApicId))) {
+ *((UINT8 *) (TempPointer + DefApicId)) = Temperature;
+ }
+
+ return;
+}
+
+/**
+ Read the temperature and update the data for PTID support.
+
+ @retval EFI_SUCCESS Digital Thermal Sensor temperature has updated successfully.
+**/
+EFI_STATUS
+DigitalThermalSensorUpdatePTID (
+ VOID
+ )
+{
+ ///
+ /// ThreadTemperatureBuffer[0], [2], [4] and [6] are Thread0 and [1], [3], [5] and [7] are Thread1 for each Core.
+ /// If thread or core not active, this thread/core temperature will be reported as 0
+ ///
+ UINT8 ThreadTemperatureBuffer[MAX_NUMBER_OF_THREADS_SUPPORTED];
+ UINT8 Index;
+ UINT8 CoreTemp[MAX_NUMBER_OF_THREADS_SUPPORTED / 2];
+
+ ///
+ /// Get DTS temperature for all cores/threads.
+ ///
+ for (Index = 0; Index < MAX_NUMBER_OF_THREADS_SUPPORTED; Index++) {
+ ThreadTemperatureBuffer[Index] = 0;
+ }
+
+ RunOnAllLogicalProcessors (DigitalThermalSensorUpdateTemperature, ThreadTemperatureBuffer);
+ ///
+ /// Compare thread1 and thread2 temperature in each core and only report higher temperature as core temperature.
+ ///
+ for (Index = 0; Index < MAX_NUMBER_OF_THREADS_SUPPORTED; Index += 2) {
+ CoreTemp[(UINT8) DivU64x32 (Index, 2)] =
+ (ThreadTemperatureBuffer[Index] > ThreadTemperatureBuffer[Index + 1])
+ ? ThreadTemperatureBuffer[Index] : ThreadTemperatureBuffer[Index + 1];
+ }
+
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = CoreTemp[0];
+ if ((MAX_NUMBER_OF_THREADS_SUPPORTED / 2) > 1) {
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = CoreTemp[1];
+ }
+
+ if ((MAX_NUMBER_OF_THREADS_SUPPORTED / 2) > 2) {
+ mGlobalNvsAreaPtr->Ap2DigitalThermalSensorTemperature = CoreTemp[2];
+ }
+
+ if ((MAX_NUMBER_OF_THREADS_SUPPORTED / 2) > 3) {
+ mGlobalNvsAreaPtr->Ap3DigitalThermalSensorTemperature = CoreTemp[3];
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ SMI handler to handle Digital Thermal Sensor CPU Local APIC SMI
+ for thermal Out Of Spec interrupt
+
+ @param[in] SmmImageHandle Image handle returned by the SMM driver.
+ @param[in] CommunicationBuffer Pointer to the buffer that contains the communication Message
+ @param[in] SourceSize Size of the memory image to be used for handler.
+
+ @retval EFI_SUCCESS Callback Function Executed
+**/
+EFI_STATUS
+EFIAPI
+DtsOutOfSpecSmiCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+
+ DTS_EVENT_TYPE EventType;
+
+ ///
+ /// If not enabled; return. (The DTS will be disabled upon S3 entry
+ /// and will remain disabled until after re-initialized upon wake.)
+ ///
+ if (!mDtsEnabled) {
+ return EFI_SUCCESS;
+ }
+
+ EventType = DtsEventNone;
+
+ if (gIsPackageTempMsrAvailable) {
+ ///
+ /// Get the Package DTS Event Type
+ ///
+ DigitalThermalSensorEventCheckPackageMsr (&EventType);
+ } else {
+ ///
+ /// Get the DTS Event Type
+ ///
+ DigitalThermalSensorEventCheck (&EventType);
+ }
+ ///
+ /// Check if this a DTS Out Of Spec SMI event
+ ///
+ if (EventType == DtsEventOutOfSpec) {
+ ///
+ /// Return Critical temperature value to _TMP and generate GPE event for critical shutdown.
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = DTS_OUT_OF_SPEC_OCCURRED;
+
+ ///
+ /// Generate SCI to shut down the system
+ ///
+ DigitalThermalSensorSetSwGpeSts ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Call from SMI handler to handle Package thermal temperature Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @retval None
+**/
+VOID
+PackageThermalDTS (
+ VOID
+ )
+{
+ DTS_EVENT_TYPE PkgEventType;
+
+ PkgEventType = DtsEventNone;
+
+ ///
+ /// Check is this a Platform SMI event or the flag of update DTS temperature and threshold value in every SMI
+ ///
+ if (DigitalThermalSensorEventCheckPackageMsr (&PkgEventType) || mUpdateDtsInEverySmi) {
+ ///
+ /// Disable Local APIC SMI before programming the threshold
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorDisableSmi, NULL);
+
+ do {
+ ///
+ /// Handle Package events
+ ///
+ if ((PkgEventType == DtsEventOutOfSpec) && (mGlobalNvsAreaPtr->OperatingSystem == 0)) {
+ ///
+ /// Handle critical event by shutting down via EC if ACPI
+ /// is not enabled.
+ ///
+ PlatformEventOutOfSpec ();
+ }
+ ///
+ /// Set the thermal trip toints as needed.
+ ///
+ mGlobalNvsAreaPtr->PackageDTSTemperature = 0;
+
+ ///
+ /// Set the Package thermal sensor thresholds
+ ///
+ PackageDigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->PackageDTSTemperature);
+
+ ///
+ /// Set SWGPE Status to generate an SCI if we had any events
+ ///
+ if ((PkgEventType != DtsEventNone) || mUpdateDtsInEverySmi) {
+ DigitalThermalSensorSetSwGpeSts ();
+ }
+
+ } while (DigitalThermalSensorEventCheckPackageMsr (&PkgEventType));
+ ///
+ /// Enable Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ }
+}
+
+/**
+ SMI handler to handle Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @param[in] SmmImageHandle Image handle returned by the SMM driver.
+ @param[in] CommunicationBuffer Pointer to the buffer that contains the communication Message
+ @param[in] SourceSize Size of the memory image to be used for handler.
+
+ @retval EFI_SUCCESS Callback Function Executed
+**/
+EFI_STATUS
+EFIAPI
+DtsSmiCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ UINTN Index;
+ DTS_EVENT_TYPE EventType;
+ ///
+ /// If not enabled; return. (The DTS will be disabled upon S3 entry
+ /// and will remain disabled until after re-initialized upon wake.)
+ ///
+ if (!mDtsEnabled) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Get the Package thermal temperature
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ PackageThermalDTS ();
+ } else {
+ ///
+ /// We enable the Thermal interrupt on the AP's prior to the event check
+ /// for the case where the AP has gone through the INIT-SIPI-SIPI sequence
+ /// and does not have the interrupt enabled. (This allows the AP thermal
+ /// interrupt to be re-enabled due to chipset-based SMIs without waiting
+ /// to receive a DTS event on the BSP.)
+ ///
+ for (Index = 1; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (DigitalThermalSensorEnableSmi, Index, NULL);
+ }
+ ///
+ /// Check is this a DTS SMI event or the flag of update DTS temperature and threshold value in every SMI
+ ///
+ if (DigitalThermalSensorEventCheck (&EventType) || mUpdateDtsInEverySmi) {
+ ///
+ /// Disable Local APIC SMI before programming the threshold
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorDisableSmi, NULL);
+
+ do {
+ ///
+ /// Handle BSP events
+ ///
+ if ((EventType == DtsEventOutOfSpec) && (mGlobalNvsAreaPtr->OperatingSystem == 0)) {
+ ///
+ /// Handle critical event by shutting down via EC if ACPI
+ /// is not enabled.
+ ///
+ PlatformEventOutOfSpec ();
+ }
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+
+ ///
+ /// Set the thermal trip toints as needed.
+ /// Note: We only save the highest temperature of each die in
+ /// the NVS area when more than two logical processors are
+ /// present as only the highest DTS reading is actually used by
+ /// the current ASL solution.
+ ///
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+
+ ///
+ /// Set the BSP thermal sensor thresholds
+ ///
+ DigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature);
+
+ ///
+ /// Set the AP thermal sensor thresholds and update temperatures
+ ///
+ for (Index = 1; Index < mSmst->NumberOfCpus / 2; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature
+ );
+ }
+
+ for (Index = mSmst->NumberOfCpus / 2; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature
+ );
+ }
+ ///
+ /// Set SWGPE Status to generate an SCI if we had any events
+ ///
+ if ((EventType != DtsEventNone) || mUpdateDtsInEverySmi) {
+ DigitalThermalSensorSetSwGpeSts ();
+ }
+
+ } while (DigitalThermalSensorEventCheck (&EventType));
+ ///
+ /// Enable Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This catches IO trap SMI generated by the ASL code to enable the DTS AP function
+
+ @param[in] DispatchHandle Not used
+ @param[in] CallbackContext Not used
+**/
+VOID
+EFIAPI
+DtsIoTrapCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT *CallbackContext
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT8 RetryIteration;
+
+ ///
+ /// Determine the function desired, passed in the global NVS area
+ ///
+ switch (mGlobalNvsAreaPtr->DigitalThermalSensorSmiFunction) {
+ ///
+ /// Enable AP Digital Thermal Sensor function after resume from S3
+ ///
+ case IO_TRAP_INIT_DTS_FUNCTION_AFTER_S3:
+ ///
+ /// Enable the Package DTS on the processors.
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorEnable (NULL);
+ } else {
+ ///
+ /// Enable the DTS on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnable, NULL);
+ }
+
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ ///
+ /// Set the thermal trip toints on all logical processors.
+ /// Note: We only save the highest temperature of each die in the NVS area when
+ /// more than two logical processors are present as only the highest DTS reading
+ /// is actually used by the current ASL solution.
+ ///
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->PackageDTSTemperature = 0;
+
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->PackageDTSTemperature);
+ } else {
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ DigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature);
+
+ for (Index = 1; Index < mSmst->NumberOfCpus / 2; Index++) {
+ Status = EFI_NOT_READY;
+ for (RetryIteration = 0;
+ (RetryIteration < DTS_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS);
+ RetryIteration++
+ ) {
+ Status = mSmst->SmmStartupThisAp (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature
+ );
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ }
+ }
+ }
+
+ for (Index = mSmst->NumberOfCpus / 2; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature
+ );
+ }
+ }
+ ///
+ /// Re-enable the DTS.
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = CPU_FEATURE_ENABLE;
+ } else {
+ ///
+ /// Enable Out Of Spec Interrupt
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetOutOfSpecInterrupt (NULL);
+ } else {
+ RunOnAllLogicalProcessors (DigitalThermalSensorSetOutOfSpecInterrupt, NULL);
+ }
+ ///
+ /// Re-enable the DTS which only handle Out-Of-Spec condition
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = DTS_OUT_OF_SPEC_ONLY;
+ }
+ ///
+ /// Enable the Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ ///
+ /// Set SWGPE Status
+ ///
+ DigitalThermalSensorSetSwGpeSts ();
+
+ mUpdateDtsInEverySmi = UPDATE_DTS_EVERY_SMI;
+ mDtsEnabled = TRUE;
+ break;
+
+ ///
+ /// Disable update DTS temperature and threshold value in every SMI
+ ///
+ case IO_TRAP_DISABLE_UPDATE_DTS:
+ mUpdateDtsInEverySmi = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ ///
+ /// Store return value
+ ///
+ mGlobalNvsAreaPtr->DigitalThermalSensorSmiFunction = 0;
+}
+
+/**
+ This function executes DTS procedures for preparing to enter S3.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS DTS disabled
+**/
+VOID
+EFIAPI
+DtsS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *Context
+ )
+{
+ ///
+ /// Clear the Digital Thermal Sensor flag in ACPI NVS.
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = CPU_FEATURE_DISABLE;
+ ///
+ /// Clear the enable flag.
+ ///
+ mDtsEnabled = FALSE;
+
+ return;
+}
+
+/**
+ Performs initialization of the threshold table.
+
+ @todo Update this function as necessary for the tables used by the implementation.
+
+ @retval EFI_SUCCESS Threshold tables initialized successfully.
+**/
+EFI_STATUS
+ThresholdTableInit (
+ VOID
+ )
+{
+ UINTN i;
+ UINT8 Delta;
+
+ ///
+ /// If the table must be updated, shift the thresholds by the difference between
+ /// TJ_MAX=110 and DtsTjMax.
+ ///
+ if (mDtsTjMax != TJ_MAX) {
+ Delta = TJ_MAX - mDtsTjMax;
+
+ for (i = 0; i < mNoOfThresholdRanges; i++) {
+ if (mDtsThresholdTable[i][1] <= mDtsTjMax) {
+ mDtsThresholdTable[i][0] = mDtsThresholdTable[i][0] - Delta;
+ } else {
+ mDtsThresholdTable[i][0] = 0;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform first time initialization of the Digital Thermal Sensor
+
+ @retval EFI_SUCCESS Init Digital Thermal Sensor successfully
+**/
+EFI_STATUS
+DigitalThermalSensorInit (
+ VOID
+ )
+{
+ UINTN Index;
+
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ ///
+ /// Initialize the DTS threshold table.
+ ///
+ ThresholdTableInit ();
+
+ ///
+ /// Set the thermal trip points on all logical processors.
+ /// Note: We only save the highest temperature of each die in the NVS area when
+ /// more than two logical processors are present as only the highest DTS reading
+ /// is actually used by the current ASL solution.
+ ///
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->PackageDTSTemperature = 0;
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->PackageDTSTemperature);
+ } else {
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ DigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature);
+
+ for (Index = 1; Index < mSmst->NumberOfCpus / 2; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature
+ );
+ }
+
+ for (Index = mSmst->NumberOfCpus / 2; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature
+ );
+ }
+ }
+
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = CPU_FEATURE_ENABLE;
+ } else {
+ ///
+ /// Enable Out Of Spec Interrupt
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetOutOfSpecInterrupt (NULL);
+ } else {
+ RunOnAllLogicalProcessors (DigitalThermalSensorSetOutOfSpecInterrupt, NULL);
+ }
+
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = DTS_OUT_OF_SPEC_ONLY;
+ }
+ ///
+ /// Enable the Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ ///
+ /// Set Digital Thermal Sensor flag in ACPI NVS
+ ///
+ mUpdateDtsInEverySmi = UPDATE_DTS_EVERY_SMI;
+ mDtsEnabled = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the Thermal Sensor Control MSR
+
+ This function must be AP safe.
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnable (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// First, clear our log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ MsrData.Qword &= ~THERM_STATUS_LOG_MASK;
+ } else {
+ MsrData.Qword &= ~B_OUT_OF_SPEC_STATUS_LOG;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_STATUS, MsrData.Qword);
+
+ ///
+ /// Second, configure the thermal sensor control
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_MISC_PWR_MGMT);
+
+ ///
+ /// Only lock interrupts if in CMP mode
+ ///
+ if (mSmst->NumberOfCpus > 1) {
+ MsrData.Qword |= B_LOCK_THERMAL_INT;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_MISC_PWR_MGMT, MsrData.Qword);
+
+ return;
+}
+
+/**
+ Initializes the Package Thermal Sensor Control MSR
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+PackageDigitalThermalSensorEnable (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// First, clear our log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ MsrData.Qword &= ~THERM_STATUS_LOG_MASK;
+ } else {
+ MsrData.Qword &= ~B_OUT_OF_SPEC_STATUS_LOG;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS, MsrData.Qword);
+
+ ///
+ /// Second, configure the thermal sensor control
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_MISC_PWR_MGMT);
+
+ ///
+ /// Only lock interrupts if in CMP mode
+ ///
+ if (mSmst->NumberOfCpus > 1) {
+ MsrData.Qword |= B_LOCK_THERMAL_INT;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_MISC_PWR_MGMT, MsrData.Qword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates a _GPE._L02 SCI to an ACPI OS.
+**/
+VOID
+DigitalThermalSensorSetSwGpeSts (
+ VOID
+ )
+{
+ UINT8 GpeCntl;
+
+ ///
+ /// Check SCI enable
+ ///
+ if (((SmmIoRead8 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT)) & B_PCH_ACPI_PM1_CNT_SCI_EN) != 0) {
+ ///
+ /// Do platform specific things before generate SCI
+ ///
+ PlatformHookBeforeGenerateSCI ();
+
+ ///
+ /// Set SWGPE Status
+ ///
+ GpeCntl = SmmIoRead8 (mAcpiBaseAddr + R_ACPI_GPE_CNTL);
+ GpeCntl |= B_SWGPE_CTRL;
+ SmmIoWrite8 (mAcpiBaseAddr + R_ACPI_GPE_CNTL, GpeCntl);
+ }
+}
+
+/**
+ Checks for a Core Thermal Event on any processor
+
+ @param[in] EventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a DTS Thermal event
+ @retval FALSE means this is not a DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheck (
+ DTS_EVENT_TYPE *EventType
+ )
+{
+ ///
+ /// Clear event status
+ ///
+ *EventType = DtsEventNone;
+
+ RunOnAllLogicalProcessors (DigitalThermalSensorEventCheckMsr, EventType);
+ ///
+ /// Return TRUE if any logical processor reported an event.
+ ///
+ if (*EventType != DtsEventNone) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Checks for a Package Thermal Event by reading MSR.
+
+ @param[in] PkgEventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a Package DTS Thermal event
+ @retval FALSE means this is not a Package DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheckPackageMsr (
+ DTS_EVENT_TYPE *PkgEventType
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// Clear event status
+ ///
+ *PkgEventType = DtsEventNone;
+
+ ///
+ /// If Processor has already been flagged as Out-Of-Spec,
+ /// just return.
+ ///
+ if (*PkgEventType != DtsEventOutOfSpec) {
+ ///
+ /// Read thermal status
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+
+ ///
+ /// Check for Out-Of-Spec status.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS_LOG) {
+ *PkgEventType = DtsEventOutOfSpec;
+
+ ///
+ /// Check thresholds.
+ ///
+ } else if ((DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) &&
+ (MsrData.Qword & (B_THERMAL_THRESHOLD_1_STATUS_LOG | B_THERMAL_THRESHOLD_2_STATUS_LOG))
+ ) {
+ *PkgEventType = DtsEventThreshold;
+ }
+ }
+ ///
+ /// Return TRUE if processor reported an event.
+ ///
+ if (*PkgEventType != DtsEventNone) {
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+/**
+ Checks for a Core Thermal Event by reading MSR.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to DTS_EVENT_TYPE
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEventCheckMsr (
+ IN VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+ DTS_EVENT_TYPE *EventType;
+
+ ///
+ /// Cast to enhance readability.
+ ///
+ EventType = (DTS_EVENT_TYPE *) Buffer;
+
+ ///
+ /// If any processor has already been flagged as Out-Of-Spec,
+ /// just return.
+ ///
+ if (*EventType != DtsEventOutOfSpec) {
+ ///
+ /// Read thermal status
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+
+ ///
+ /// Check for Out-Of-Spec status.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS_LOG) {
+ *EventType = DtsEventOutOfSpec;
+
+ ///
+ /// Check thresholds.
+ ///
+ } else if ((DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) &&
+ (MsrData.Qword & (B_THERMAL_THRESHOLD_1_STATUS_LOG | B_THERMAL_THRESHOLD_2_STATUS_LOG))
+ ) {
+ *EventType = DtsEventThreshold;
+ }
+ }
+}
+
+/**
+ Set the Out Of Spec Interrupt in all cores
+ This function must be AP safe.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// Enable Out Of Spec interrupt
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_INTERRUPT);
+ MsrData.Qword |= OVERHEAT_INTERRUPT_ENABLE;
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_INTERRUPT, MsrData.Qword);
+
+ return;
+
+}
+
+/**
+ Set the Out Of Spec Interrupt on the package
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// Enable Out Of Spec interrupt
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT);
+ MsrData.Qword |= OVERHEAT_INTERRUPT_ENABLE;
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT, MsrData.Qword);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Read the temperature and reconfigure the thresholds.
+ This function must be AP safe.
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ )
+{
+ INT8 ThresholdEntry;
+ MSR_REGISTER MsrData;
+ UINT8 Temperature;
+
+ ///
+ /// Read the temperature
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+
+ ///
+ /// If Out-Of-Spec, return the critical shutdown temperature.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS) {
+ *((UINT8 *) Buffer) = DTS_CRITICAL_TEMPERATURE;
+ return;
+ } else if (MsrData.Qword & B_READING_VALID) {
+ ///
+ /// Find the DTS temperature.
+ ///
+ Temperature = mDtsTjMax - (MsrData.Bytes.ThirdByte & OFFSET_MASK);
+ ///
+ /// We only update the temperature if it is above the current temperature.
+ ///
+ if (Temperature > *((UINT8 *) Buffer)) {
+ *((UINT8 *) Buffer) = Temperature;
+ }
+ ///
+ /// Compare the current temperature to the Digital Thermal Sensor Threshold Table until
+ /// a matching Value is found.
+ ///
+ ThresholdEntry = 0;
+ while ((Temperature > mDtsThresholdTable[ThresholdEntry][0]) && (ThresholdEntry < (mNoOfThresholdRanges - 1))) {
+ ThresholdEntry++;
+ }
+ ///
+ /// Update the threshold values
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_INTERRUPT);
+ ///
+ /// Low temp is threshold #2
+ ///
+ MsrData.Bytes.ThirdByte = mDtsThresholdTable[ThresholdEntry][1];
+ ///
+ /// High temp is threshold #1
+ ///
+ MsrData.Bytes.SecondByte = mDtsThresholdTable[ThresholdEntry][2];
+
+ ///
+ /// Enable interrupts
+ ///
+ MsrData.Qword |= TH1_ENABLE;
+ MsrData.Qword |= TH2_ENABLE;
+
+ ///
+ /// If the high temp is at TjMax (offset == 0)
+ /// We disable the int to avoid generating a large number of SMI because of TM1/TM2
+ /// causing many threshold crossings
+ ///
+ if (MsrData.Bytes.SecondByte == 0x80) {
+ MsrData.Qword &= ~TH1_ENABLE;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_INTERRUPT, MsrData.Qword);
+ }
+ ///
+ /// Clear the threshold log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+ MsrData.Qword &= ~THERM_STATUS_THRESHOLD_LOG_MASK;
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_STATUS, MsrData.Qword);
+
+ return;
+}
+
+/**
+ Read the temperature and reconfigure the thresholds on the package
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ )
+{
+ INT8 ThresholdEntry;
+ MSR_REGISTER MsrData;
+ UINT8 Temperature;
+
+ ///
+ /// Read the temperature
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+
+ ///
+ /// If Out-Of-Spec, return the critical shutdown temperature.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS) {
+ *((UINT8 *) Buffer) = DTS_CRITICAL_TEMPERATURE;
+ return EFI_SUCCESS;
+ } else if (MsrData.Qword & B_READING_VALID) {
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+
+ ///
+ /// Find the DTS temperature.
+ ///
+ Temperature = mDtsTjMax - (MsrData.Bytes.ThirdByte & OFFSET_MASK);
+ ///
+ /// We only update the temperature if it is above the current temperature.
+ ///
+ if (Temperature > *((UINT8 *) Buffer)) {
+ *((UINT8 *) Buffer) = Temperature;
+ }
+ ///
+ /// Compare the current temperature to the Digital Thermal Sensor Threshold Table until
+ /// a matching Value is found.
+ ///
+ ThresholdEntry = 0;
+ while ((Temperature > mDtsThresholdTable[ThresholdEntry][0]) && (ThresholdEntry < (mNoOfThresholdRanges - 1))) {
+ ThresholdEntry++;
+ }
+ ///
+ /// Update the threshold values
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT);
+ ///
+ /// Low temp is threshold #2
+ ///
+ MsrData.Bytes.ThirdByte = mDtsThresholdTable[ThresholdEntry][1];
+ ///
+ /// High temp is threshold #1
+ ///
+ MsrData.Bytes.SecondByte = mDtsThresholdTable[ThresholdEntry][2];
+
+ ///
+ /// Enable interrupts
+ ///
+ MsrData.Qword |= TH1_ENABLE;
+ MsrData.Qword |= TH2_ENABLE;
+
+ ///
+ /// If the high temp is at TjMax (offset == 0)
+ /// We disable the int to avoid generating a large number of SMI because of TM1/TM2
+ /// causing many threshold crossings
+ ///
+ if (MsrData.Bytes.SecondByte == 0x80) {
+ MsrData.Qword &= ~TH1_ENABLE;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT, MsrData.Qword);
+ }
+ ///
+ /// Clear the threshold log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+ MsrData.Qword &= ~THERM_STATUS_THRESHOLD_LOG_MASK;
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS, MsrData.Qword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Enable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnableSmi (
+ VOID *Buffer
+ )
+{
+ UINT32 ApicThermalValue;
+ BOOLEAN x2ApicEnabled;
+
+ x2ApicEnabled = (BOOLEAN) (((AsmReadMsr64 (EFI_MSR_XAPIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10);
+ ///
+ /// Configure the Local APIC to generate an SMI on Thermal events. First,
+ /// Clear BIT16, BIT10-BIT8, BIT7-BIT0. Then, set BIT9 (delivery mode).
+ /// Don't enable the interrupt if it's already enabled
+ ///
+ if (x2ApicEnabled) {
+ ApicThermalValue = (UINT32) AsmReadMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM);
+ } else {
+ ApicThermalValue = *(UINT32 *) (UINTN) LOCAL_APIC_THERMAL_DEF;
+ }
+
+ if ((ApicThermalValue & (B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) != V_MODE_SMI) {
+ ApicThermalValue = (ApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | V_MODE_SMI;
+ if (x2ApicEnabled) {
+ AsmWriteMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM, ApicThermalValue);
+ } else {
+ *(UINT32 *) (UINTN) (LOCAL_APIC_THERMAL_DEF) = (UINT32) ApicThermalValue;
+ }
+ }
+
+ return;
+}
+
+/**
+ Disables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Disable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorDisableSmi (
+ VOID *Buffer
+ )
+{
+ UINT32 ApicThermalValue;
+ BOOLEAN x2ApicEnabled;
+
+ x2ApicEnabled = (BOOLEAN) (((AsmReadMsr64 (EFI_MSR_XAPIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10);
+ ///
+ /// Disable Local APIC thermal entry
+ ///
+ if (x2ApicEnabled) {
+ ApicThermalValue = (UINT32) AsmReadMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM);
+ } else {
+ ApicThermalValue = *(UINT32 *) (UINTN) LOCAL_APIC_THERMAL_DEF;
+ }
+ ///
+ /// Following descriptions were from SSE BIOS
+ /// We set the interrupt mode at the same time as the interrupt is disabled to
+ /// avoid the "Received Illegal Vector" being set in the Error Status Register.
+ /// and eax, 0FFFEF800h
+ /// or eax, 000010200h ; Clear Mask, Set Delivery
+ ///
+ ApicThermalValue = (ApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | (B_INTERRUPT_MASK | V_MODE_SMI);
+ if (x2ApicEnabled) {
+ AsmWriteMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM, ApicThermalValue);
+ } else {
+ *(UINT32 *) (UINTN) (LOCAL_APIC_THERMAL_DEF) = (UINT32) ApicThermalValue;
+ }
+
+ return;
+}
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT8 RetryIteration;
+ ///
+ /// Run the procedure on all logical processors.
+ ///
+ for (Index = 1; Index < mSmst->NumberOfCpus; Index++) {
+ Status = EFI_NOT_READY;
+ for (RetryIteration = 0; (RetryIteration < DTS_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS); RetryIteration++) {
+ Status = mSmst->SmmStartupThisAp (Procedure, Index, Buffer);
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ }
+ }
+ }
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ (*Procedure)(Buffer);
+ return EFI_SUCCESS;
+}
+
+/**
+ Runs the specified procedure on one specific logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Index Indicate which logical processor should execute this procedure
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnSpecificLogicalProcessor (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN UINTN Index,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 RetryIteration;
+ ///
+ /// Run the procedure on one specific logical processor.
+ ///
+ Status = EFI_NOT_READY;
+ for (RetryIteration = 0; (RetryIteration < DTS_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS); RetryIteration++) {
+ Status = mSmst->SmmStartupThisAp (Procedure, Index, Buffer);
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Digital Thermal Sensor (DTS) SMM driver entry point function.
+
+ @param[in] ImageHandle Image handle for this driver image
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+ @retval EFI_OUT_OF_RESOURCES Error when allocating required memory buffer.
+**/
+EFI_STATUS
+InstallDigitalThermalSensor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ MSR_REGISTER MsrData;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol;
+ EFI_SMM_SX_DISPATCH_CONTEXT SxDispatchContext;
+ EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatchProtocol;
+ EFI_HANDLE SxDispatchHandle;
+
+ EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL *PchIoTrap;
+ EFI_HANDLE PchIoTrapHandle;
+ EFI_SMM_IO_TRAP_DISPATCH_REGISTER_CONTEXT PchIoTrapContext;
+ EFI_CPUID_REGISTER Cpuid06;
+
+ ///
+ /// Install DTS_INIT_STATUS_PROTOCOL protocol
+ ///
+ Handle = NULL;
+ mDtsInitStatusProtocol.IsDtsInitComplete = FALSE;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gDtsInitStatusProtocolGuid,
+ &mDtsInitStatusProtocol,
+ NULL
+ );
+
+ ///
+ /// Locate DTS platform policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxeCpuPlatformPolicyProtocolGuid,
+ NULL,
+ (VOID **) &mPlatformCpu
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "No DTS Platform Policy Protocol available"));
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Check if DTS disabled in setup.
+ ///
+ if (mPlatformCpu->CpuConfig->EnableDts == CPU_FEATURE_DISABLE) {
+ DEBUG ((EFI_D_WARN, "DTS not enabled/supported, so driver not loaded into SMM\n"));
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Find the SMM base protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize global variables.
+ ///
+ Status = mSmmBase->GetSmstLocation (mSmmBase, &mSmst);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Verify the code supports the number of processors present.
+ ///
+ ASSERT (mSmst->NumberOfCpus <= MAX_NUMBER_OF_THREADS_SUPPORTED);
+
+ ///
+ /// Get the ACPI Base Address
+ ///
+ mAcpiBaseAddr = MmioRead16 (MmPciExpressAddress (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_ACPI_BASE)) &~BIT0;
+
+ ///
+ /// Initialize DTS setup value
+ ///
+ DTSSetupValue = mPlatformCpu->CpuConfig->EnableDts;
+
+ ///
+ /// Locate our shared data area
+ ///
+ Status = gBS->LocateProtocol (&mEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **) &GlobalNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mGlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area;
+ ///
+ /// CPU_ID 6, EAX bit 6 for the Package temperature MSR support
+ ///
+ ZeroMem (&Cpuid06, sizeof (Cpuid06));
+ AsmCpuid (6, &Cpuid06.RegEax, &Cpuid06.RegEbx, &Cpuid06.RegEcx, &Cpuid06.RegEdx);
+
+ gIsPackageTempMsrAvailable = (BOOLEAN) ((Cpuid06.RegEax >> 6) & 0x01);
+ mGlobalNvsAreaPtr->IsPackageTempMSRAvailable = gIsPackageTempMsrAvailable;
+ ///
+ /// Locate Platform specific data area, or prepare platform services
+ ///
+ InitializeDtsHookLib ();
+
+ ///
+ /// Initialize ASL manipulation library
+ ///
+ InitializeAslUpdateLib ();
+
+ ///
+ /// Locate the PCH Trap dispatch protocol
+ ///
+ Status = gBS->LocateProtocol (&mEfiSmmIoTrapDispatchProtocolGuid, NULL, (VOID **) &PchIoTrap);
+ ASSERT_EFI_ERROR (Status);
+
+ PchIoTrapContext.Type = ReadWriteTrap;
+ PchIoTrapContext.Length = 4;
+ PchIoTrapContext.Address = 0;
+ PchIoTrapContext.Context = NULL;
+ PchIoTrapContext.MergeDisable = FALSE;
+ Status = PchIoTrap->Register (
+ PchIoTrap,
+ DtsIoTrapCallback,
+ &PchIoTrapContext,
+ &PchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update two ASL items.
+ /// 1: Operating Region for DTS IO Trap.
+ /// 2: Resource Consumption in LPC Device.
+ ///
+ ASSERT (PchIoTrapContext.Length <= (UINT8) (-1));
+ Status = UpdateAslCode (
+ (EFI_SIGNATURE_32 ('I', 'O', '_', 'D')),
+ PchIoTrapContext.Address,
+ (UINT8) PchIoTrapContext.Length
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register a callback function to handle Digital Thermal Sensor SMIs.
+ ///
+ if (mPlatformCpu->CpuConfig->EnableDts != DTS_OUT_OF_SPEC_ONLY) {
+ Status = mSmmBase->RegisterCallback (mSmmBase, ImageHandle, DtsSmiCallback, FALSE, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = mSmmBase->RegisterCallback (mSmmBase, ImageHandle, DtsOutOfSpecSmiCallback, FALSE, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ }
+ ///
+ /// Locate the Sx Dispatch Protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiSmmSxDispatchProtocolGuid,
+ NULL,
+ (VOID **) &SxDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register the callback for S3 entry
+ ///
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = SxDispatchProtocol->Register (
+ SxDispatchProtocol,
+ DtsS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (mPlatformCpu->CpuConfig->EnableDts != DTS_OUT_OF_SPEC_ONLY) {
+ ///
+ /// Get the TCC Activation Temperature and use it for TjMax.
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_TEMPERATURE_TARGET);
+
+ mDtsTjMax = (MsrData.Bytes.ThirdByte);
+ mDtsThresholdTable = mDigitalThermalSensorThresholdTable;
+ mNoOfThresholdRanges = DTS_NUMBER_THRESHOLD_RANGES;
+ }
+
+ if (gIsPackageTempMsrAvailable) {
+ ///
+ /// Enable the DTS on package.
+ ///
+ PackageDigitalThermalSensorEnable (NULL);
+ } else {
+ ///
+ /// Enable the DTS on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnable, NULL);
+ }
+ ///
+ /// Initialize Digital Thermal Sensor Function in POST
+ ///
+ DigitalThermalSensorInit ();
+
+ mDtsInitStatusProtocol.IsDtsInitComplete = TRUE;
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif
new file mode 100644
index 0000000..c0b71a1
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "DigitalThermalSensorSmm"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\DTS\Smm"
+ RefName = "DigitalThermalSensorSmm"
+[files]
+"DigitalThermalSensorSmm.mak"
+"DigitalThermalSensorSmm.sdl"
+"DigitalThermalSensorSmm.inf"
+"DigitalThermalSensorSmm.c"
+"DigitalThermalSensorSmm.dxs"
+"DigitalThermalSensorSmm.h"
+"DigitalThermalSensorInitStatus.h"
+"DigitalThermalSensorLib.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs
new file mode 100644
index 0000000..cc37eff
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs
@@ -0,0 +1,52 @@
+/** @file
+
+ Dispatch dependency expression file for the DigitalThermalSensorSmm driver.
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+
+
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport)
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+#include EFI_PROTOCOL_DEPENDENCY (GlobalNvsArea)
+#include EFI_PROTOCOL_DEFINITION (SmmIoTrapDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmSxDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (CpuPlatformPolicy)
+
+DEPENDENCY_START
+ EFI_ACPI_SUPPORT_GUID AND
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL_GUID AND
+ EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID AND
+ EFI_SMM_SX_DISPATCH_PROTOCOL_GUID AND
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID
+DEPENDENCY_END
+
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h
new file mode 100644
index 0000000..f89e982
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h
@@ -0,0 +1,477 @@
+/** @file
+ Defines and prototypes for the Digital Thermal Sensor SMM driver
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#ifndef _DIGITAL_THERMAL_SENSOR_SMM_H_
+#define _DIGITAL_THERMAL_SENSOR_SMM_H_
+
+//
+// Include files
+//
+#include "EdkIIGlueDxe.h"
+#include "CpuFuncs.h"
+#include "Cpu.h"
+
+//
+// Include dependent protocols
+//
+#include EFI_PROTOCOL_DEPENDENCY (LoadedImage)
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+#include EFI_PROTOCOL_DEPENDENCY (GlobalNvsArea)
+#include EFI_PROTOCOL_DEPENDENCY (SmmIchnDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmIoTrapDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmSxDispatch)
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+
+#include "SmmIoLib.h"
+#include "AslUpdateLib.h"
+#include "DigitalThermalSensorlib.h"
+
+#include "DigitalThermalSensorInitStatus.h"
+#include "CpuRegs.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+
+///
+/// Stall period in microseconds
+///
+#define DTS_WAIT_PERIOD 1
+#define DTS_AP_SAFE_RETRY_LIMIT 3
+///
+/// Define module definitions
+///
+#define TJ_MAX 110
+#define DTS_CRITICAL_TEMPERATURE 255
+
+#define DTS_SAMPLE_RATE 0x10
+#define EFI_MSR_XAPIC_BASE 0x1B
+#define EFI_MSR_IA32_THERM_INTERRUPT 0x19B
+#define TH1_VALUE 8
+#define TH1_ENABLE (1 << 15)
+#define TH2_VALUE 16
+#define TH2_ENABLE (1 << 23)
+#define OFFSET_MASK (0x7F)
+#define OVERHEAT_INTERRUPT_ENABLE (1 << 4)
+
+#define B_OUT_OF_SPEC_STATUS (1 << 4)
+#define B_OUT_OF_SPEC_STATUS_LOG (1 << 5)
+#define B_THERMAL_THRESHOLD_1_STATUS (1 << 6)
+#define B_THERMAL_THRESHOLD_1_STATUS_LOG (1 << 7)
+#define B_THERMAL_THRESHOLD_2_STATUS (1 << 8)
+#define B_THERMAL_THRESHOLD_2_STATUS_LOG (1 << 9)
+#define B_READING_VALID (1 << 31)
+
+#define EFI_MSR_IA32_TEMPERATURE_TARGET 0x1A2
+#define EFI_MSR_EXT_XAPIC_LVT_THERM 0x833
+#define EFI_MSR_MISC_PWR_MGMT 0x1AA
+#define B_LOCK_THERMAL_INT (1 << 22)
+
+#define THERM_STATUS_LOG_MASK (B_THERMAL_THRESHOLD_2_STATUS_LOG | B_THERMAL_THRESHOLD_1_STATUS_LOG | B_OUT_OF_SPEC_STATUS_LOG)
+#define THERM_STATUS_THRESHOLD_LOG_MASK (B_THERMAL_THRESHOLD_2_STATUS_LOG | B_THERMAL_THRESHOLD_1_STATUS_LOG)
+
+#define EFI_MSR_IA32_PACKAGE_THERM_STATUS 0x1B1
+#define EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT 0x1B2
+
+#define B_DTS_IO_TRAP (1 << 2)
+#define R_ACPI_GPE_CNTL 0x42 ///< ACPI PM IO register 42h
+#define R_ACPI_SMI_EN 0x30 ///< ACPI PM IO register 30h
+#define B_SWGPE_CTRL (1 << 1)
+#define DTS_IO_TRAP_REGISTER_LOW_DWORD (0x00040001 + ICH_DTS_IO_TRAP_BASE_ADDRESS) ///< DigitalThermalSensor IO Trap High DWord value
+#define DTS_IO_TRAP_REGISTER_HIGH_DWORD 0x000200F0 ///< DigitalThermalSensor IO Trap High DWord value
+#define LOCAL_APIC_THERMAL_DEF 0xFEE00330
+#define B_INTERRUPT_MASK (1 << 16)
+#define B_DELIVERY_MODE (0x07 << 8)
+#define V_MODE_SMI (0x02 << 8)
+#define B_VECTOR (0xFF << 0)
+
+#define DTS_NUMBER_THRESHOLD_RANGES 9 ///< How many ranges are in the threshold table
+#define IO_TRAP_INIT_AP_DTS_FUNCTION 0x0A ///< Enable AP DigitalThermalSensor function
+#define IO_TRAP_INIT_DTS_FUNCTION_AFTER_S3 0x14 ///< Enable Digital Thermal Sensor function after resume from S3
+#define IO_TRAP_DISABLE_UPDATE_DTS 0x1E ///< Disable update DTS temperature and threshold value in every SMI
+#define INIT_DTS_SCF_MIN 0x10 ///< SCF Minimum value.
+#define INIT_DTS_SCF_UNITY 0x20 ///< SCF Unity Value.
+#define INIT_DTS_SCF_MAX 0x30 ///< SCF Maximum value.
+#define UPDATE_DTS_EVERY_SMI TRUE ///< Update DTS temperature and threshold value in every SMI
+#define R_PCH_ACPI_PM1_CNT 0x04
+#define B_PCH_ACPI_PM1_CNT_SCI_EN 0x00000001
+#define R_PCH_LPC_ACPI_BASE 0x40
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define MAX_NUMBER_OF_THREADS_SUPPORTED 8 ///< Max number of threads supported by processor.
+#ifndef BIT63
+#define BIT0 0x0001
+#define BIT1 0x0002
+#define BIT2 0x0004
+#define BIT3 0x0008
+#define BIT4 0x0010
+#define BIT5 0x0020
+#define BIT6 0x0040
+#define BIT7 0x0080
+#define BIT8 0x0100
+#define BIT9 0x0200
+#define BIT10 0x0400
+#define BIT11 0x0800
+#define BIT12 0x1000
+#define BIT13 0x2000
+#define BIT14 0x4000
+#define BIT15 0x8000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+#define BIT32 0x100000000
+#define BIT33 0x200000000
+#define BIT34 0x400000000
+#define BIT35 0x800000000
+#define BIT36 0x1000000000
+#define BIT37 0x2000000000
+#define BIT38 0x4000000000
+#define BIT39 0x8000000000
+#define BIT40 0x10000000000
+#define BIT41 0x20000000000
+#define BIT42 0x40000000000
+#define BIT43 0x80000000000
+#define BIT44 0x100000000000
+#define BIT45 0x200000000000
+#define BIT46 0x400000000000
+#define BIT47 0x800000000000
+#define BIT48 0x1000000000000
+#define BIT49 0x2000000000000
+#define BIT50 0x4000000000000
+#define BIT51 0x8000000000000
+#define BIT52 0x10000000000000
+#define BIT53 0x20000000000000
+#define BIT54 0x40000000000000
+#define BIT55 0x80000000000000
+#define BIT56 0x100000000000000
+#define BIT57 0x200000000000000
+#define BIT58 0x400000000000000
+#define BIT59 0x800000000000000
+#define BIT60 0x1000000000000000
+#define BIT61 0x2000000000000000
+#define BIT62 0x4000000000000000
+#define BIT63 0x8000000000000000
+#endif
+///
+/// Enumerate a DTS event type
+///
+typedef enum {
+ DtsEventNone,
+ DtsEventThreshold,
+ DtsEventOutOfSpec,
+ DtsEventMax
+} DTS_EVENT_TYPE;
+
+///
+/// Memory Mapped PCI Access macro
+///
+//#define MmPciExpressAddress(Bus, Device, Function, Register) \
+// ( \
+// (UINTN) GetPciExpressBaseAddress () + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \
+// (Function << 12) + (UINTN) (Register) \
+// )
+
+#define MmPciExpressAddress(Bus, Device, Function, Register) \
+ ( \
+ (UINTN) PlatformPciExpressBaseAddress + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \
+ (Function << 12) + (UINTN) (Register) \
+ )
+
+//
+// Function declarations
+//
+/**
+ SMI handler to handle Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @param[in] SmmImageHandle Image handle returned by the SMM driver.
+ @param[in] CommunicationBuffer Pointer to the buffer that contains the communication Message
+ @param[in] SourceSize Size of the memory image to be used for handler.
+
+ @retval EFI_SUCCESS Callback Function Executed
+**/
+EFI_STATUS
+EFIAPI
+DtsSmiCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ );
+
+/**
+ Call from SMI handler to handle Package thermal temperature Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @retval None
+**/
+VOID
+PackageThermalDTS (
+ VOID
+ );
+
+/**
+ Perform first time initialization of the Digital Thermal Sensor
+
+ @retval EFI_SUCCESS Init Digital Thermal Sensor successfully
+**/
+EFI_STATUS
+DigitalThermalSensorInit (
+ VOID
+ );
+
+/**
+ Initializes the Thermal Sensor Control MSR
+
+ This function must be AP safe.
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnable (
+ VOID *Buffer
+ );
+
+/**
+ Initializes the Package Thermal Sensor Control MSR
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+PackageDigitalThermalSensorEnable (
+ VOID *Buffer
+ );
+
+/**
+ Generates a _GPE._L02 SCI to an ACPI OS.
+**/
+VOID
+DigitalThermalSensorSetSwGpeSts (
+ VOID
+ );
+
+/**
+ Checks for a Core Thermal Event by reading MSR.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to DTS_EVENT_TYPE
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEventCheckMsr (
+ IN VOID *Buffer
+ );
+
+/**
+ Checks for a Package Thermal Event by reading MSR.
+
+ @param[in] PkgEventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a Package DTS Thermal event
+ @retval FALSE means this is not a Package DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheckPackageMsr (
+ DTS_EVENT_TYPE *PkgEventType
+ );
+
+/**
+ Checks for a Core Thermal Event on any processor
+
+ @param[in] EventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a DTS Thermal event
+ @retval FALSE means this is not a DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheck (
+ DTS_EVENT_TYPE *EventType
+ );
+
+/**
+ Read the temperature and reconfigure the thresholds.
+ This function must be AP safe.
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ );
+
+/**
+ Read the temperature and reconfigure the thresholds on the package
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ );
+
+/**
+ Set the Out Of Spec Interrupt in all cores
+ This function must be AP safe.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ );
+
+/**
+ Set the Out Of Spec Interrupt on the package
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ );
+
+/**
+ Enables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Enable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnableSmi (
+ VOID *Buffer
+ );
+
+/**
+ Disables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Disable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorDisableSmi (
+ VOID *Buffer
+ );
+
+/**
+ Digital Thermal Sensor (DTS) SMM driver entry point function.
+
+ @param[in] ImageHandle Image handle for this driver image
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+InstallDigitalThermalSensor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Runs the specified procedure on one specific logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Index Indicate which logical processor should execute this procedure
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnSpecificLogicalProcessor (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN UINTN Index,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Performs initialization of the threshold table.
+
+ @todo Update this function as necessary for the tables used by the implementation.
+
+ @retval EFI_SUCCESS Threshold tables initialized successfully.
+**/
+EFI_STATUS
+ThresholdTableInit (
+ VOID
+ );
+
+/**
+ This function executes DTS procedures for preparing to enter S3.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS DTS disabled
+**/
+VOID
+EFIAPI
+DtsS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *Context
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf
new file mode 100644
index 0000000..f5d0d57
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf
@@ -0,0 +1,106 @@
+## @file
+# Component description file for the DigitalThermalSensor SMM driver
+#
+#@copyright
+# Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains an 'Intel Peripheral Driver' and uniquely
+# identified as "Intel Reference Module" and is
+# licensed for Intel CPUs and chipsets under the terms of your
+# license agreement with Intel or your vendor. This file may
+# be modified by the user, subject to additional terms of the
+# license agreement
+#
+
+
+[defines]
+BASE_NAME = DigitalThermalSensorSmm
+FILE_GUID = 77A6009E-116E-464D-8EF8-B35201A022DD
+COMPONENT_TYPE = RT_DRIVER
+
+[sources.common]
+ DigitalThermalSensorSmm.c
+ DigitalThermalSensorSmm.h
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueSmmDriverEntryPoint.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Framework
+ .
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Core/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Pcd
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode/Library/AslUpdate/Dxe
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)
+
+
+[includes.ipf]
+
+[libraries.common]
+ EdkProtocolLib
+ ArchProtocolLib
+ EdkFrameworkProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueUefiLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiDevicePathLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGlueBasePciExpressLib
+ EfiProtocolLib
+ DTSHookLib
+ DxeAslUpdateLib
+ SmmIoLib
+ SmmKscLib
+ CpuProtocolLib
+ PchPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT=_ModuleEntryPoint
+ DPX_SOURCE=DigitalThermalSensorSmm.dxs
+
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallDigitalThermalSensor
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_UEFI_LIB__\
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
+
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak
new file mode 100644
index 0000000..a1386d5
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak
@@ -0,0 +1,77 @@
+# MAK file for the Module Part: PowerMgmtS3
+
+EDK : DigitalThermalSensorSmm
+
+BUILD_DigitalThermalSensorSmm_DIR = $(BUILD_DIR)\$(DigitalThermalSensorSmm_DIR)
+
+$(BUILD_DIR)\DigitalThermalSensorSmm.mak : $(DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.cif $(BUILD_RULES)
+ $(CIF2MAK) $(DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.cif $(CIF2MAK_DEFAULTS)
+
+DigitalThermalSensorSmm : $(BUILD_DIR)\DigitalThermalSensorSmm.mak DigitalThermalSensorSmmBin
+
+DigitalThermalSensorSmm_OBJECTS = \
+ $(BUILD_DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.obj
+
+DigitalThermalSensorSmm_MY_INCLUDES= \
+ $(EDK_INCLUDES) \
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_PLATFORM_PROTOCOL_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)
+
+DigitalThermalSensorSmm_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallDigitalThermalSensor"\
+ /D PlatformPciExpressBaseAddress=$(PCIEX_BASE_ADDRESS) \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+# /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
+
+DigitalThermalSensorSmm_LIBS =\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKGUIDLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(CpuProtocolLib_LIB)\
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(PpmAslUpdateLib_LIB)\
+ $(SmmIoLib_LIB)\
+ $(SmmKscLib_LIB)\
+ $(DTSHookLib_LIB)\
+ $(PchPlatformSmmLib_LIB)
+
+DigitalThermalSensorSmmBin : $(DigitalThermalSensorSmm_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\DigitalThermalSensorSmm.mak all\
+ MAKEFILE=$(BUILD_DIR)\DigitalThermalSensorSmm.mak \
+ "MY_INCLUDES=$(DigitalThermalSensorSmm_MY_INCLUDES)" \
+ "MY_DEFINES=$(DigitalThermalSensorSmm_DEFINES)"\
+ OBJECTS="$(DigitalThermalSensorSmm_OBJECTS)" \
+ GUID=77A6009E-116E-464D-8EF8-B35201A022DD\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER \
+ EDKIIModule=SMMDRIVER\
+ DEPEX1=$(DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl
new file mode 100644
index 0000000..a28ccce
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "Haswell_DigitalThermalSensorSmm_SUPPORT"
+ Value = "1"
+ Help = "Main switch to include Haswell DigitalThermalSensorSmm driver to the Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "DigitalThermalSensorSmm_DIR"
+End
+
+MODULE
+ Help = "Includes DigitalThermalSensorSmm.mak to Project"
+ File = "DigitalThermalSensorSmm.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\DigitalThermalSensorSmm.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End