Cpu.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*++ @file
  2. Emu driver to produce CPU Architectural Protocol.
  3. Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
  4. Portions copyright (c) 2011 - 2012, Apple Inc. All rights reserved.
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "CpuDriver.h"
  8. UINT64 mTimerPeriod;
  9. CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {
  10. CPU_ARCH_PROT_PRIVATE_SIGNATURE,
  11. NULL,
  12. {
  13. EmuFlushCpuDataCache,
  14. EmuEnableInterrupt,
  15. EmuDisableInterrupt,
  16. EmuGetInterruptState,
  17. EmuInit,
  18. EmuRegisterInterruptHandler,
  19. EmuGetTimerValue,
  20. EmuSetMemoryAttributes,
  21. 0,
  22. 4
  23. },
  24. {
  25. {
  26. CpuMemoryServiceRead,
  27. CpuMemoryServiceWrite
  28. },
  29. {
  30. CpuIoServiceRead,
  31. CpuIoServiceWrite
  32. }
  33. },
  34. TRUE
  35. };
  36. #define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
  37. SMBIOS_TABLE_TYPE4 mCpuSmbiosType4 = {
  38. { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE4), 0 },
  39. 1, // Socket String
  40. ProcessorOther, // ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA.
  41. ProcessorFamilyOther, // ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY_DATA.
  42. 2, // ProcessorManufacture String;
  43. { // ProcessorId;
  44. { // PROCESSOR_SIGNATURE
  45. 0, // ProcessorSteppingId:4;
  46. 0, // ProcessorModel: 4;
  47. 0, // ProcessorFamily: 4;
  48. 0, // ProcessorType: 2;
  49. 0, // ProcessorReserved1: 2;
  50. 0, // ProcessorXModel: 4;
  51. 0, // ProcessorXFamily: 8;
  52. 0, // ProcessorReserved2: 4;
  53. },
  54. { // PROCESSOR_FEATURE_FLAGS
  55. 0, // ProcessorFpu :1;
  56. 0, // ProcessorVme :1;
  57. 0, // ProcessorDe :1;
  58. 0, // ProcessorPse :1;
  59. 0, // ProcessorTsc :1;
  60. 0, // ProcessorMsr :1;
  61. 0, // ProcessorPae :1;
  62. 0, // ProcessorMce :1;
  63. 0, // ProcessorCx8 :1;
  64. 0, // ProcessorApic :1;
  65. 0, // ProcessorReserved1 :1;
  66. 0, // ProcessorSep :1;
  67. 0, // ProcessorMtrr :1;
  68. 0, // ProcessorPge :1;
  69. 0, // ProcessorMca :1;
  70. 0, // ProcessorCmov :1;
  71. 0, // ProcessorPat :1;
  72. 0, // ProcessorPse36 :1;
  73. 0, // ProcessorPsn :1;
  74. 0, // ProcessorClfsh :1;
  75. 0, // ProcessorReserved2 :1;
  76. 0, // ProcessorDs :1;
  77. 0, // ProcessorAcpi :1;
  78. 0, // ProcessorMmx :1;
  79. 0, // ProcessorFxsr :1;
  80. 0, // ProcessorSse :1;
  81. 0, // ProcessorSse2 :1;
  82. 0, // ProcessorSs :1;
  83. 0, // ProcessorReserved3 :1;
  84. 0, // ProcessorTm :1;
  85. 0, // ProcessorReserved4 :2;
  86. }
  87. },
  88. 3, // ProcessorVersion String;
  89. { // Voltage;
  90. 1, // ProcessorVoltageCapability5V :1;
  91. 1, // ProcessorVoltageCapability3_3V :1;
  92. 1, // ProcessorVoltageCapability2_9V :1;
  93. 0, // ProcessorVoltageCapabilityReserved :1; ///< Bit 3, must be zero.
  94. 0, // ProcessorVoltageReserved :3; ///< Bits 4-6, must be zero.
  95. 0 // ProcessorVoltageIndicateLegacy :1;
  96. },
  97. 0, // ExternalClock;
  98. 0, // MaxSpeed;
  99. 0, // CurrentSpeed;
  100. 0x41, // Status;
  101. ProcessorUpgradeOther, // ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE.
  102. 0, // L1CacheHandle;
  103. 0, // L2CacheHandle;
  104. 0, // L3CacheHandle;
  105. 4, // SerialNumber;
  106. 5, // AssetTag;
  107. 6, // PartNumber;
  108. 0, // CoreCount;
  109. 0, // EnabledCoreCount;
  110. 0, // ThreadCount;
  111. 0, // ProcessorCharacteristics;
  112. 0, // ProcessorFamily2;
  113. };
  114. CHAR8 *mCpuSmbiosType4Strings[] = {
  115. "Socket",
  116. "http://www.tianocore.org/edk2/",
  117. "Emulated Processor",
  118. "1.0",
  119. "1.0",
  120. "1.0",
  121. NULL
  122. };
  123. /**
  124. Create SMBIOS record.
  125. Converts a fixed SMBIOS structure and an array of pointers to strings into
  126. an SMBIOS record where the strings are cat'ed on the end of the fixed record
  127. and terminated via a double NULL and add to SMBIOS table.
  128. SMBIOS_TABLE_TYPE32 gSmbiosType12 = {
  129. { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },
  130. 1 // StringCount
  131. };
  132. CHAR8 *gSmbiosType12Strings[] = {
  133. "Not Found",
  134. NULL
  135. };
  136. ...
  137. LogSmbiosData (
  138. (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12,
  139. gSmbiosType12Strings
  140. );
  141. @param Template Fixed SMBIOS structure, required.
  142. @param StringArray Array of strings to convert to an SMBIOS string pack.
  143. NULL is OK.
  144. **/
  145. EFI_STATUS
  146. LogSmbiosData (
  147. IN EFI_SMBIOS_TABLE_HEADER *Template,
  148. IN CHAR8 **StringPack
  149. )
  150. {
  151. EFI_STATUS Status;
  152. EFI_SMBIOS_PROTOCOL *Smbios;
  153. EFI_SMBIOS_HANDLE SmbiosHandle;
  154. EFI_SMBIOS_TABLE_HEADER *Record;
  155. UINTN Index;
  156. UINTN StringSize;
  157. UINTN Size;
  158. CHAR8 *Str;
  159. //
  160. // Locate Smbios protocol.
  161. //
  162. Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
  163. if (EFI_ERROR (Status)) {
  164. return Status;
  165. }
  166. // Calculate the size of the fixed record and optional string pack
  167. Size = Template->Length;
  168. if (StringPack == NULL) {
  169. // At least a double null is required
  170. Size += 2;
  171. } else {
  172. for (Index = 0; StringPack[Index] != NULL; Index++) {
  173. StringSize = AsciiStrSize (StringPack[Index]);
  174. Size += StringSize;
  175. }
  176. if (StringPack[0] == NULL) {
  177. // At least a double null is required
  178. Size += 1;
  179. }
  180. // Don't forget the terminating double null
  181. Size += 1;
  182. }
  183. // Copy over Template
  184. Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size);
  185. if (Record == NULL) {
  186. return EFI_OUT_OF_RESOURCES;
  187. }
  188. CopyMem (Record, Template, Template->Length);
  189. // Append string pack
  190. Str = ((CHAR8 *)Record) + Record->Length;
  191. for (Index = 0; StringPack[Index] != NULL; Index++) {
  192. StringSize = AsciiStrSize (StringPack[Index]);
  193. CopyMem (Str, StringPack[Index], StringSize);
  194. Str += StringSize;
  195. }
  196. *Str = 0;
  197. SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  198. Status = Smbios->Add (
  199. Smbios,
  200. gImageHandle,
  201. &SmbiosHandle,
  202. Record
  203. );
  204. ASSERT_EFI_ERROR (Status);
  205. FreePool (Record);
  206. return Status;
  207. }
  208. VOID
  209. CpuUpdateSmbios (
  210. IN UINTN MaxCpus
  211. )
  212. {
  213. mCpuSmbiosType4.CoreCount = (UINT8)MaxCpus;
  214. mCpuSmbiosType4.EnabledCoreCount = (UINT8)MaxCpus;
  215. mCpuSmbiosType4.ThreadCount = (UINT8)MaxCpus;
  216. //
  217. // The value of 1234 is fake value for CPU frequency
  218. //
  219. mCpuSmbiosType4.CurrentSpeed = 1234;
  220. LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mCpuSmbiosType4, mCpuSmbiosType4Strings);
  221. }
  222. //
  223. // Service routines for the driver
  224. //
  225. EFI_STATUS
  226. EFIAPI
  227. EmuFlushCpuDataCache (
  228. IN EFI_CPU_ARCH_PROTOCOL *This,
  229. IN EFI_PHYSICAL_ADDRESS Start,
  230. IN UINT64 Length,
  231. IN EFI_CPU_FLUSH_TYPE FlushType
  232. )
  233. {
  234. if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
  235. //
  236. // Only WB flush is supported. We actually need do nothing on Emu emulator
  237. // environment. Classify this to follow EFI spec
  238. //
  239. return EFI_SUCCESS;
  240. }
  241. //
  242. // Other flush types are not supported by Emu emulator
  243. //
  244. return EFI_UNSUPPORTED;
  245. }
  246. EFI_STATUS
  247. EFIAPI
  248. EmuEnableInterrupt (
  249. IN EFI_CPU_ARCH_PROTOCOL *This
  250. )
  251. {
  252. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  253. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  254. Private->InterruptState = TRUE;
  255. gEmuThunk->EnableInterrupt ();
  256. return EFI_SUCCESS;
  257. }
  258. EFI_STATUS
  259. EFIAPI
  260. EmuDisableInterrupt (
  261. IN EFI_CPU_ARCH_PROTOCOL *This
  262. )
  263. {
  264. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  265. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  266. Private->InterruptState = FALSE;
  267. gEmuThunk->DisableInterrupt ();
  268. return EFI_SUCCESS;
  269. }
  270. EFI_STATUS
  271. EFIAPI
  272. EmuGetInterruptState (
  273. IN EFI_CPU_ARCH_PROTOCOL *This,
  274. OUT BOOLEAN *State
  275. )
  276. {
  277. CPU_ARCH_PROTOCOL_PRIVATE *Private;
  278. if (State == NULL) {
  279. return EFI_INVALID_PARAMETER;
  280. }
  281. Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  282. *State = Private->InterruptState;
  283. return EFI_SUCCESS;
  284. }
  285. EFI_STATUS
  286. EFIAPI
  287. EmuInit (
  288. IN EFI_CPU_ARCH_PROTOCOL *This,
  289. IN EFI_CPU_INIT_TYPE InitType
  290. )
  291. {
  292. return EFI_UNSUPPORTED;
  293. }
  294. EFI_STATUS
  295. EFIAPI
  296. EmuRegisterInterruptHandler (
  297. IN EFI_CPU_ARCH_PROTOCOL *This,
  298. IN EFI_EXCEPTION_TYPE InterruptType,
  299. IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
  300. )
  301. {
  302. //
  303. // Do parameter checking for EFI spec conformance
  304. //
  305. if ((InterruptType < 0) || (InterruptType > 0xff)) {
  306. return EFI_UNSUPPORTED;
  307. }
  308. //
  309. // Do nothing for Emu emulation
  310. //
  311. return EFI_UNSUPPORTED;
  312. }
  313. EFI_STATUS
  314. EFIAPI
  315. EmuGetTimerValue (
  316. IN EFI_CPU_ARCH_PROTOCOL *This,
  317. IN UINT32 TimerIndex,
  318. OUT UINT64 *TimerValue,
  319. OUT UINT64 *TimerPeriod OPTIONAL
  320. )
  321. {
  322. if (TimerValue == NULL) {
  323. return EFI_INVALID_PARAMETER;
  324. }
  325. if (TimerIndex != 0) {
  326. return EFI_INVALID_PARAMETER;
  327. }
  328. *TimerValue = gEmuThunk->QueryPerformanceCounter ();
  329. if (TimerPeriod != NULL) {
  330. *TimerPeriod = mTimerPeriod;
  331. }
  332. return EFI_SUCCESS;
  333. }
  334. EFI_STATUS
  335. EFIAPI
  336. EmuSetMemoryAttributes (
  337. IN EFI_CPU_ARCH_PROTOCOL *This,
  338. IN EFI_PHYSICAL_ADDRESS BaseAddress,
  339. IN UINT64 Length,
  340. IN UINT64 Attributes
  341. )
  342. {
  343. //
  344. // Check for invalid parameter for Spec conformance
  345. //
  346. if (Length == 0) {
  347. return EFI_INVALID_PARAMETER;
  348. }
  349. //
  350. // Do nothing for Nt32 emulation
  351. //
  352. return EFI_UNSUPPORTED;
  353. }
  354. /**
  355. Callback function for idle events.
  356. @param Event Event whose notification function is being invoked.
  357. @param Context The pointer to the notification function's context,
  358. which is implementation-dependent.
  359. **/
  360. VOID
  361. EFIAPI
  362. IdleLoopEventCallback (
  363. IN EFI_EVENT Event,
  364. IN VOID *Context
  365. )
  366. {
  367. gEmuThunk->CpuSleep ();
  368. }
  369. EFI_STATUS
  370. EFIAPI
  371. InitializeCpu (
  372. IN EFI_HANDLE ImageHandle,
  373. IN EFI_SYSTEM_TABLE *SystemTable
  374. )
  375. {
  376. EFI_STATUS Status;
  377. UINT64 Frequency;
  378. EFI_EVENT IdleLoopEvent;
  379. UINTN MaxCpu;
  380. //
  381. // Retrieve the frequency of the performance counter in Hz.
  382. //
  383. Frequency = gEmuThunk->QueryPerformanceFrequency ();
  384. //
  385. // Convert frequency in Hz to a clock period in femtoseconds.
  386. //
  387. mTimerPeriod = DivU64x64Remainder (1000000000000000ULL, Frequency, NULL);
  388. CpuMpServicesInit (&MaxCpu);
  389. CpuUpdateSmbios (MaxCpu);
  390. Status = gBS->CreateEventEx (
  391. EVT_NOTIFY_SIGNAL,
  392. TPL_NOTIFY,
  393. IdleLoopEventCallback,
  394. NULL,
  395. &gIdleLoopEventGuid,
  396. &IdleLoopEvent
  397. );
  398. ASSERT_EFI_ERROR (Status);
  399. Status = gBS->InstallMultipleProtocolInterfaces (
  400. &mCpuTemplate.Handle,
  401. &gEfiCpuArchProtocolGuid,
  402. &mCpuTemplate.Cpu,
  403. &gEfiCpuIo2ProtocolGuid,
  404. &mCpuTemplate.CpuIo,
  405. NULL
  406. );
  407. ASSERT_EFI_ERROR (Status);
  408. return Status;
  409. }