]> git.proxmox.com Git - mirror_edk2.git/blame - InOsEmuPkg/CpuRuntimeDxe/Cpu.c
Add MP support. Based on PcdEmuApCount APs (Application Processors) are created in...
[mirror_edk2.git] / InOsEmuPkg / CpuRuntimeDxe / Cpu.c
CommitLineData
949f388f 1/*++ @file\r
2 Emu driver to produce CPU Architectural Protocol.\r
3 \r
4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
5Portions copyright (c) 2011, Apple Inc. All rights reserved.\r
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
50\r
51\r
52//\r
53// Service routines for the driver\r
54//\r
55EFI_STATUS\r
56EFIAPI\r
57EmuFlushCpuDataCache (\r
58 IN EFI_CPU_ARCH_PROTOCOL *This,\r
59 IN EFI_PHYSICAL_ADDRESS Start,\r
60 IN UINT64 Length,\r
61 IN EFI_CPU_FLUSH_TYPE FlushType\r
62 )\r
63{\r
64 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
65 //\r
66 // Only WB flush is supported. We actually need do nothing on Emu emulator\r
67 // environment. Classify this to follow EFI spec\r
68 //\r
69 return EFI_SUCCESS;\r
70 }\r
71 //\r
72 // Other flush types are not supported by Emu emulator\r
73 //\r
74 return EFI_UNSUPPORTED;\r
75}\r
76\r
77EFI_STATUS\r
78EFIAPI\r
79EmuEnableInterrupt (\r
80 IN EFI_CPU_ARCH_PROTOCOL *This\r
81 )\r
82{\r
83 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
84\r
85 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
86 Private->InterruptState = TRUE;\r
87 gEmuThunk->EnableInterrupt ();\r
88 return EFI_SUCCESS;\r
89}\r
90\r
91EFI_STATUS\r
92EFIAPI\r
93EmuDisableInterrupt (\r
94 IN EFI_CPU_ARCH_PROTOCOL *This\r
95 )\r
96{\r
97 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
98\r
99 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
100 Private->InterruptState = FALSE;\r
101 gEmuThunk->DisableInterrupt ();\r
102 return EFI_SUCCESS;\r
103}\r
104\r
105EFI_STATUS\r
106EFIAPI\r
107EmuGetInterruptState (\r
108 IN EFI_CPU_ARCH_PROTOCOL *This,\r
109 OUT BOOLEAN *State\r
110 )\r
111{\r
112 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
113\r
114 if (State == NULL) {\r
115 return EFI_INVALID_PARAMETER;\r
116 }\r
117\r
118 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
119 *State = Private->InterruptState;\r
120 return EFI_SUCCESS;\r
121}\r
122\r
123EFI_STATUS\r
124EFIAPI\r
125EmuInit (\r
126 IN EFI_CPU_ARCH_PROTOCOL *This,\r
127 IN EFI_CPU_INIT_TYPE InitType\r
128 )\r
129{\r
130 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
131\r
132 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
133 return EFI_UNSUPPORTED;\r
134}\r
135\r
136EFI_STATUS\r
137EFIAPI\r
138EmuRegisterInterruptHandler (\r
139 IN EFI_CPU_ARCH_PROTOCOL *This,\r
140 IN EFI_EXCEPTION_TYPE InterruptType,\r
141 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
142 )\r
143{\r
144 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
145\r
146 //\r
147 // Do parameter checking for EFI spec conformance\r
148 //\r
149 if (InterruptType < 0 || InterruptType > 0xff) {\r
150 return EFI_UNSUPPORTED;\r
151 }\r
152 //\r
153 // Do nothing for Emu emulation\r
154 //\r
155 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
156 return EFI_UNSUPPORTED;\r
157}\r
158\r
159EFI_STATUS\r
160EFIAPI\r
161EmuGetTimerValue (\r
162 IN EFI_CPU_ARCH_PROTOCOL *This,\r
163 IN UINT32 TimerIndex,\r
164 OUT UINT64 *TimerValue,\r
165 OUT UINT64 *TimerPeriod OPTIONAL\r
166 )\r
167{\r
168 if (TimerValue == NULL) {\r
169 return EFI_INVALID_PARAMETER;\r
170 }\r
171\r
172 if (TimerIndex != 0) {\r
173 return EFI_INVALID_PARAMETER;\r
174 }\r
175 \r
176 *TimerValue = gEmuThunk->QueryPerformanceCounter ();\r
177 \r
178 if (TimerPeriod != NULL) {\r
179 *TimerPeriod = mTimerPeriod;\r
180 } \r
181\r
182 return EFI_SUCCESS;\r
183}\r
184\r
185\r
186EFI_STATUS\r
187EFIAPI\r
188EmuSetMemoryAttributes (\r
189 IN EFI_CPU_ARCH_PROTOCOL *This,\r
190 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
191 IN UINT64 Length,\r
192 IN UINT64 Attributes\r
193 )\r
194{\r
195 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
196\r
197 //\r
198 // Check for invalid parameter for Spec conformance\r
199 //\r
200 if (Length == 0) {\r
201 return EFI_INVALID_PARAMETER;\r
202 }\r
203\r
204 //\r
205 // Do nothing for Nt32 emulation\r
206 //\r
207 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
208 return EFI_UNSUPPORTED;\r
209}\r
210\r
211\r
212\r
213/**\r
214 Logs SMBIOS record.\r
215\r
216 @param Smbios Pointer to SMBIOS protocol instance.\r
217 @param Buffer Pointer to the data buffer.\r
218\r
219**/\r
220VOID\r
221LogSmbiosData (\r
222 IN EFI_SMBIOS_PROTOCOL *Smbios,\r
223 IN UINT8 *Buffer\r
224 )\r
225{\r
226 EFI_STATUS Status;\r
227 EFI_SMBIOS_HANDLE SmbiosHandle;\r
228 \r
229 SmbiosHandle = 0;\r
230 Status = Smbios->Add (\r
231 Smbios,\r
232 NULL,\r
233 &SmbiosHandle,\r
234 (EFI_SMBIOS_TABLE_HEADER*)Buffer\r
235 );\r
236 ASSERT_EFI_ERROR (Status);\r
237}\r
238\r
239VOID\r
240CpuUpdateSmbios (\r
241 VOID\r
242 )\r
243{\r
244 EFI_STATUS Status;\r
245 UINT32 TotalSize;\r
246 EFI_SMBIOS_PROTOCOL *Smbios;\r
247 EFI_HII_HANDLE HiiHandle;\r
248 STRING_REF Token;\r
249 UINTN CpuVerStrLen;\r
250 EFI_STRING CpuVerStr;\r
251 SMBIOS_TABLE_TYPE4 *SmbiosRecord;\r
252 CHAR8 *OptionalStrStart;\r
253\r
254 //\r
255 // Locate Smbios protocol.\r
256 //\r
257 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);\r
258 \r
259 if (EFI_ERROR (Status)) {\r
260 return;\r
261 }\r
262\r
263 //\r
264 // Initialize strings to HII database\r
265 //\r
266 HiiHandle = HiiAddPackages (\r
267 &gEfiCallerIdGuid,\r
268 NULL,\r
269 CpuStrings,\r
270 NULL\r
271 );\r
272 ASSERT (HiiHandle != NULL);\r
273\r
274 Token = STRING_TOKEN (STR_PROCESSOR_VERSION);\r
275 CpuVerStr = HiiGetPackageString(&gEfiCallerIdGuid, Token, NULL);\r
276 CpuVerStrLen = StrLen(CpuVerStr);\r
277 ASSERT (CpuVerStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
278\r
279 TotalSize = sizeof(SMBIOS_TABLE_TYPE4) + CpuVerStrLen + 1 + 1;\r
280 SmbiosRecord = AllocatePool(TotalSize);\r
281 ZeroMem(SmbiosRecord, TotalSize);\r
282\r
283 SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;\r
284 SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);\r
285 //\r
286 // Make handle chosen by smbios protocol.add automatically.\r
287 //\r
288 SmbiosRecord->Hdr.Handle = 0; \r
289 //\r
290 // Processor version is the 1st string.\r
291 //\r
292 SmbiosRecord->ProcessorVersion = 1;\r
293 //\r
294 // Store CPU frequency data record to data hub - It's an emulator so make up a value\r
295 //\r
296 SmbiosRecord->CurrentSpeed = 1234;\r
297\r
298 OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
299 UnicodeStrToAsciiStr(CpuVerStr, OptionalStrStart);\r
300\r
301 //\r
302 // Now we have got the full smbios record, call smbios protocol to add this record.\r
303 //\r
304 LogSmbiosData(Smbios, (UINT8 *) SmbiosRecord);\r
305 FreePool (SmbiosRecord);\r
306}\r
307\r
308EFI_STATUS\r
309EFIAPI\r
310InitializeCpu (\r
311 IN EFI_HANDLE ImageHandle,\r
312 IN EFI_SYSTEM_TABLE *SystemTable\r
313 )\r
314{\r
315 EFI_STATUS Status;\r
316 UINT64 Frequency;\r
317\r
318 //\r
319 // Retrieve the frequency of the performance counter in Hz.\r
320 // \r
321 Frequency = gEmuThunk->QueryPerformanceFrequency ();\r
322 \r
323 //\r
324 // Convert frequency in Hz to a clock period in femtoseconds.\r
325 //\r
326 mTimerPeriod = DivU64x64Remainder (1000000000000000, Frequency, NULL);\r
327\r
328 CpuUpdateSmbios ();\r
c4671a67 329 \r
330 CpuMpServicesInit ();\r
949f388f 331\r
332 Status = gBS->InstallMultipleProtocolInterfaces (\r
333 &mCpuTemplate.Handle,\r
334 &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,\r
335 &gEfiCpuIo2ProtocolGuid, &mCpuTemplate.CpuIo,\r
336 NULL\r
337 );\r
338 ASSERT_EFI_ERROR (Status);\r
339\r
340 return Status;\r
341}\r