]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c
UefiCpuPkg: Add CpuDxeRiscV64 module
[mirror_edk2.git] / UefiCpuPkg / CpuDxeRiscV64 / CpuDxe.c
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 //
16 STATIC BOOLEAN mInterruptState = FALSE;
17 STATIC EFI_HANDLE mCpuHandle = NULL;
18 STATIC UINTN mBootHartId;
19 RISCV_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 **/
32 EFI_STATUS
33 EFIAPI
34 RiscvGetBootHartId (
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
47 RISCV_EFI_BOOT_PROTOCOL gRiscvBootProtocol = {
48 RISCV_EFI_BOOT_PROTOCOL_LATEST_VERSION,
49 RiscvGetBootHartId
50 };
51
52 EFI_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 **/
84 EFI_STATUS
85 EFIAPI
86 CpuFlushCpuDataCache (
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 return EFI_SUCCESS;
94 }
95
96 /**
97 Enables CPU interrupts.
98
99 @param This Protocol instance structure
100
101 @retval EFI_SUCCESS If interrupts were enabled in the CPU
102 @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
103
104 **/
105 EFI_STATUS
106 EFIAPI
107 CpuEnableInterrupt (
108 IN EFI_CPU_ARCH_PROTOCOL *This
109 )
110 {
111 EnableInterrupts ();
112 mInterruptState = TRUE;
113 return EFI_SUCCESS;
114 }
115
116 /**
117 Disables CPU interrupts.
118
119 @param This Protocol instance structure
120
121 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
122 @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
123
124 **/
125 EFI_STATUS
126 EFIAPI
127 CpuDisableInterrupt (
128 IN EFI_CPU_ARCH_PROTOCOL *This
129 )
130 {
131 DisableInterrupts ();
132 mInterruptState = FALSE;
133 return EFI_SUCCESS;
134 }
135
136 /**
137 Return the state of interrupts.
138
139 @param This Protocol instance structure
140 @param State Pointer to the CPU's current interrupt state
141
142 @retval EFI_SUCCESS If interrupts were disabled in the CPU.
143 @retval EFI_INVALID_PARAMETER State is NULL.
144
145 **/
146 EFI_STATUS
147 EFIAPI
148 CpuGetInterruptState (
149 IN EFI_CPU_ARCH_PROTOCOL *This,
150 OUT BOOLEAN *State
151 )
152 {
153 if (State == NULL) {
154 return EFI_INVALID_PARAMETER;
155 }
156
157 *State = mInterruptState;
158 return EFI_SUCCESS;
159 }
160
161 /**
162 Generates an INIT to the CPU.
163
164 @param This Protocol instance structure
165 @param InitType Type of CPU INIT to perform
166
167 @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
168 seen.
169 @retval EFI_DEVICE_ERROR If CPU INIT failed.
170 @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
171
172 **/
173 EFI_STATUS
174 EFIAPI
175 CpuInit (
176 IN EFI_CPU_ARCH_PROTOCOL *This,
177 IN EFI_CPU_INIT_TYPE InitType
178 )
179 {
180 return EFI_UNSUPPORTED;
181 }
182
183 /**
184 Registers a function to be called from the CPU interrupt handler.
185
186 @param This Protocol instance structure
187 @param InterruptType Defines which interrupt to hook. IA-32
188 valid range is 0x00 through 0xFF
189 @param InterruptHandler A pointer to a function of type
190 EFI_CPU_INTERRUPT_HANDLER that is called
191 when a processor interrupt occurs. A null
192 pointer is an error condition.
193
194 @retval EFI_SUCCESS If handler installed or uninstalled.
195 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
196 for InterruptType was previously installed.
197 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
198 InterruptType was not previously installed.
199 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
200 is not supported.
201
202 **/
203 EFI_STATUS
204 EFIAPI
205 CpuRegisterInterruptHandler (
206 IN EFI_CPU_ARCH_PROTOCOL *This,
207 IN EFI_EXCEPTION_TYPE InterruptType,
208 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
209 )
210 {
211 return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
212 }
213
214 /**
215 Returns a timer value from one of the CPU's internal timers. There is no
216 inherent time interval between ticks but is a function of the CPU frequency.
217
218 @param This - Protocol instance structure.
219 @param TimerIndex - Specifies which CPU timer is requested.
220 @param TimerValue - Pointer to the returned timer value.
221 @param TimerPeriod - A pointer to the amount of time that passes
222 in femtoseconds (10-15) for each increment
223 of TimerValue. If TimerValue does not
224 increment at a predictable rate, then 0 is
225 returned. The amount of time that has
226 passed between two calls to GetTimerValue()
227 can be calculated with the formula
228 (TimerValue2 - TimerValue1) * TimerPeriod.
229 This parameter is optional and may be NULL.
230
231 @retval EFI_SUCCESS - If the CPU timer count was returned.
232 @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
233 @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
234 @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
235
236 **/
237 EFI_STATUS
238 EFIAPI
239 CpuGetTimerValue (
240 IN EFI_CPU_ARCH_PROTOCOL *This,
241 IN UINT32 TimerIndex,
242 OUT UINT64 *TimerValue,
243 OUT UINT64 *TimerPeriod OPTIONAL
244 )
245 {
246 if (TimerValue == NULL) {
247 return EFI_INVALID_PARAMETER;
248 }
249
250 if (TimerIndex != 0) {
251 return EFI_INVALID_PARAMETER;
252 }
253
254 *TimerValue = (UINT64)RiscVReadTimer ();
255 if (TimerPeriod != NULL) {
256 *TimerPeriod = DivU64x32 (
257 1000000000000000u,
258 PcdGet64 (PcdCpuCoreCrystalClockFrequency)
259 );
260 }
261
262 return EFI_SUCCESS;
263 }
264
265 /**
266 Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.
267
268 This function modifies the attributes for the memory region specified by BaseAddress and
269 Length from their current attributes to the attributes specified by Attributes.
270
271 @param This The EFI_CPU_ARCH_PROTOCOL instance.
272 @param BaseAddress The physical address that is the start address of a memory region.
273 @param Length The size in bytes of the memory region.
274 @param Attributes The bit mask of attributes to set for the memory region.
275
276 @retval EFI_SUCCESS The attributes were set for the memory region.
277 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
278 BaseAddress and Length cannot be modified.
279 @retval EFI_INVALID_PARAMETER Length is zero.
280 Attributes specified an illegal combination of attributes that
281 cannot be set together.
282 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
283 the memory resource range.
284 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
285 resource range specified by BaseAddress and Length.
286 The bit mask of attributes is not support for the memory resource
287 range specified by BaseAddress and Length.
288
289 **/
290 EFI_STATUS
291 EFIAPI
292 CpuSetMemoryAttributes (
293 IN EFI_CPU_ARCH_PROTOCOL *This,
294 IN EFI_PHYSICAL_ADDRESS BaseAddress,
295 IN UINT64 Length,
296 IN UINT64 Attributes
297 )
298 {
299 DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __FUNCTION__));
300 return EFI_SUCCESS;
301 }
302
303 /**
304 Initialize the state information for the CPU Architectural Protocol.
305
306 @param ImageHandle Image handle this driver.
307 @param SystemTable Pointer to the System Table.
308
309 @retval EFI_SUCCESS Thread can be successfully created
310 @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
311 @retval EFI_DEVICE_ERROR Cannot create the thread
312
313 **/
314 EFI_STATUS
315 EFIAPI
316 InitializeCpu (
317 IN EFI_HANDLE ImageHandle,
318 IN EFI_SYSTEM_TABLE *SystemTable
319 )
320 {
321 EFI_STATUS Status;
322 EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
323
324 GetFirmwareContextPointer (&FirmwareContext);
325 ASSERT (FirmwareContext != NULL);
326 if (FirmwareContext == NULL) {
327 DEBUG ((DEBUG_ERROR, "Failed to get the pointer of EFI_RISCV_FIRMWARE_CONTEXT\n"));
328 return EFI_NOT_FOUND;
329 }
330
331 DEBUG ((DEBUG_INFO, " %a: Firmware Context is at 0x%x.\n", __FUNCTION__, FirmwareContext));
332
333 mBootHartId = FirmwareContext->BootHartId;
334 DEBUG ((DEBUG_INFO, " %a: mBootHartId = 0x%x.\n", __FUNCTION__, mBootHartId));
335
336 InitializeCpuExceptionHandlers (NULL);
337
338 //
339 // Make sure interrupts are disabled
340 //
341 DisableInterrupts ();
342
343 //
344 // Install Boot protocol
345 //
346 Status = gBS->InstallProtocolInterface (
347 &ImageHandle,
348 &gRiscVEfiBootProtocolGuid,
349 EFI_NATIVE_INTERFACE,
350 &gRiscvBootProtocol
351 );
352 ASSERT_EFI_ERROR (Status);
353
354 //
355 // Install CPU Architectural Protocol
356 //
357 Status = gBS->InstallMultipleProtocolInterfaces (
358 &mCpuHandle,
359 &gEfiCpuArchProtocolGuid,
360 &gCpu,
361 NULL
362 );
363 ASSERT_EFI_ERROR (Status);
364 return Status;
365 }