VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/MdePkg/Library/BaseCacheMaintenanceLib/RiscVCache.c@ 109091

Last change on this file since 109091 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: 10.2 KB
Line 
1/** @file
2 RISC-V specific functionality for cache.
3
4 Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
5 Copyright (c) 2023, Rivos Inc. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8**/
9
10#include <Base.h>
11#include <Library/BaseLib.h>
12#include <Library/DebugLib.h>
13#include <Library/PcdLib.h>
14
15//
16// TODO: Grab cache block size and make Cache Management Operation
17// enabling decision based on RISC-V CPU HOB in
18// future when it is available and convert PcdRiscVFeatureOverride
19// PCD to a pointer that contains pointer to bitmap structure
20// which can be operated more elegantly.
21//
22#define RISCV_CACHE_BLOCK_SIZE 64
23#define RISCV_CPU_FEATURE_CMO_BITMASK 0x1
24
25typedef enum {
26 CacheOpClean,
27 CacheOpFlush,
28 CacheOpInvld,
29} CACHE_OP;
30
31/**
32Verify CBOs are supported by this HW
33TODO: Use RISC-V CPU HOB once available.
34
35**/
36STATIC
37BOOLEAN
38RiscVIsCMOEnabled (
39 VOID
40 )
41{
42 // If CMO is disabled in HW, skip Override check
43 // Otherwise this PCD can override settings
44 return ((PcdGet64 (PcdRiscVFeatureOverride) & RISCV_CPU_FEATURE_CMO_BITMASK) != 0);
45}
46
47/**
48 Performs required opeartion on cache lines in the cache coherency domain
49 of the calling CPU. If Address is not aligned on a cache line boundary,
50 then entire cache line containing Address is operated. If Address + Length
51 is not aligned on a cache line boundary, then the entire cache line
52 containing Address + Length -1 is operated.
53 If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
54 @param Address The base address of the cache lines to
55 invalidate.
56 @param Length The number of bytes to invalidate from the instruction
57 cache.
58 @param Op Type of CMO operation to be performed
59 @return Address.
60
61**/
62STATIC
63VOID
64CacheOpCacheRange (
65 IN VOID *Address,
66 IN UINTN Length,
67 IN CACHE_OP Op
68 )
69{
70 UINTN CacheLineSize;
71 UINTN Start;
72 UINTN End;
73
74 if (Length == 0) {
75 return;
76 }
77
78 if ((Op != CacheOpInvld) && (Op != CacheOpFlush) && (Op != CacheOpClean)) {
79 return;
80 }
81
82 ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Address));
83
84 CacheLineSize = RISCV_CACHE_BLOCK_SIZE;
85
86 Start = (UINTN)Address;
87 //
88 // Calculate the cache line alignment
89 //
90 End = (Start + Length + (CacheLineSize - 1)) & ~(CacheLineSize - 1);
91 Start &= ~((UINTN)CacheLineSize - 1);
92
93 DEBUG (
94 (DEBUG_VERBOSE,
95 "CacheOpCacheRange: Performing Cache Management Operation %d \n", Op)
96 );
97
98 do {
99 switch (Op) {
100 case CacheOpInvld:
101 RiscVCpuCacheInvalCmoAsm (Start);
102 break;
103 case CacheOpFlush:
104 RiscVCpuCacheFlushCmoAsm (Start);
105 break;
106 case CacheOpClean:
107 RiscVCpuCacheCleanCmoAsm (Start);
108 break;
109 default:
110 break;
111 }
112
113 Start = Start + CacheLineSize;
114 } while (Start != End);
115}
116
117/**
118 Invalidates the entire instruction cache in cache coherency domain of the
119 calling CPU. Risc-V does not have currently an CBO implementation which can
120 invalidate the entire I-cache. Hence using Fence instruction for now. P.S.
121 Fence instruction may or may not implement full I-cache invd functionality
122 on all implementations.
123
124**/
125VOID
126EFIAPI
127InvalidateInstructionCache (
128 VOID
129 )
130{
131 RiscVInvalidateInstCacheFenceAsm ();
132}
133
134/**
135 Invalidates a range of instruction cache lines in the cache coherency domain
136 of the calling CPU.
137
138 An operation from a CMO instruction is defined to operate only on the copies
139 of a cache block that are cached in the caches accessible by the explicit
140 memory accesses performed by the set of coherent agents.In other words CMO
141 operations are not applicable to instruction cache. Use fence.i instruction
142 instead to achieve the same purpose.
143 @param Address The base address of the instruction cache lines to
144 invalidate. If the CPU is in a physical addressing mode, then
145 Address is a physical address. If the CPU is in a virtual
146 addressing mode, then Address is a virtual address.
147
148 @param Length The number of bytes to invalidate from the instruction cache.
149
150 @return Address.
151
152**/
153VOID *
154EFIAPI
155InvalidateInstructionCacheRange (
156 IN VOID *Address,
157 IN UINTN Length
158 )
159{
160 DEBUG (
161 (DEBUG_VERBOSE,
162 "InvalidateInstructionCacheRange: RISC-V unsupported function.\n"
163 "Invalidating the whole instruction cache instead.\n"
164 )
165 );
166 InvalidateInstructionCache ();
167 return Address;
168}
169
170/**
171 Writes back and invalidates the entire data cache in cache coherency domain
172 of the calling CPU.
173
174 Writes back and invalidates the entire data cache in cache coherency domain
175 of the calling CPU. This function guarantees that all dirty cache lines are
176 written back to system memory, and also invalidates all the data cache lines
177 in the cache coherency domain of the calling CPU.
178
179**/
180VOID
181EFIAPI
182WriteBackInvalidateDataCache (
183 VOID
184 )
185{
186 ASSERT (FALSE);
187 DEBUG ((
188 DEBUG_ERROR,
189 "WriteBackInvalidateDataCache: RISC-V unsupported function.\n"
190 ));
191}
192
193/**
194 Writes back and invalidates a range of data cache lines in the cache
195 coherency domain of the calling CPU.
196
197 Writes back and invalidates the data cache lines specified by Address and
198 Length. If Address is not aligned on a cache line boundary, then entire data
199 cache line containing Address is written back and invalidated. If Address +
200 Length is not aligned on a cache line boundary, then the entire data cache
201 line containing Address + Length -1 is written back and invalidated. This
202 function may choose to write back and invalidate the entire data cache if
203 that is more efficient than writing back and invalidating the specified
204 range. If Length is 0, then no data cache lines are written back and
205 invalidated. Address is returned.
206
207 If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
208
209 @param Address The base address of the data cache lines to write back and
210 invalidate. If the CPU is in a physical addressing mode, then
211 Address is a physical address. If the CPU is in a virtual
212 addressing mode, then Address is a virtual address.
213 @param Length The number of bytes to write back and invalidate from the
214 data cache.
215
216 @return Address of cache invalidation.
217
218**/
219VOID *
220EFIAPI
221WriteBackInvalidateDataCacheRange (
222 IN VOID *Address,
223 IN UINTN Length
224 )
225{
226 if (RiscVIsCMOEnabled ()) {
227 CacheOpCacheRange (Address, Length, CacheOpFlush);
228 } else {
229 ASSERT (FALSE);
230 }
231
232 return Address;
233}
234
235/**
236 Writes back the entire data cache in cache coherency domain of the calling
237 CPU.
238
239 Writes back the entire data cache in cache coherency domain of the calling
240 CPU. This function guarantees that all dirty cache lines are written back to
241 system memory. This function may also invalidate all the data cache lines in
242 the cache coherency domain of the calling CPU.
243
244**/
245VOID
246EFIAPI
247WriteBackDataCache (
248 VOID
249 )
250{
251 ASSERT (FALSE);
252}
253
254/**
255 Writes back a range of data cache lines in the cache coherency domain of the
256 calling CPU.
257
258 Writes back the data cache lines specified by Address and Length. If Address
259 is not aligned on a cache line boundary, then entire data cache line
260 containing Address is written back. If Address + Length is not aligned on a
261 cache line boundary, then the entire data cache line containing Address +
262 Length -1 is written back. This function may choose to write back the entire
263 data cache if that is more efficient than writing back the specified range.
264 If Length is 0, then no data cache lines are written back. This function may
265 also invalidate all the data cache lines in the specified range of the cache
266 coherency domain of the calling CPU. Address is returned.
267
268 If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
269
270 @param Address The base address of the data cache lines to write back.
271 @param Length The number of bytes to write back from the data cache.
272
273 @return Address of cache written in main memory.
274
275**/
276VOID *
277EFIAPI
278WriteBackDataCacheRange (
279 IN VOID *Address,
280 IN UINTN Length
281 )
282{
283 if (RiscVIsCMOEnabled ()) {
284 CacheOpCacheRange (Address, Length, CacheOpClean);
285 } else {
286 ASSERT (FALSE);
287 }
288
289 return Address;
290}
291
292/**
293 Invalidates the entire data cache in cache coherency domain of the calling
294 CPU.
295
296 Invalidates the entire data cache in cache coherency domain of the calling
297 CPU. This function must be used with care because dirty cache lines are not
298 written back to system memory. It is typically used for cache diagnostics. If
299 the CPU does not support invalidation of the entire data cache, then a write
300 back and invalidate operation should be performed on the entire data cache.
301
302**/
303VOID
304EFIAPI
305InvalidateDataCache (
306 VOID
307 )
308{
309 RiscVInvalidateDataCacheFenceAsm ();
310}
311
312/**
313 Invalidates a range of data cache lines in the cache coherency domain of the
314 calling CPU.
315
316 Invalidates the data cache lines specified by Address and Length. If Address
317 is not aligned on a cache line boundary, then entire data cache line
318 containing Address is invalidated. If Address + Length is not aligned on a
319 cache line boundary, then the entire data cache line containing Address +
320 Length -1 is invalidated. This function must never invalidate any cache lines
321 outside the specified range. If Length is 0, then no data cache lines are
322 invalidated. Address is returned. This function must be used with care
323 because dirty cache lines are not written back to system memory. It is
324 typically used for cache diagnostics. If the CPU does not support
325 invalidation of a data cache range, then a write back and invalidate
326 operation should be performed on the data cache range.
327
328 If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
329
330 @param Address The base address of the data cache lines to invalidate.
331 @param Length The number of bytes to invalidate from the data cache.
332
333 @return Address.
334
335**/
336VOID *
337EFIAPI
338InvalidateDataCacheRange (
339 IN VOID *Address,
340 IN UINTN Length
341 )
342{
343 if (RiscVIsCMOEnabled ()) {
344 CacheOpCacheRange (Address, Length, CacheOpInvld);
345 } else {
346 DEBUG (
347 (DEBUG_VERBOSE,
348 "InvalidateDataCacheRange: Zicbom not supported.\n"
349 "Invalidating the whole Data cache instead.\n")
350 );
351 InvalidateDataCache ();
352 }
353
354 return Address;
355}
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