]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/CpuRuntimeDxe/Cpu.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
a550d468 14CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {\r
949f388f 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
a550d468 42#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100\r
949f388f 43\r
a550d468
MK
44SMBIOS_TABLE_TYPE4 mCpuSmbiosType4 = {\r
45 { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE4), 0 },\r
a0af6b27 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
a550d468 51 { // PROCESSOR_SIGNATURE\r
a0af6b27 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
a550d468 61 { // PROCESSOR_FEATURE_FLAGS\r
a0af6b27 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
a550d468 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
a550d468 122CHAR8 *mCpuSmbiosType4Strings[] = {\r
a0af6b27 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
a0af6b27 132/**\r
b02127ec 133 Create SMBIOS record.\r
134\r
135 Converts a fixed SMBIOS structure and an array of pointers to strings into\r
136 an SMBIOS record where the strings are cat'ed on the end of the fixed record\r
137 and terminated via a double NULL and add to SMBIOS table.\r
138\r
139 SMBIOS_TABLE_TYPE32 gSmbiosType12 = {\r
140 { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },\r
141 1 // StringCount\r
142 };\r
143 CHAR8 *gSmbiosType12Strings[] = {\r
144 "Not Found",\r
145 NULL\r
146 };\r
79e4f2a5 147\r
b02127ec 148 ...\r
149 LogSmbiosData (\r
79e4f2a5 150 (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12,\r
b02127ec 151 gSmbiosType12Strings\r
152 );\r
a0af6b27 153\r
b02127ec 154 @param Template Fixed SMBIOS structure, required.\r
79e4f2a5 155 @param StringArray Array of strings to convert to an SMBIOS string pack.\r
b02127ec 156 NULL is OK.\r
a0af6b27 157\r
158**/\r
159EFI_STATUS\r
160LogSmbiosData (\r
a550d468
MK
161 IN EFI_SMBIOS_TABLE_HEADER *Template,\r
162 IN CHAR8 **StringPack\r
a0af6b27 163 )\r
164{\r
a550d468
MK
165 EFI_STATUS Status;\r
166 EFI_SMBIOS_PROTOCOL *Smbios;\r
167 EFI_SMBIOS_HANDLE SmbiosHandle;\r
168 EFI_SMBIOS_TABLE_HEADER *Record;\r
169 UINTN Index;\r
170 UINTN StringSize;\r
171 UINTN Size;\r
172 CHAR8 *Str;\r
a0af6b27 173\r
174 //\r
175 // Locate Smbios protocol.\r
176 //\r
177 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);\r
178 if (EFI_ERROR (Status)) {\r
179 return Status;\r
180 }\r
181\r
182 // Calculate the size of the fixed record and optional string pack\r
183 Size = Template->Length;\r
b02127ec 184 if (StringPack == NULL) {\r
185 // At least a double null is required\r
186 Size += 2;\r
187 } else {\r
188 for (Index = 0; StringPack[Index] != NULL; Index++) {\r
189 StringSize = AsciiStrSize (StringPack[Index]);\r
a550d468 190 Size += StringSize;\r
b02127ec 191 }\r
a550d468 192\r
b02127ec 193 if (StringPack[0] == NULL) {\r
194 // At least a double null is required\r
195 Size += 1;\r
196 }\r
a550d468 197\r
b02127ec 198 // Don't forget the terminating double null\r
199 Size += 1;\r
a0af6b27 200 }\r
a0af6b27 201\r
202 // Copy over Template\r
203 Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size);\r
204 if (Record == NULL) {\r
205 return EFI_OUT_OF_RESOURCES;\r
206 }\r
a550d468 207\r
a0af6b27 208 CopyMem (Record, Template, Template->Length);\r
209\r
210 // Append string pack\r
211 Str = ((CHAR8 *)Record) + Record->Length;\r
212 for (Index = 0; StringPack[Index] != NULL; Index++) {\r
213 StringSize = AsciiStrSize (StringPack[Index]);\r
214 CopyMem (Str, StringPack[Index], StringSize);\r
215 Str += StringSize;\r
216 }\r
a550d468 217\r
a0af6b27 218 *Str = 0;\r
79e4f2a5 219\r
a0af6b27 220 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
a550d468
MK
221 Status = Smbios->Add (\r
222 Smbios,\r
223 gImageHandle,\r
224 &SmbiosHandle,\r
225 Record\r
226 );\r
a0af6b27 227 ASSERT_EFI_ERROR (Status);\r
79e4f2a5 228\r
a0af6b27 229 FreePool (Record);\r
230 return Status;\r
231}\r
232\r
a0af6b27 233VOID\r
234CpuUpdateSmbios (\r
235 IN UINTN MaxCpus\r
236 )\r
237{\r
a550d468
MK
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
949f388f 248//\r
249// Service routines for the driver\r
250//\r
251EFI_STATUS\r
252EFIAPI\r
253EmuFlushCpuDataCache (\r
254 IN EFI_CPU_ARCH_PROTOCOL *This,\r
255 IN EFI_PHYSICAL_ADDRESS Start,\r
256 IN UINT64 Length,\r
257 IN EFI_CPU_FLUSH_TYPE FlushType\r
258 )\r
259{\r
260 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
261 //\r
262 // Only WB flush is supported. We actually need do nothing on Emu emulator\r
263 // environment. Classify this to follow EFI spec\r
264 //\r
265 return EFI_SUCCESS;\r
266 }\r
a550d468 267\r
949f388f 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
a550d468 280 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
949f388f 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
a550d468 294 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
949f388f 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
a550d468 309 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
949f388f 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
a550d468 341 if ((InterruptType < 0) || (InterruptType > 0xff)) {\r
949f388f 342 return EFI_UNSUPPORTED;\r
343 }\r
a550d468 344\r
949f388f 345 //\r
346 // Do nothing for Emu emulation\r
347 //\r
949f388f 348 return EFI_UNSUPPORTED;\r
349}\r
350\r
351EFI_STATUS\r
352EFIAPI\r
353EmuGetTimerValue (\r
a550d468
MK
354 IN EFI_CPU_ARCH_PROTOCOL *This,\r
355 IN UINT32 TimerIndex,\r
356 OUT UINT64 *TimerValue,\r
357 OUT UINT64 *TimerPeriod OPTIONAL\r
949f388f 358 )\r
359{\r
360 if (TimerValue == NULL) {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363\r
364 if (TimerIndex != 0) {\r
365 return EFI_INVALID_PARAMETER;\r
366 }\r
d18d8a1d 367\r
949f388f 368 *TimerValue = gEmuThunk->QueryPerformanceCounter ();\r
d18d8a1d 369\r
949f388f 370 if (TimerPeriod != NULL) {\r
371 *TimerPeriod = mTimerPeriod;\r
d18d8a1d 372 }\r
949f388f 373\r
374 return EFI_SUCCESS;\r
375}\r
376\r
949f388f 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
57c7d70f 399/**\r
400 Callback function for idle events.\r
d18d8a1d 401\r
57c7d70f 402 @param Event Event whose notification function is being invoked.\r
403 @param Context The pointer to the notification function's context,\r
404 which is implementation-dependent.\r
405\r
406**/\r
407VOID\r
408EFIAPI\r
409IdleLoopEventCallback (\r
a550d468
MK
410 IN EFI_EVENT Event,\r
411 IN VOID *Context\r
57c7d70f 412 )\r
413{\r
414 gEmuThunk->CpuSleep ();\r
415}\r
416\r
949f388f 417EFI_STATUS\r
418EFIAPI\r
419InitializeCpu (\r
420 IN EFI_HANDLE ImageHandle,\r
421 IN EFI_SYSTEM_TABLE *SystemTable\r
422 )\r
423{\r
a550d468
MK
424 EFI_STATUS Status;\r
425 UINT64 Frequency;\r
426 EFI_EVENT IdleLoopEvent;\r
427 UINTN MaxCpu;\r
949f388f 428\r
429 //\r
430 // Retrieve the frequency of the performance counter in Hz.\r
d18d8a1d 431 //\r
949f388f 432 Frequency = gEmuThunk->QueryPerformanceFrequency ();\r
d18d8a1d 433\r
949f388f 434 //\r
435 // Convert frequency in Hz to a clock period in femtoseconds.\r
436 //\r
7e284acb 437 mTimerPeriod = DivU64x64Remainder (1000000000000000ULL, Frequency, NULL);\r
949f388f 438\r
a0af6b27 439 CpuMpServicesInit (&MaxCpu);\r
440\r
441 CpuUpdateSmbios (MaxCpu);\r
d18d8a1d 442\r
57c7d70f 443 Status = gBS->CreateEventEx (\r
444 EVT_NOTIFY_SIGNAL,\r
445 TPL_NOTIFY,\r
446 IdleLoopEventCallback,\r
447 NULL,\r
448 &gIdleLoopEventGuid,\r
449 &IdleLoopEvent\r
450 );\r
451 ASSERT_EFI_ERROR (Status);\r
452\r
949f388f 453 Status = gBS->InstallMultipleProtocolInterfaces (\r
454 &mCpuTemplate.Handle,\r
a550d468
MK
455 &gEfiCpuArchProtocolGuid,\r
456 &mCpuTemplate.Cpu,\r
457 &gEfiCpuIo2ProtocolGuid,\r
458 &mCpuTemplate.CpuIo,\r
949f388f 459 NULL\r
460 );\r
461 ASSERT_EFI_ERROR (Status);\r
462\r
463 return Status;\r
464}\r