VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c@ 107365

Last change on this file since 107365 was 105670, checked in by vboxsync, 9 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • Property svn:eol-style set to native
File size: 11.4 KB
Line 
1/** @file
2 RISC-V CPU DXE driver.
3
4 Copyright (c) 2016 - 2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
5 Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9**/
10
11#include "CpuDxe.h"
12
13//
14// Global Variables
15//
16STATIC BOOLEAN mInterruptState = FALSE;
17STATIC EFI_HANDLE mCpuHandle = NULL;
18STATIC UINTN mBootHartId;
19RISCV_EFI_BOOT_PROTOCOL gRiscvBootProtocol;
20
21/**
22 Get the boot hartid
23
24 @param This Protocol instance structure
25 @param BootHartId Pointer to the Boot Hart ID variable
26
27 @retval EFI_SUCCESS If BootHartId is returned
28 @retval EFI_INVALID_PARAMETER Either "BootHartId" is NULL or "This" is not
29 a valid RISCV_EFI_BOOT_PROTOCOL instance.
30
31**/
32EFI_STATUS
33EFIAPI
34RiscvGetBootHartId (
35 IN RISCV_EFI_BOOT_PROTOCOL *This,
36 OUT UINTN *BootHartId
37 )
38{
39 if ((This != &gRiscvBootProtocol) || (BootHartId == NULL)) {
40 return EFI_INVALID_PARAMETER;
41 }
42
43 *BootHartId = mBootHartId;
44 return EFI_SUCCESS;
45}
46
47RISCV_EFI_BOOT_PROTOCOL gRiscvBootProtocol = {
48 RISCV_EFI_BOOT_PROTOCOL_LATEST_VERSION,
49 RiscvGetBootHartId
50};
51
52EFI_CPU_ARCH_PROTOCOL gCpu = {
53 CpuFlushCpuDataCache,
54 CpuEnableInterrupt,
55 CpuDisableInterrupt,
56 CpuGetInterruptState,
57 CpuInit,
58 CpuRegisterInterruptHandler,
59 CpuGetTimerValue,
60 CpuSetMemoryAttributes,
61 1, // NumberOfTimers
62 4 // DmaBufferAlignment
63};
64
65//
66// CPU Arch Protocol Functions
67//
68
69/**
70 Flush CPU data cache. If the instruction cache is fully coherent
71 with all DMA operations then function can just return EFI_SUCCESS.
72
73 @param This Protocol instance structure
74 @param Start Physical address to start flushing from.
75 @param Length Number of bytes to flush. Round up to chipset
76 granularity.
77 @param FlushType Specifies the type of flush operation to perform.
78
79 @retval EFI_SUCCESS If cache was flushed
80 @retval EFI_UNSUPPORTED If flush type is not supported.
81 @retval EFI_DEVICE_ERROR If requested range could not be flushed.
82
83**/
84EFI_STATUS
85EFIAPI
86CpuFlushCpuDataCache (
87 IN EFI_CPU_ARCH_PROTOCOL *This,
88 IN EFI_PHYSICAL_ADDRESS Start,
89 IN UINT64 Length,
90 IN EFI_CPU_FLUSH_TYPE FlushType
91 )
92{
93 switch (FlushType) {
94 case EfiCpuFlushTypeWriteBack:
95 WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
96 break;
97 case EfiCpuFlushTypeInvalidate:
98 InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
99 break;
100 case EfiCpuFlushTypeWriteBackInvalidate:
101 WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
102 break;
103 default:
104 return EFI_INVALID_PARAMETER;
105 }
106
107 return EFI_SUCCESS;
108}
109
110/**
111 Enables CPU interrupts.
112
113 @param This Protocol instance structure
114
115 @retval EFI_SUCCESS If interrupts were enabled in the CPU
116 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
117
118**/
119EFI_STATUS
120EFIAPI
121CpuEnableInterrupt (
122 IN EFI_CPU_ARCH_PROTOCOL *This
123 )
124{
125 EnableInterrupts ();
126 mInterruptState = TRUE;
127 return EFI_SUCCESS;
128}
129
130/**
131 Disables CPU interrupts.
132
133 @param This Protocol instance structure
134
135 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
136 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
137
138**/
139EFI_STATUS
140EFIAPI
141CpuDisableInterrupt (
142 IN EFI_CPU_ARCH_PROTOCOL *This
143 )
144{
145 DisableInterrupts ();
146 mInterruptState = FALSE;
147 return EFI_SUCCESS;
148}
149
150/**
151 Return the state of interrupts.
152
153 @param This Protocol instance structure
154 @param State Pointer to the CPU's current interrupt state
155
156 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
157 @retval EFI_INVALID_PARAMETER State is NULL.
158
159**/
160EFI_STATUS
161EFIAPI
162CpuGetInterruptState (
163 IN EFI_CPU_ARCH_PROTOCOL *This,
164 OUT BOOLEAN *State
165 )
166{
167 if (State == NULL) {
168 return EFI_INVALID_PARAMETER;
169 }
170
171 *State = mInterruptState;
172 return EFI_SUCCESS;
173}
174
175/**
176 Generates an INIT to the CPU.
177
178 @param This Protocol instance structure
179 @param InitType Type of CPU INIT to perform
180
181 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
182 seen.
183 @retval EFI_DEVICE_ERROR If CPU INIT failed.
184 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
185
186**/
187EFI_STATUS
188EFIAPI
189CpuInit (
190 IN EFI_CPU_ARCH_PROTOCOL *This,
191 IN EFI_CPU_INIT_TYPE InitType
192 )
193{
194 return EFI_UNSUPPORTED;
195}
196
197/**
198 Registers a function to be called from the CPU interrupt handler.
199
200 @param This Protocol instance structure
201 @param InterruptType Defines which interrupt to hook. IA-32
202 valid range is 0x00 through 0xFF
203 @param InterruptHandler A pointer to a function of type
204 EFI_CPU_INTERRUPT_HANDLER that is called
205 when a processor interrupt occurs. A null
206 pointer is an error condition.
207
208 @retval EFI_SUCCESS If handler installed or uninstalled.
209 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
210 for InterruptType was previously installed.
211 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
212 InterruptType was not previously installed.
213 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
214 is not supported.
215
216**/
217EFI_STATUS
218EFIAPI
219CpuRegisterInterruptHandler (
220 IN EFI_CPU_ARCH_PROTOCOL *This,
221 IN EFI_EXCEPTION_TYPE InterruptType,
222 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
223 )
224{
225 return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
226}
227
228/**
229 Returns a timer value from one of the CPU's internal timers. There is no
230 inherent time interval between ticks but is a function of the CPU frequency.
231
232 @param This - Protocol instance structure.
233 @param TimerIndex - Specifies which CPU timer is requested.
234 @param TimerValue - Pointer to the returned timer value.
235 @param TimerPeriod - A pointer to the amount of time that passes
236 in femtoseconds (10-15) for each increment
237 of TimerValue. If TimerValue does not
238 increment at a predictable rate, then 0 is
239 returned. The amount of time that has
240 passed between two calls to GetTimerValue()
241 can be calculated with the formula
242 (TimerValue2 - TimerValue1) * TimerPeriod.
243 This parameter is optional and may be NULL.
244
245 @retval EFI_SUCCESS - If the CPU timer count was returned.
246 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
247 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
248 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
249
250**/
251EFI_STATUS
252EFIAPI
253CpuGetTimerValue (
254 IN EFI_CPU_ARCH_PROTOCOL *This,
255 IN UINT32 TimerIndex,
256 OUT UINT64 *TimerValue,
257 OUT UINT64 *TimerPeriod OPTIONAL
258 )
259{
260 if (TimerValue == NULL) {
261 return EFI_INVALID_PARAMETER;
262 }
263
264 if (TimerIndex != 0) {
265 return EFI_INVALID_PARAMETER;
266 }
267
268 *TimerValue = (UINT64)RiscVReadTimer ();
269 if (TimerPeriod != NULL) {
270 *TimerPeriod = DivU64x32 (
271 1000000000000000u,
272 PcdGet64 (PcdCpuCoreCrystalClockFrequency)
273 );
274 }
275
276 return EFI_SUCCESS;
277}
278
279/**
280 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
281
282 This function modifies the attributes for the memory region specified by BaseAddress and
283 Length from their current attributes to the attributes specified by Attributes.
284
285 @param This The EFI_CPU_ARCH_PROTOCOL instance.
286 @param BaseAddress The physical address that is the start address of a memory region.
287 @param Length The size in bytes of the memory region.
288 @param Attributes The bit mask of attributes to set for the memory region.
289
290 @retval EFI_SUCCESS The attributes were set for the memory region.
291 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
292 BaseAddress and Length cannot be modified.
293 @retval EFI_INVALID_PARAMETER Length is zero.
294 Attributes specified an illegal combination of attributes that
295 cannot be set together.
296 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
297 the memory resource range.
298 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
299 resource range specified by BaseAddress and Length.
300 The bit mask of attributes is not support for the memory resource
301 range specified by BaseAddress and Length.
302
303**/
304EFI_STATUS
305EFIAPI
306CpuSetMemoryAttributes (
307 IN EFI_CPU_ARCH_PROTOCOL *This,
308 IN EFI_PHYSICAL_ADDRESS BaseAddress,
309 IN UINT64 Length,
310 IN UINT64 Attributes
311 )
312{
313 return RiscVSetMemoryAttributes (BaseAddress, Length, Attributes);
314}
315
316/**
317 Initialize the state information for the CPU Architectural Protocol.
318
319 @param ImageHandle Image handle this driver.
320 @param SystemTable Pointer to the System Table.
321
322 @retval EFI_SUCCESS Thread can be successfully created
323 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
324 @retval EFI_DEVICE_ERROR Cannot create the thread
325
326**/
327EFI_STATUS
328EFIAPI
329InitializeCpu (
330 IN EFI_HANDLE ImageHandle,
331 IN EFI_SYSTEM_TABLE *SystemTable
332 )
333{
334 EFI_STATUS Status;
335 EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
336
337 GetFirmwareContextPointer (&FirmwareContext);
338 ASSERT (FirmwareContext != NULL);
339 if (FirmwareContext == NULL) {
340 DEBUG ((DEBUG_ERROR, "Failed to get the pointer of EFI_RISCV_FIRMWARE_CONTEXT\n"));
341 return EFI_NOT_FOUND;
342 }
343
344 DEBUG ((DEBUG_INFO, " %a: Firmware Context is at 0x%x.\n", __func__, FirmwareContext));
345
346 mBootHartId = FirmwareContext->BootHartId;
347 DEBUG ((DEBUG_INFO, " %a: mBootHartId = 0x%x.\n", __func__, mBootHartId));
348
349 InitializeCpuExceptionHandlers (NULL);
350
351 //
352 // Make sure interrupts are disabled
353 //
354 DisableInterrupts ();
355
356 //
357 // Enable MMU
358 //
359 Status = RiscVConfigureMmu ();
360 ASSERT_EFI_ERROR (Status);
361
362 //
363 // Install Boot protocol
364 //
365 Status = gBS->InstallProtocolInterface (
366 &ImageHandle,
367 &gRiscVEfiBootProtocolGuid,
368 EFI_NATIVE_INTERFACE,
369 &gRiscvBootProtocol
370 );
371 ASSERT_EFI_ERROR (Status);
372
373 //
374 // Install CPU Architectural Protocol
375 //
376 Status = gBS->InstallMultipleProtocolInterfaces (
377 &mCpuHandle,
378 &gEfiCpuArchProtocolGuid,
379 &gCpu,
380 NULL
381 );
382 ASSERT_EFI_ERROR (Status);
383 return Status;
384}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette