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