diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/DTS/Smm | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Haswell/DTS/Smm')
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 |