]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/CpuDxe/CpuDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / CpuDxe.c
1 /** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2011, ARM Limited. All rights reserved.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "CpuDxe.h"
11
12 #include <Guid/IdleLoopEvent.h>
13
14 BOOLEAN mIsFlushingGCD;
15
16 /**
17 This function flushes the range of addresses from Start to Start+Length
18 from the processor's data cache. If Start is not aligned to a cache line
19 boundary, then the bytes before Start to the preceding cache line boundary
20 are also flushed. If Start+Length is not aligned to a cache line boundary,
21 then the bytes past Start+Length to the end of the next cache line boundary
22 are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
23 supported. If the data cache is fully coherent with all DMA operations, then
24 this function can just return EFI_SUCCESS. If the processor does not support
25 flushing a range of the data cache, then the entire data cache can be flushed.
26
27 @param This The EFI_CPU_ARCH_PROTOCOL instance.
28 @param Start The beginning physical address to flush from the processor's data
29 cache.
30 @param Length The number of bytes to flush from the processor's data cache. This
31 function may flush more bytes than Length specifies depending upon
32 the granularity of the flush operation that the processor supports.
33 @param FlushType Specifies the type of flush operation to perform.
34
35 @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
36 the processor's data cache.
37 @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
38 by FlushType.
39 @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
40 from the processor's data cache.
41
42 **/
43 EFI_STATUS
44 EFIAPI
45 CpuFlushCpuDataCache (
46 IN EFI_CPU_ARCH_PROTOCOL *This,
47 IN EFI_PHYSICAL_ADDRESS Start,
48 IN UINT64 Length,
49 IN EFI_CPU_FLUSH_TYPE FlushType
50 )
51 {
52 switch (FlushType) {
53 case EfiCpuFlushTypeWriteBack:
54 WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
55 break;
56 case EfiCpuFlushTypeInvalidate:
57 InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
58 break;
59 case EfiCpuFlushTypeWriteBackInvalidate:
60 WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
61 break;
62 default:
63 return EFI_INVALID_PARAMETER;
64 }
65
66 return EFI_SUCCESS;
67 }
68
69 /**
70 This function enables interrupt processing by the processor.
71
72 @param This The EFI_CPU_ARCH_PROTOCOL instance.
73
74 @retval EFI_SUCCESS Interrupts are enabled on the processor.
75 @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
76
77 **/
78 EFI_STATUS
79 EFIAPI
80 CpuEnableInterrupt (
81 IN EFI_CPU_ARCH_PROTOCOL *This
82 )
83 {
84 ArmEnableInterrupts ();
85
86 return EFI_SUCCESS;
87 }
88
89 /**
90 This function disables interrupt processing by the processor.
91
92 @param This The EFI_CPU_ARCH_PROTOCOL instance.
93
94 @retval EFI_SUCCESS Interrupts are disabled on the processor.
95 @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
96
97 **/
98 EFI_STATUS
99 EFIAPI
100 CpuDisableInterrupt (
101 IN EFI_CPU_ARCH_PROTOCOL *This
102 )
103 {
104 ArmDisableInterrupts ();
105
106 return EFI_SUCCESS;
107 }
108
109 /**
110 This function retrieves the processor's current interrupt state a returns it in
111 State. If interrupts are currently enabled, then TRUE is returned. If interrupts
112 are currently disabled, then FALSE is returned.
113
114 @param This The EFI_CPU_ARCH_PROTOCOL instance.
115 @param State A pointer to the processor's current interrupt state. Set to TRUE if
116 interrupts are enabled and FALSE if interrupts are disabled.
117
118 @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
119 @retval EFI_INVALID_PARAMETER State is NULL.
120
121 **/
122 EFI_STATUS
123 EFIAPI
124 CpuGetInterruptState (
125 IN EFI_CPU_ARCH_PROTOCOL *This,
126 OUT BOOLEAN *State
127 )
128 {
129 if (State == NULL) {
130 return EFI_INVALID_PARAMETER;
131 }
132
133 *State = ArmGetInterruptState ();
134 return EFI_SUCCESS;
135 }
136
137 /**
138 This function generates an INIT on the processor. If this function succeeds, then the
139 processor will be reset, and control will not be returned to the caller. If InitType is
140 not supported by this processor, or the processor cannot programmatically generate an
141 INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
142 occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
143
144 @param This The EFI_CPU_ARCH_PROTOCOL instance.
145 @param InitType The type of processor INIT to perform.
146
147 @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
148 @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
149 by this processor.
150 @retval EFI_DEVICE_ERROR The processor INIT failed.
151
152 **/
153 EFI_STATUS
154 EFIAPI
155 CpuInit (
156 IN EFI_CPU_ARCH_PROTOCOL *This,
157 IN EFI_CPU_INIT_TYPE InitType
158 )
159 {
160 return EFI_UNSUPPORTED;
161 }
162
163 EFI_STATUS
164 EFIAPI
165 CpuRegisterInterruptHandler (
166 IN EFI_CPU_ARCH_PROTOCOL *This,
167 IN EFI_EXCEPTION_TYPE InterruptType,
168 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
169 )
170 {
171 return RegisterInterruptHandler (InterruptType, InterruptHandler);
172 }
173
174 EFI_STATUS
175 EFIAPI
176 CpuGetTimerValue (
177 IN EFI_CPU_ARCH_PROTOCOL *This,
178 IN UINT32 TimerIndex,
179 OUT UINT64 *TimerValue,
180 OUT UINT64 *TimerPeriod OPTIONAL
181 )
182 {
183 return EFI_UNSUPPORTED;
184 }
185
186 /**
187 Callback function for idle events.
188
189 @param Event Event whose notification function is being invoked.
190 @param Context The pointer to the notification function's context,
191 which is implementation-dependent.
192
193 **/
194 VOID
195 EFIAPI
196 IdleLoopEventCallback (
197 IN EFI_EVENT Event,
198 IN VOID *Context
199 )
200 {
201 CpuSleep ();
202 }
203
204 //
205 // Globals used to initialize the protocol
206 //
207 EFI_HANDLE mCpuHandle = NULL;
208 EFI_CPU_ARCH_PROTOCOL mCpu = {
209 CpuFlushCpuDataCache,
210 CpuEnableInterrupt,
211 CpuDisableInterrupt,
212 CpuGetInterruptState,
213 CpuInit,
214 CpuRegisterInterruptHandler,
215 CpuGetTimerValue,
216 CpuSetMemoryAttributes,
217 0, // NumberOfTimers
218 2048, // DmaBufferAlignment
219 };
220
221 STATIC
222 VOID
223 InitializeDma (
224 IN OUT EFI_CPU_ARCH_PROTOCOL *CpuArchProtocol
225 )
226 {
227 CpuArchProtocol->DmaBufferAlignment = ArmCacheWritebackGranule ();
228 }
229
230 EFI_STATUS
231 CpuDxeInitialize (
232 IN EFI_HANDLE ImageHandle,
233 IN EFI_SYSTEM_TABLE *SystemTable
234 )
235 {
236 EFI_STATUS Status;
237 EFI_EVENT IdleLoopEvent;
238
239 InitializeExceptions (&mCpu);
240
241 InitializeDma (&mCpu);
242
243 Status = gBS->InstallMultipleProtocolInterfaces (
244 &mCpuHandle,
245 &gEfiCpuArchProtocolGuid,
246 &mCpu,
247 NULL
248 );
249
250 //
251 // Make sure GCD and MMU settings match. This API calls gDS->SetMemorySpaceAttributes ()
252 // and that calls EFI_CPU_ARCH_PROTOCOL.SetMemoryAttributes, so this code needs to go
253 // after the protocol is installed
254 //
255 mIsFlushingGCD = TRUE;
256 SyncCacheConfig (&mCpu);
257 mIsFlushingGCD = FALSE;
258
259 // If the platform is a MPCore system then install the Configuration Table describing the
260 // secondary core states
261 if (ArmIsMpCore ()) {
262 PublishArmProcessorTable ();
263 }
264
265 //
266 // Setup a callback for idle events
267 //
268 Status = gBS->CreateEventEx (
269 EVT_NOTIFY_SIGNAL,
270 TPL_NOTIFY,
271 IdleLoopEventCallback,
272 NULL,
273 &gIdleLoopEventGuid,
274 &IdleLoopEvent
275 );
276 ASSERT_EFI_ERROR (Status);
277
278 return Status;
279 }