AcpiPlatformLibSsdt.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. /** @file
  2. ACPI Platform Driver Hooks
  3. @copyright
  4. Copyright 1996 - 2020 Intel Corporation. <BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. //
  8. // Statements that include other files
  9. //
  10. #include "AcpiPlatformLibLocal.h"
  11. #include <Protocol/DynamicSiLibraryProtocol2.h>
  12. extern BIOS_ACPI_PARAM *mAcpiParameter;
  13. extern EFI_IIO_UDS_PROTOCOL *mIioUds;
  14. extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
  15. extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
  16. extern BOOLEAN mCpuOrderSorted;
  17. extern UINT32 mApicIdMap[MAX_SOCKET][MAX_CORE * MAX_THREAD];
  18. extern UINT32 mNumOfBitShift;
  19. extern UINT32 mEnabledProcessor[MAX_SOCKET];
  20. extern EFI_CPU_CSR_ACCESS_PROTOCOL *mCpuCsrAccess;
  21. UINT32 mCpuPCPSInfo[MAX_SOCKET];
  22. UINT32 mNcpuValue[MAX_SOCKET];
  23. extern CPU_ID_ORDER_MAP mCpuApicIdOrderTable[];
  24. extern UINT8 mPStateEnable;
  25. #ifndef MSR_MISC_ENABLES
  26. #define MSR_MISC_ENABLES 0x01A0
  27. #endif
  28. /**
  29. This function detects PCPS Info
  30. mCpuPCPSInfo usage:
  31. Bit[15:0]: Enabled processors in current socket
  32. Bit[16]: Hyperthreading enable
  33. Bit[17]: PCPS disable in system
  34. @param None
  35. @retval VOID
  36. **/
  37. VOID
  38. DetectPcpsInfo (
  39. VOID
  40. )
  41. {
  42. UINT8 Socket;
  43. UINT32 CpuPCPSInfo = 0;
  44. UINT32 SmtDisable = 0;
  45. UINT32 Csr;
  46. EFI_STATUS Status = EFI_SUCCESS;
  47. DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
  48. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, (VOID **) &DynamicSiLibraryProtocol2);
  49. if (EFI_ERROR (Status)) {
  50. ASSERT_EFI_ERROR (Status);
  51. return;
  52. }
  53. for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
  54. if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].Valid) {
  55. SmtDisable = DynamicSiLibraryProtocol2->PcuGetDesiredCoreSmtDis (Socket);
  56. Csr = mCpuCsrAccess->ReadCpuCsr (Socket, 0, 0x04320084);
  57. if (!SmtDisable && !(Csr & (1 << 12))) {
  58. mCpuPCPSInfo[Socket] |= B_PCPS_HT_ENABLE;
  59. }
  60. CpuPCPSInfo = mCpuPCPSInfo[Socket];
  61. //
  62. // Update NCPU
  63. //
  64. mNcpuValue[Socket] = mCpuPCPSInfo[Socket] & 0xFF;
  65. if (((CpuPCPSInfo & B_PCPS_DISABLE) == 0)) {
  66. if (CpuPCPSInfo & B_PCPS_HT_ENABLE) {
  67. mNcpuValue[Socket] = 2;
  68. } else {
  69. mNcpuValue[Socket] = 1;
  70. }
  71. }
  72. }
  73. }
  74. for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
  75. if (mCpuPCPSInfo[Socket] == 0) {
  76. mCpuPCPSInfo[Socket] = CpuPCPSInfo;
  77. mNcpuValue[Socket] = mNcpuValue[0];
  78. }
  79. }
  80. }
  81. /**
  82. Find APICID in mCpuApicIdOrderTable
  83. @param SocketIndex - In: Acpi thread number
  84. @param ThreadIndex - In: Acpi thread number
  85. @retval APICID - If not found, return 0xFFFFFFFF
  86. **/
  87. UINT32
  88. LocateApicIdInfo (
  89. IN UINT32 SocketIndex,
  90. IN UINT32 ThreadIndex
  91. )
  92. {
  93. if (mApicIdMap[SocketIndex][ThreadIndex] == (UINT32) -1) {
  94. return (UINT32) -1;
  95. }
  96. return (mApicIdMap[SocketIndex][ThreadIndex] + (SocketIndex << mNumOfBitShift));
  97. }
  98. /**
  99. Gather the EIST information
  100. @param ThreadId - In: Acpi thread number
  101. @param CpuMiscData - In/Out: Pointer to thread's CPU_MISC_DTAT struct
  102. @retval EFI_SUCCESS - EIST info retrieved
  103. **/
  104. EFI_STATUS
  105. LocateCpuEistInfo (
  106. IN UINT32 CpuIndex,
  107. OUT CPU_MISC_DATA **CpuMiscData
  108. )
  109. {
  110. UINTN Index;
  111. UINT32 Socket;
  112. UINT32 ApicId;
  113. const UINT32 *ApicMapPtr;
  114. Socket = CpuIndex / (MAX_CORE * MAX_THREAD);
  115. Index = CpuIndex % (MAX_CORE * MAX_THREAD);
  116. ApicMapPtr = mApicIdMap[Socket];
  117. ApicId = mAcpiParameter->ProcessorApicIdBase[Socket] + ApicMapPtr[Index];
  118. for (Index = 0; Index < mCpuConfigLibConfigContextBuffer->NumberOfProcessors; ++Index) {
  119. if (mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[Index].CpuMiscData.ApicID == ApicId) {
  120. *CpuMiscData = &mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[Index].CpuMiscData;
  121. break;
  122. }
  123. }
  124. if (*CpuMiscData == NULL) { //use SBSP's data
  125. *CpuMiscData = &mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[0].CpuMiscData;
  126. }
  127. return EFI_SUCCESS;
  128. }
  129. /**
  130. Determine turbo mode status
  131. @param None
  132. @retval TRUE if turbo enabled, FALSE if disabled
  133. **/
  134. BOOLEAN
  135. IsTurboModeEnabled (
  136. VOID
  137. )
  138. {
  139. EFI_CPUID_REGISTER CpuidRegisters;
  140. BOOLEAN Status;
  141. UINT64 MiscEnable;
  142. Status = FALSE;
  143. AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
  144. if (((CPUID_THERMAL_POWER_MANAGEMENT_EAX*)&CpuidRegisters.RegEax)->Bits.TurboBoostTechnology != 0) {
  145. //
  146. // Turbo mode is supported on this processor (Available)
  147. //
  148. MiscEnable = AsmReadMsr64 (MSR_MISC_ENABLES);
  149. if ((RShiftU64 (MiscEnable, 38) & 1) == 0) { // Bit 38 is TurboModeDisable
  150. //
  151. // Turbo mode is supported on this processor (Available)
  152. //
  153. Status = TRUE;
  154. }
  155. }
  156. return Status;
  157. }
  158. /**
  159. Finds the actual beginning of a CPU SSDT table, skips the If(Zero) { External() ... } opcode
  160. auto-generated by the iASL 6.1 compiler
  161. From iASL/6.1/changes.txt
  162. "Completed full support for the ACPI 6.0 External() AML opcode. The
  163. compiler emits an external AML opcode for each ASL External statement.
  164. This opcode is used by the disassembler to assist with the disassembly of
  165. external control methods by specifying the required number of arguments
  166. for the method. AML interpreters do not use this opcode. To ensure that
  167. interpreters do not even see the opcode, a block of one or more external
  168. opcodes is surrounded by an "If(0)" construct. As this feature becomes
  169. commonly deployed in BIOS code, the ability of disassemblers to correctly
  170. disassemble AML code will be greatly improved."
  171. The AML code contains external (_SB_SCKxCyyy) opcodes within a If(Zero) statement;
  172. we have to ignore this opcodes and start patching from the actual table begin marker, i.e., "TBST"
  173. @param[in] BeginPtr a pointer to the begin of a SSDT table
  174. @param[in] EndPtr a pointer to the end of a SSDT table
  175. @retval beginning of the part of SSDT table past external _SB_ opcodes
  176. **/
  177. static inline
  178. UINT8 *
  179. SkipExternalSbOpcodes(
  180. IN UINT8 *BeginPtr,
  181. IN UINT8 *EndPtr,
  182. IN UINT32 ExternSbExpected
  183. )
  184. {
  185. UINT8 *CurPtr = BeginPtr;
  186. UINT32 ExternSbFound = 0;
  187. ASSERT (BeginPtr < EndPtr);
  188. DEBUG ((DEBUG_VERBOSE, "SkipExternalSbOpcodes start\n"));
  189. for (CurPtr = BeginPtr; CurPtr < EndPtr; ++CurPtr) {
  190. UINT32 Signature = *(UINT32 *) CurPtr;
  191. if (SIGNATURE_32 ('_', 'S', 'B', '_') == Signature) {
  192. CONST EXTERNAL_OBJECT_DECL *ExternDecl = ACPI_EXTERNAL_OBJECT_DECL_FROM_NAME_STR (CurPtr);
  193. ASSERT (BeginPtr < (UINT8 *)ExternDecl);
  194. if ((AML_EXTERNAL_OP == ExternDecl->ExternalOp ) &&
  195. (AML_ROOT_CHAR == ExternDecl->RootChar) &&
  196. (AML_MULTI_NAME_PREFIX == ExternDecl->MultiNamePrefix) &&
  197. (0x3 <= ExternDecl->SegCount)) {
  198. ++ExternSbFound;
  199. } else {
  200. break;
  201. }
  202. }
  203. }
  204. DEBUG ((DEBUG_ERROR, "ExternSbExpected: %d, ExternSbFound: %d\n"));
  205. ASSERT ((ExternSbFound % ExternSbExpected) == 0);
  206. DEBUG ((DEBUG_VERBOSE, "SkipExternalSbOpcodes end\n"));
  207. return CurPtr;
  208. }
  209. /**
  210. Update the CPU PM SSDT table
  211. @param[in,out] TableHeader The table to be set
  212. @retval EFI_SUCCESS Returns Success
  213. @retval EFI_UNSUPPORTED Table is not supported
  214. **/
  215. EFI_STATUS
  216. PatchCpuPmSsdtTable (
  217. IN OUT EFI_ACPI_COMMON_HEADER *Table
  218. )
  219. {
  220. UINT8 *CurrPtr;
  221. UINT8 *EndPtr;
  222. UINT8 *SsdtPointer;
  223. UINT32 Signature;
  224. UINT32 CpuFixes;
  225. UINT32 CpuSkt;
  226. UINT32 CpuIndex;
  227. UINT32 ThreadIndex;
  228. UINT32 AdjustSize;
  229. ACPI_NAMEPACK_DWORD *NamePtr;
  230. UINT32 DomnValue;
  231. ACPI_NAME_COMMAND *PsdPackage;
  232. PSD_PACKAGE_LAYOUT *PsdPackageItemPtr;
  233. CPU_MISC_DATA *CpuMiscData;
  234. DEBUG ((DEBUG_INFO, "Patching SSDT PatchCpuPmSsdtTable\n"));
  235. //
  236. // Loop through the ASL looking for values that we must fix up.
  237. //
  238. DomnValue = 0;
  239. CpuFixes = 0;
  240. CpuSkt = 0;
  241. CpuIndex = 0;
  242. ThreadIndex = 0;
  243. CurrPtr = (UINT8 *) Table;
  244. EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
  245. CpuMiscData = NULL;
  246. DetectPcpsInfo ();
  247. //
  248. // CurrPtr = beginning of table to search
  249. //
  250. CurrPtr = SkipExternalSbOpcodes (CurrPtr, EndPtr, (UINT32) MAX_CPU_NUM);
  251. //
  252. // Subtract 11 from EndPtr - this is the size of the largest data item we will search for
  253. // so that we do not try to read past the end of the table
  254. //
  255. EndPtr -= 11;
  256. for (SsdtPointer = CurrPtr; SsdtPointer <= EndPtr; ++SsdtPointer) {
  257. Signature = *(UINT32 *) SsdtPointer;
  258. CpuIndex = 0;
  259. AdjustSize = 0;
  260. switch (Signature) {
  261. //
  262. // The AML code contains strings in the form of _SB_SCKxCyyy where x is the socket number
  263. // and yyy is the thread number in hexadecimal, this first case parses that string and saves
  264. // the socket number into CpuSkt and the thread number into CpuIndex.
  265. //
  266. case SIGNATURE_32 ('_', 'S', 'B', '_'):
  267. //
  268. // SKTX
  269. //
  270. CpuSkt = *(SsdtPointer + 7);
  271. if ((CpuSkt < '0') || ((CpuSkt - '0') > MAX_SOCKET)) {
  272. CpuSkt = '0';
  273. }
  274. CpuSkt -= '0';
  275. if ((*(SsdtPointer + 8) != 'C')) {
  276. continue;
  277. }
  278. if ((*(SsdtPointer + 11) > '0') && (*(SsdtPointer + 11) <= '9')) {
  279. CpuIndex = (*(SsdtPointer + 11) -'0');
  280. } else if ((*(SsdtPointer + 11) >= 'A') && (*(SsdtPointer + 11) <= 'F')) {
  281. CpuIndex = (*(SsdtPointer + 11) -'A' + 10);
  282. }
  283. if ((*(SsdtPointer + 10) > '0') && ( *(SsdtPointer + 10) <= '9')) {
  284. AdjustSize = (*(SsdtPointer + 10) -'0') * 0x10;
  285. } else if ((*(SsdtPointer + 10) >= 'A') && (*(SsdtPointer + 10) <= 'F')) {
  286. AdjustSize = (*(SsdtPointer + 10) -'A' + 10) * 0x10;
  287. }
  288. CpuIndex += AdjustSize;
  289. AdjustSize = 0;
  290. if ((*(SsdtPointer + 9) > '0') && (*(SsdtPointer + 9) <= '9')) {
  291. AdjustSize = (*(SsdtPointer + 9) -'0') * 0x100;
  292. } else if ((*(SsdtPointer + 9) >= 'A') && (*(SsdtPointer + 9) <= 'F')) {
  293. AdjustSize = (*(SsdtPointer + 9) -'A' + 10) * 0x100;
  294. }
  295. CpuIndex += AdjustSize;
  296. ThreadIndex = CpuIndex;
  297. //
  298. // PCPS - Update DOMN
  299. //
  300. DomnValue = (UINT8) CpuSkt;
  301. if ((mCpuPCPSInfo[CpuSkt] & B_PCPS_DISABLE) == 0) {
  302. DomnValue = LocateApicIdInfo (CpuSkt, ThreadIndex);
  303. if (mNcpuValue[CpuSkt] == 2) {
  304. DomnValue = (DomnValue >> 1);
  305. }
  306. }
  307. DEBUG ((
  308. DEBUG_INFO,
  309. ":ACPI: PatchCpuPmSsdtTable(): CpuSkt: %d ThreadIndex: %d, NcpuValue: %d, DomnValue: %d\n",
  310. CpuSkt,
  311. ThreadIndex,
  312. mNcpuValue[CpuSkt],
  313. DomnValue
  314. ));
  315. ++CpuFixes;
  316. CpuMiscData = NULL;
  317. LocateCpuEistInfo (0, &CpuMiscData); // use CPU0 for update NPSS and SPSS
  318. break;
  319. case SIGNATURE_32 ('D', 'O', 'M', 'N'):
  320. NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
  321. if (NamePtr->StartByte != AML_NAME_OP) {
  322. continue;
  323. }
  324. if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
  325. continue;
  326. }
  327. NamePtr->Value = DomnValue;
  328. break;
  329. case SIGNATURE_32 ('N', 'C', 'P', 'U'):
  330. NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
  331. if (NamePtr->StartByte != AML_NAME_OP) {
  332. continue;
  333. }
  334. if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
  335. continue;
  336. }
  337. NamePtr->Value = (UINT32) mNcpuValue[CpuSkt];
  338. break;
  339. case SIGNATURE_32 ('P', 'S', 'D', 'C'):
  340. case SIGNATURE_32 ('P', 'S', 'D', 'E'):
  341. PsdPackage = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
  342. if (PsdPackage->StartByte != AML_NAME_OP) {
  343. continue;
  344. }
  345. PsdPackageItemPtr = (PSD_PACKAGE_LAYOUT *) ((UINT8 *) PsdPackage);
  346. DEBUG ((
  347. DEBUG_VERBOSE,
  348. "PatchCpuPmSsdtTable(): PsdPackageItemPtr table: %x is detected...\n",
  349. PsdPackage->NameStr
  350. ));
  351. DEBUG ((
  352. DEBUG_VERBOSE,
  353. " Initial Values: Domain = %x, CoordType = %x, NumProcessors = %x\n",
  354. PsdPackageItemPtr->Domain,
  355. PsdPackageItemPtr->CoordType,
  356. PsdPackageItemPtr->NumProcessors
  357. ));
  358. PsdPackageItemPtr->Domain = DomnValue;
  359. PsdPackageItemPtr->NumProcessors = (UINT32) mNcpuValue[CpuSkt];
  360. DEBUG ((
  361. DEBUG_VERBOSE,
  362. " PsdPackage = %x, PsdPackageItemPtr = %x, SsdtPointer = %x\n",
  363. (UINT8 *)PsdPackage,
  364. (UINT8 *)PsdPackageItemPtr,
  365. (UINT8 *)SsdtPointer
  366. ));
  367. DEBUG ((
  368. DEBUG_VERBOSE,
  369. " Updated PSD Domain = %x, CoordType = %x, NumProcessors = %x\n",
  370. PsdPackageItemPtr->Domain,
  371. PsdPackageItemPtr->CoordType,
  372. PsdPackageItemPtr->NumProcessors
  373. ));
  374. break;
  375. default:
  376. break;
  377. } // switch
  378. } // for
  379. //
  380. // N fixes together currently
  381. //
  382. ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
  383. return EFI_SUCCESS;
  384. }
  385. /**
  386. Update the OEM1 P-State SSDT table (EIST)
  387. @param *TableHeader - The table to be set
  388. @retval EFI_SUCCESS - Returns Success
  389. **/
  390. EFI_STATUS
  391. PatchOem1SsdtTable (
  392. IN OUT EFI_ACPI_COMMON_HEADER *Table
  393. )
  394. {
  395. EFI_STATUS Status;
  396. UINT8 *CurrPtr;
  397. UINT8 *EndPtr;
  398. UINT8 *SsdtPointer;
  399. UINT32 Signature;
  400. UINT32 CpuFixes;
  401. UINT32 NpssFixes;
  402. UINT32 GpssFixes;
  403. UINT32 CpuSkt;
  404. UINT32 CpuIndex;
  405. UINT32 PackageSize;
  406. UINT32 NewPackageSize;
  407. UINT32 AdjustSize;
  408. UINTN TableIndex;
  409. ACPI_NAME_COMMAND *PssTable;
  410. PSS_PACKAGE *PssTableItemPtr;
  411. CPU_MISC_DATA *CpuMiscData;
  412. FVID_ENTRY *PssState;
  413. DEBUG ((DEBUG_INFO, "Patching SSDT PatchOem1SsdtTable\n"));
  414. //
  415. // Loop through the ASL looking for values that we must fix up.
  416. //
  417. NpssFixes = 0;
  418. GpssFixes = 0;
  419. CpuFixes = 0;
  420. CpuSkt = 0;
  421. CpuIndex = 0;
  422. CurrPtr = (UINT8 *) Table;
  423. EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
  424. CpuMiscData = NULL;
  425. Status = LocateCpuEistInfo (0, &CpuMiscData); // get BSP's data
  426. if( (EFI_ERROR (Status)) || (CpuMiscData == NULL ) ){
  427. DEBUG ((DEBUG_WARN, " PatchGv3SsdtTable - EIST info for BSP index not found \n"));
  428. return Status;
  429. }
  430. mPStateEnable = 1;
  431. //
  432. // CurrPtr = beginning of table to search
  433. //
  434. CurrPtr = SkipExternalSbOpcodes (CurrPtr, EndPtr, (UINT32) MAX_CPU_NUM);
  435. //
  436. // Subtract 11 from EndPtr - this is the size of the larget data item we will search for
  437. // so that we do not try to read past the end of the table
  438. //
  439. EndPtr -= 11;
  440. for (SsdtPointer = CurrPtr; SsdtPointer <= EndPtr; ++SsdtPointer) {
  441. Signature = *(UINT32 *) SsdtPointer;
  442. CpuIndex = 0;
  443. AdjustSize = 0;
  444. switch (Signature) {
  445. case SIGNATURE_32 ('_', 'S', 'B', '_'):
  446. //
  447. // SKTX
  448. //
  449. CpuSkt = *(SsdtPointer + 7);
  450. if ((CpuSkt < '0') || ((CpuSkt - '0') > MAX_SOCKET)) {
  451. CpuSkt = '0';
  452. }
  453. CpuSkt -= '0';
  454. if ((*(SsdtPointer + 11) > '0') && (*(SsdtPointer + 11) <= '9')) {
  455. CpuIndex = (*(SsdtPointer + 11) -'0');
  456. } else if ((*(SsdtPointer + 11) >= 'A') && (*(SsdtPointer + 11) <= 'F')) {
  457. CpuIndex = (*(SsdtPointer + 11) -'A' + 10);
  458. }
  459. if ((*(SsdtPointer + 10) > '0') && ( *(SsdtPointer + 10) <= '9')) {
  460. AdjustSize = (*(SsdtPointer + 10) -'0') * 0x10;
  461. } else if ((*(SsdtPointer + 10) >= 'A') && (*(SsdtPointer + 10) <= 'F')) {
  462. AdjustSize = (*(SsdtPointer + 10) -'A' + 10) * 0x10;
  463. }
  464. CpuIndex += AdjustSize;
  465. AdjustSize = 0;
  466. if ((*(SsdtPointer + 9) > '0') && (*(SsdtPointer + 9) <= '9')) {
  467. AdjustSize = (*(SsdtPointer + 9) -'0') * 0x100;
  468. } else if ((*(SsdtPointer + 9) >= 'A') && (*(SsdtPointer + 9) <= 'F')) {
  469. AdjustSize = (*(SsdtPointer + 9) -'A' + 10) * 0x100;
  470. }
  471. CpuIndex += AdjustSize;
  472. ++CpuFixes;
  473. CpuMiscData = NULL;
  474. LocateCpuEistInfo (0, &CpuMiscData); // use CPU0 for update NPSS and SPSS
  475. break;
  476. case SIGNATURE_32 ('N', 'P', 'S', 'S'):
  477. case SIGNATURE_32 ('S', 'P', 'S', 'S'):
  478. PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
  479. if (PssTable->StartByte != AML_NAME_OP) {
  480. continue;
  481. }
  482. ASSERT (CpuMiscData != NULL);
  483. PssState = CpuMiscData->FvidTable;
  484. AdjustSize = PssTable->NumEntries * sizeof (PSS_PACKAGE);
  485. AdjustSize -= (UINT32)(CpuMiscData->NumberOfPStates * sizeof (PSS_PACKAGE));
  486. PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);
  487. NewPackageSize = PackageSize - AdjustSize;
  488. PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));
  489. //
  490. // Set most significant two bits of byte zero to 01, meaning two bytes used
  491. //
  492. PssTable->Size |= 0x40;
  493. //
  494. // Set unused table to Noop Code
  495. //
  496. SetMem (
  497. (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE,
  498. AdjustSize,
  499. AML_NOOP_OP
  500. );
  501. PssTable->NumEntries = (UINT8) CpuMiscData->NumberOfPStates;
  502. PssTableItemPtr = (PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (ACPI_NAME_COMMAND));
  503. //
  504. // Update the size
  505. //
  506. if (CpuMiscData->NumberOfPStates == 1) {
  507. mPStateEnable = 0;
  508. }
  509. for (TableIndex = 0; TableIndex < CpuMiscData->NumberOfPStates; ++TableIndex) {
  510. PssTableItemPtr->CoreFreq = (UINT32) (CpuMiscData->IntendedFsbFrequency * PssState[TableIndex].Ratio);
  511. if (mSocketPowermanagementConfiguration.TurboMode && (TableIndex == 0) && IsTurboModeEnabled ()) {
  512. PssTableItemPtr->CoreFreq = (UINT32)((CpuMiscData->IntendedFsbFrequency * PssState[TableIndex + 1].Ratio) + 1);
  513. }
  514. PssTableItemPtr->Power = (UINT32)(PssState[TableIndex].Power); // when calulate Tdp already make it mW;
  515. if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
  516. PssTableItemPtr->TransLatency = (UINT32)(PssState[TableIndex].TransitionLatency);
  517. PssTableItemPtr->Control = (UINT32)(PssState[TableIndex].Ratio << 8);
  518. PssTableItemPtr->Status = (UINT32)(PssState[TableIndex].Ratio << 8);
  519. } else {
  520. //
  521. // This method should be supported by SMM PPM Handler
  522. //
  523. // Status is simply the state number.
  524. // Use the state number w/ OS command value so that the
  525. // legacy interface may be used. Latency for SMM is 100 + BM latency.
  526. PssTableItemPtr->Status = (UINT32)TableIndex;
  527. PssTableItemPtr->TransLatency = (UINT32)(100 + PssState[TableIndex].TransitionLatency);
  528. PssTableItemPtr->Control = (UINT32)(SW_SMI_OS_REQUEST | (TableIndex << 8));
  529. }
  530. PssTableItemPtr->BMLatency = (UINT32)(PssState[TableIndex].BusMasterLatency);
  531. ++PssTableItemPtr;
  532. }
  533. if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
  534. ++NpssFixes;
  535. }
  536. SsdtPointer = (UINT8 *) PssTable + PackageSize;
  537. break;
  538. case SIGNATURE_32 ('G', 'P', 'S', 'S'):
  539. PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
  540. if (PssTable->StartByte != AML_NAME_OP) {
  541. continue;
  542. }
  543. ASSERT (CpuMiscData != NULL);
  544. PssState = CpuMiscData->GreaterFvidTable;
  545. ASSERT (CpuMiscData->GreaterNumberOfPStates <= GPSS_FVID_MAX_STATES);
  546. if (CpuMiscData->GreaterNumberOfPStates > GPSS_FVID_MAX_STATES) {
  547. continue;
  548. }
  549. AdjustSize = PssTable->NumEntries * sizeof (PSS_PACKAGE);
  550. AdjustSize -= (UINT32)(CpuMiscData->GreaterNumberOfPStates * sizeof (PSS_PACKAGE));
  551. PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);
  552. NewPackageSize = PackageSize - AdjustSize;
  553. PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));
  554. //
  555. // Set most significant two bits of byte zero to 01, meaning two bytes used
  556. //
  557. PssTable->Size |= 0x40;
  558. //
  559. // Set unused table to Noop Code
  560. //
  561. SetMem (
  562. (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE,
  563. AdjustSize,
  564. AML_NOOP_OP
  565. );
  566. PssTable->NumEntries = (UINT8) CpuMiscData->GreaterNumberOfPStates;
  567. PssTableItemPtr = (PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (ACPI_NAME_COMMAND));
  568. //
  569. // Update the size
  570. //
  571. for (TableIndex = 0; TableIndex < CpuMiscData->GreaterNumberOfPStates; ++TableIndex) {
  572. PssTableItemPtr->CoreFreq = (UINT32) (CpuMiscData->IntendedFsbFrequency * PssState[TableIndex].Ratio);
  573. if (mSocketPowermanagementConfiguration.TurboMode && (TableIndex == 0) && IsTurboModeEnabled()) {
  574. PssTableItemPtr->CoreFreq = (UINT32)((CpuMiscData->IntendedFsbFrequency * PssState[TableIndex + 1].Ratio) + 1);
  575. }
  576. //
  577. // If Turbo mode is supported, add one to the Max Non-Turbo frequency
  578. //
  579. PssTableItemPtr->Power = (UINT32)(PssState[TableIndex].Power); // when calulate Tdp already make it mW;
  580. if (PssTable->NameStr == SIGNATURE_32 ('G', 'P', 'S', 'S')) {
  581. PssTableItemPtr->TransLatency = (UINT32)(PssState[TableIndex].TransitionLatency);
  582. PssTableItemPtr->Control = (UINT32)(PssState[TableIndex].Ratio << 8);
  583. PssTableItemPtr->Status = (UINT32)(PssState[TableIndex].Ratio << 8);
  584. } else {
  585. //
  586. // This method should be supported by SMM PPM Handler
  587. //
  588. // Status is simply the state number.
  589. // Use the state number w/ OS command value so that the
  590. // legacy interface may be used. Latency for SMM is 100 + BM latency.
  591. //
  592. PssTableItemPtr->Status = (UINT32)TableIndex;
  593. PssTableItemPtr->TransLatency = (UINT32)(100 + PssState[TableIndex].TransitionLatency);
  594. PssTableItemPtr->Control = (UINT32)(SW_SMI_OS_REQUEST | (TableIndex << 8));
  595. }
  596. PssTableItemPtr->BMLatency = (UINT32)(PssState[TableIndex].BusMasterLatency);
  597. ++PssTableItemPtr;
  598. }
  599. if (PssTable->NameStr == SIGNATURE_32 ('G', 'P', 'S', 'S')) {
  600. ++GpssFixes;
  601. }
  602. SsdtPointer = (UINT8 *) PssTable + PackageSize;
  603. break;
  604. default:
  605. break;
  606. } // switch
  607. } // for
  608. //
  609. // N fixes together currently
  610. //
  611. ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
  612. if (!mPStateEnable || !mSocketPowermanagementConfiguration.ProcessorEistEnable || (mSocketPowermanagementConfiguration.ProcessorHWPMEnable > HWP_MODE_NATIVE) ) {
  613. Status = EFI_UNSUPPORTED; //CPU EIST
  614. return Status;
  615. }
  616. return EFI_SUCCESS;
  617. }
  618. EFI_STATUS
  619. PatchSsdtTable (
  620. IN OUT EFI_ACPI_COMMON_HEADER *Table,
  621. IN OUT EFI_ACPI_TABLE_VERSION *Version
  622. )
  623. {
  624. EFI_STATUS Status;
  625. EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
  626. Status = EFI_SUCCESS;
  627. TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *)Table;
  628. //
  629. // Do not load the xHCI table. It is handled by separate function.
  630. //
  631. TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
  632. if (CompareMem (&TableHeader->OemTableId, "xh_", 3) == 0) {
  633. DEBUG ((DEBUG_ERROR,"Xhci TableHeader->OemTableId = %x\n ", TableHeader->OemTableId));
  634. *Version = EFI_ACPI_TABLE_VERSION_NONE;
  635. }
  636. if (TableHeader->OemTableId == SIGNATURE_64 ('S', 'S', 'D', 'T', ' ', ' ', 'P', 'M')) {
  637. PatchCpuPmSsdtTable (Table); //CPU PM
  638. }
  639. return Status;
  640. }
  641. /**
  642. Update the OEM2 HWP SSDT table if needed
  643. @param *TableHeader - The table to be set
  644. @retval EFI_SUCCESS - Returns Success
  645. **/
  646. EFI_STATUS
  647. PatchOem2SsdtTable (
  648. IN OUT EFI_ACPI_COMMON_HEADER *Table
  649. )
  650. {
  651. EFI_STATUS Status = EFI_SUCCESS;
  652. if ((mSocketPowermanagementConfiguration.ProcessorHWPMEnable == 0) || (mSocketPowermanagementConfiguration.ProcessorHWPMEnable == HWP_MODE_OOB)) {
  653. Status = EFI_UNSUPPORTED;
  654. }
  655. return Status;
  656. }
  657. /**
  658. Update the OEM3 T-State SSDT table (TST)
  659. @param *TableHeader - The table to be set
  660. @retval EFI_SUCCESS - Returns Success
  661. **/
  662. EFI_STATUS
  663. PatchOem3SsdtTable (
  664. IN OUT EFI_ACPI_COMMON_HEADER *Table
  665. )
  666. {
  667. UINT8 *CurrPtr;
  668. UINT8 *EndPtr;
  669. UINT8 *SsdtPointer;
  670. UINT32 Signature;
  671. UINT32 CpuFixes;
  672. UINT32 CpuSkt;
  673. UINT32 CpuIndex;
  674. UINT32 ThreadIndex;
  675. UINT32 AdjustSize;
  676. UINT32 DomnValue;
  677. ACPI_NAME_COMMAND *PsdPackage;
  678. PSD_PACKAGE_LAYOUT *PsdPackageItemPtr;
  679. DEBUG ((DEBUG_INFO, "Patching SSDT PatchOem3SsdtTable\n"));
  680. if (!mSocketPowermanagementConfiguration.TStateEnable || (mSocketPowermanagementConfiguration.ProcessorHWPMEnable > HWP_MODE_NATIVE) ) {
  681. return EFI_UNSUPPORTED;
  682. }
  683. //
  684. // Loop through the ASL looking for values that we must fix up.
  685. //
  686. DomnValue = 0;
  687. CpuFixes = 0;
  688. CpuSkt = 0;
  689. ThreadIndex = 0;
  690. CurrPtr = (UINT8 *) Table;
  691. EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
  692. //
  693. // CurrPtr = beginning of table we want to search
  694. //
  695. CurrPtr = SkipExternalSbOpcodes(CurrPtr, EndPtr, (UINT32) MAX_CPU_NUM);
  696. //
  697. // Subtract 11 from EndPtr - this is the size of the larget data item we will read
  698. // so that we don't read beyond the end of the table
  699. //
  700. EndPtr -= 11;
  701. for (SsdtPointer = CurrPtr; SsdtPointer <= EndPtr; ++SsdtPointer) {
  702. Signature = *(UINT32 *) SsdtPointer;
  703. CpuIndex = 0;
  704. AdjustSize = 0;
  705. switch (Signature) {
  706. case SIGNATURE_32 ('_', 'S', 'B', '_'):
  707. //
  708. // SKTX
  709. //
  710. CpuSkt = *(SsdtPointer + 7);
  711. CpuSkt -= '0';
  712. if ((*(SsdtPointer + 8) != 'C')) {
  713. continue;
  714. }
  715. if ((*(SsdtPointer + 11) > '0') && (*(SsdtPointer + 11) <= '9')) {
  716. CpuIndex = (*(SsdtPointer + 11) -'0');
  717. } else if ((*(SsdtPointer + 11) >= 'A') && (*(SsdtPointer + 11) <= 'F')) {
  718. CpuIndex = (*(SsdtPointer + 11) -'A' + 10);
  719. }
  720. if ((*(SsdtPointer + 10) > '0') && ( *(SsdtPointer + 10) <= '9')) {
  721. AdjustSize = (*(SsdtPointer + 10) -'0') * 0x10;
  722. } else if ((*(SsdtPointer + 10) >= 'A') && (*(SsdtPointer + 10) <= 'F')) {
  723. AdjustSize = (*(SsdtPointer + 10) -'A' + 10) * 0x10;
  724. }
  725. CpuIndex += AdjustSize;
  726. AdjustSize = 0;
  727. if ((*(SsdtPointer + 9) > '0') && (*(SsdtPointer + 9) <= '9')) {
  728. AdjustSize = (*(SsdtPointer + 9) -'0') * 0x100;
  729. } else if ((*(SsdtPointer + 9) >= 'A') && (*(SsdtPointer + 9) <= 'F')) {
  730. AdjustSize = (*(SsdtPointer + 9) -'A' + 10) * 0x100;
  731. }
  732. CpuIndex += AdjustSize;
  733. ThreadIndex = CpuIndex;
  734. //
  735. // PCPS - Update DOMN
  736. //
  737. DomnValue = (UINT8) CpuSkt;
  738. if ((mCpuPCPSInfo[CpuSkt] & B_PCPS_DISABLE) == 0) {
  739. DomnValue = LocateApicIdInfo (CpuSkt, ThreadIndex);
  740. if (mNcpuValue[CpuSkt] == 2) {
  741. DomnValue = (DomnValue >> 1);
  742. }
  743. }
  744. DEBUG ((
  745. DEBUG_VERBOSE,
  746. "PatchOem3SsdtTable(): CpuIndex: 0x%x ThreadIndex: 0x%x CpuFixes: 0x%x (%d)\n",
  747. CpuIndex,
  748. ThreadIndex,
  749. CpuFixes,
  750. CpuFixes
  751. ));
  752. DEBUG ((
  753. DEBUG_INFO,
  754. "PatchOem3SsdtTable(): CpuSkt: %d CpuIndex: 0x%x, NcpuValue = 0x%x, DomnValue = 0x%x\n",
  755. CpuSkt,
  756. CpuIndex,
  757. mNcpuValue[CpuSkt],
  758. DomnValue
  759. ));
  760. ++CpuFixes;
  761. break;
  762. case SIGNATURE_32 ('T', 'S', 'D', 'C'):
  763. case SIGNATURE_32 ('T', 'S', 'D', 'D'):
  764. PsdPackage = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
  765. if (PsdPackage->StartByte != AML_NAME_OP) {
  766. continue;
  767. }
  768. PsdPackageItemPtr = (PSD_PACKAGE_LAYOUT *) ((UINT8 *) PsdPackage);
  769. DEBUG ((
  770. DEBUG_VERBOSE,
  771. "TSDC: PsdPackageItemPtr table: %x is detected...\n",
  772. PsdPackage->NameStr
  773. ));
  774. DEBUG ((
  775. DEBUG_VERBOSE,
  776. " Initial Values: Domain = %x, CoordType = %x, NumProcessors = %x\n",
  777. PsdPackageItemPtr->Domain,
  778. PsdPackageItemPtr->CoordType,
  779. PsdPackageItemPtr->NumProcessors
  780. ));
  781. PsdPackageItemPtr->Domain = DomnValue;
  782. PsdPackageItemPtr->NumProcessors = mNcpuValue[CpuSkt];
  783. DEBUG ((
  784. DEBUG_VERBOSE,
  785. " PsdPackage = %x, PsdPackageItemPtr = %x, SsdtPointer = %x\n",
  786. (UINT8 *)PsdPackage,
  787. (UINT8 *)PsdPackageItemPtr,
  788. (UINT8 *)SsdtPointer
  789. ));
  790. DEBUG ((
  791. DEBUG_VERBOSE,
  792. " Updated TSD Domain = %x, CoordType = %x, NumProcessors = %x\n",
  793. PsdPackageItemPtr->Domain,
  794. PsdPackageItemPtr->CoordType,
  795. PsdPackageItemPtr->NumProcessors
  796. ));
  797. break;
  798. default:
  799. break;
  800. } // switch
  801. } // for
  802. //
  803. // N fixes together currently
  804. //
  805. ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
  806. return EFI_SUCCESS;
  807. }
  808. /**
  809. Update the OEM4 C State SSDT table (CST)
  810. @param *TableHeader - The table to be set
  811. @retval EFI_SUCCESS - Returns Success
  812. **/
  813. EFI_STATUS
  814. PatchOem4SsdtTable (
  815. IN OUT EFI_ACPI_COMMON_HEADER *Table
  816. )
  817. {
  818. return EFI_SUCCESS;
  819. }