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