MdePkg: Utilize Cache Management Operations Implementation For RISC-V

Use newly defined cache management operations for RISC-V where possible
It builds up on the support added for RISC-V cache management
instructions in BaseLib.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Pedro Falcato <pedro.falcato@gmail.com>

Signed-off-by: Dhaval Sharma <dhaval@rivosinc.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Pedro Falcato <pedro.falcato@gmail.com>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
This commit is contained in:
Dhaval Sharma
2023-12-13 20:29:30 +05:30
committed by mergify[bot]
parent 26727c2ae2
commit 904b002c50
4 changed files with 165 additions and 28 deletions

View File

@@ -56,3 +56,8 @@
BaseLib BaseLib
DebugLib DebugLib
[LibraryClasses.RISCV64]
PcdLib
[Pcd.RISCV64]
gEfiMdePkgTokenSpaceGuid.PcdRiscVFeatureOverride ## CONSUMES

View File

@@ -2,6 +2,7 @@
RISC-V specific functionality for cache. RISC-V specific functionality for cache.
Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR> Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
Copyright (c) 2023, Rivos Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@@ -9,10 +10,116 @@
#include <Base.h> #include <Base.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/PcdLib.h>
//
// TODO: Grab cache block size and make Cache Management Operation
// enabling decision based on RISC-V CPU HOB in
// future when it is available and convert PcdRiscVFeatureOverride
// PCD to a pointer that contains pointer to bitmap structure
// which can be operated more elegantly.
//
#define RISCV_CACHE_BLOCK_SIZE 64
#define RISCV_CPU_FEATURE_CMO_BITMASK 0x1
typedef enum {
CacheOpClean,
CacheOpFlush,
CacheOpInvld,
} CACHE_OP;
/**
Verify CBOs are supported by this HW
TODO: Use RISC-V CPU HOB once available.
**/
STATIC
BOOLEAN
RiscVIsCMOEnabled (
VOID
)
{
// If CMO is disabled in HW, skip Override check
// Otherwise this PCD can override settings
return ((PcdGet64 (PcdRiscVFeatureOverride) & RISCV_CPU_FEATURE_CMO_BITMASK) != 0);
}
/**
Performs required opeartion on cache lines in the cache coherency domain
of the calling CPU. If Address is not aligned on a cache line boundary,
then entire cache line containing Address is operated. If Address + Length
is not aligned on a cache line boundary, then the entire cache line
containing Address + Length -1 is operated.
If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
@param Address The base address of the cache lines to
invalidate.
@param Length The number of bytes to invalidate from the instruction
cache.
@param Op Type of CMO operation to be performed
@return Address.
**/
STATIC
VOID
CacheOpCacheRange (
IN VOID *Address,
IN UINTN Length,
IN CACHE_OP Op
)
{
UINTN CacheLineSize;
UINTN Start;
UINTN End;
if (Length == 0) {
return;
}
if ((Op != CacheOpInvld) && (Op != CacheOpFlush) && (Op != CacheOpClean)) {
return;
}
ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Address));
CacheLineSize = RISCV_CACHE_BLOCK_SIZE;
Start = (UINTN)Address;
//
// Calculate the cache line alignment
//
End = (Start + Length + (CacheLineSize - 1)) & ~(CacheLineSize - 1);
Start &= ~((UINTN)CacheLineSize - 1);
DEBUG (
(DEBUG_VERBOSE,
"CacheOpCacheRange: Performing Cache Management Operation %d \n", Op)
);
do {
switch (Op) {
case CacheOpInvld:
RiscVCpuCacheInvalCmoAsm (Start);
break;
case CacheOpFlush:
RiscVCpuCacheFlushCmoAsm (Start);
break;
case CacheOpClean:
RiscVCpuCacheCleanCmoAsm (Start);
break;
default:
break;
}
Start = Start + CacheLineSize;
} while (Start != End);
}
/** /**
Invalidates the entire instruction cache in cache coherency domain of the Invalidates the entire instruction cache in cache coherency domain of the
calling CPU. calling CPU. Risc-V does not have currently an CBO implementation which can
invalidate the entire I-cache. Hence using Fence instruction for now. P.S.
Fence instruction may or may not implement full I-cache invd functionality
on all implementations.
**/ **/
VOID VOID
@@ -28,17 +135,11 @@ InvalidateInstructionCache (
Invalidates a range of instruction cache lines in the cache coherency domain Invalidates a range of instruction cache lines in the cache coherency domain
of the calling CPU. of the calling CPU.
Invalidates the instruction cache lines specified by Address and Length. If An operation from a CMO instruction is defined to operate only on the copies
Address is not aligned on a cache line boundary, then entire instruction of a cache block that are cached in the caches accessible by the explicit
cache line containing Address is invalidated. If Address + Length is not memory accesses performed by the set of coherent agents.In other words CMO
aligned on a cache line boundary, then the entire instruction cache line operations are not applicable to instruction cache. Use fence.i instruction
containing Address + Length -1 is invalidated. This function may choose to instead to achieve the same purpose.
invalidate the entire instruction cache if that is more efficient than
invalidating the specified range. If Length is 0, then no instruction cache
lines are invalidated. Address is returned.
If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
@param Address The base address of the instruction cache lines to @param Address The base address of the instruction cache lines to
invalidate. If the CPU is in a physical addressing mode, then invalidate. If the CPU is in a physical addressing mode, then
Address is a physical address. If the CPU is in a virtual Address is a physical address. If the CPU is in a virtual
@@ -57,9 +158,10 @@ InvalidateInstructionCacheRange (
) )
{ {
DEBUG ( DEBUG (
(DEBUG_WARN, (DEBUG_VERBOSE,
"%a:RISC-V unsupported function.\n" "InvalidateInstructionCacheRange: RISC-V unsupported function.\n"
"Invalidating the whole instruction cache instead.\n", __func__) "Invalidating the whole instruction cache instead.\n"
)
); );
InvalidateInstructionCache (); InvalidateInstructionCache ();
return Address; return Address;
@@ -81,7 +183,11 @@ WriteBackInvalidateDataCache (
VOID VOID
) )
{ {
DEBUG ((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __func__)); ASSERT (FALSE);
DEBUG ((
DEBUG_ERROR,
"WriteBackInvalidateDataCache: RISC-V unsupported function.\n"
));
} }
/** /**
@@ -117,7 +223,12 @@ WriteBackInvalidateDataCacheRange (
IN UINTN Length IN UINTN Length
) )
{ {
DEBUG ((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __func__)); if (RiscVIsCMOEnabled ()) {
CacheOpCacheRange (Address, Length, CacheOpFlush);
} else {
ASSERT (FALSE);
}
return Address; return Address;
} }
@@ -137,7 +248,7 @@ WriteBackDataCache (
VOID VOID
) )
{ {
DEBUG ((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __func__)); ASSERT (FALSE);
} }
/** /**
@@ -156,10 +267,7 @@ WriteBackDataCache (
If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
@param Address The base address of the data cache lines to write back. If @param Address The base address of the data cache lines to write back.
the CPU is in a physical addressing mode, then Address is a
physical address. If the CPU is in a virtual addressing
mode, then Address is a virtual address.
@param Length The number of bytes to write back from the data cache. @param Length The number of bytes to write back from the data cache.
@return Address of cache written in main memory. @return Address of cache written in main memory.
@@ -172,7 +280,12 @@ WriteBackDataCacheRange (
IN UINTN Length IN UINTN Length
) )
{ {
DEBUG ((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __func__)); if (RiscVIsCMOEnabled ()) {
CacheOpCacheRange (Address, Length, CacheOpClean);
} else {
ASSERT (FALSE);
}
return Address; return Address;
} }
@@ -214,10 +327,7 @@ InvalidateDataCache (
If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
@param Address The base address of the data cache lines to invalidate. If @param Address The base address of the data cache lines to invalidate.
the CPU is in a physical addressing mode, then Address is a
physical address. If the CPU is in a virtual addressing mode,
then Address is a virtual address.
@param Length The number of bytes to invalidate from the data cache. @param Length The number of bytes to invalidate from the data cache.
@return Address. @return Address.
@@ -230,6 +340,16 @@ InvalidateDataCacheRange (
IN UINTN Length IN UINTN Length
) )
{ {
DEBUG ((DEBUG_ERROR, "%a:RISC-V unsupported function.\n", __func__)); if (RiscVIsCMOEnabled ()) {
CacheOpCacheRange (Address, Length, CacheOpInvld);
} else {
DEBUG (
(DEBUG_VERBOSE,
"InvalidateDataCacheRange: Zicbom not supported.\n"
"Invalidating the whole Data cache instead.\n")
);
InvalidateDataCache ();
}
return Address; return Address;
} }

View File

@@ -2400,6 +2400,14 @@
# @Prompt CPU Rng algorithm's GUID. # @Prompt CPU Rng algorithm's GUID.
gEfiMdePkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID*|0x00000037 gEfiMdePkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID*|0x00000037
[PcdsFixedAtBuild.RISCV64, PcdsPatchableInModule.RISCV64]
#
# Configurability to override RISC-V CPU Features
# BIT 0 = Cache Management Operations. This bit is relevant only if
# previous stage has feature enabled and user wants to disable it.
#
gEfiMdePkgTokenSpaceGuid.PcdRiscVFeatureOverride|0xFFFFFFFFFFFFFFFF|UINT64|0x69
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## This value is used to set the base address of PCI express hierarchy. ## This value is used to set the base address of PCI express hierarchy.
# @Prompt PCI Express Base Address. # @Prompt PCI Express Base Address.

View File

@@ -289,6 +289,10 @@
#string STR_gEfiMdePkgTokenSpaceGuid_PcdGuidedExtractHandlerTableAddress_HELP #language en-US "This value is used to set the available memory address to store Guided Extract Handlers. The required memory space is decided by the value of PcdMaximumGuidedExtractHandler." #string STR_gEfiMdePkgTokenSpaceGuid_PcdGuidedExtractHandlerTableAddress_HELP #language en-US "This value is used to set the available memory address to store Guided Extract Handlers. The required memory space is decided by the value of PcdMaximumGuidedExtractHandler."
#string STR_gEfiMdePkgTokenSpaceGuid_PcdRiscVFeatureOverride_PROMPT #language en-US "RISC-V Feature Override"
#string STR_gEfiMdePkgTokenSpaceGuid_PcdRiscVFeatureOverride_HELP #language en-US "This value is used to override any RISC-V specific features supported by this PCD"
#string STR_gEfiMdePkgTokenSpaceGuid_PcdPciExpressBaseAddress_PROMPT #language en-US "PCI Express Base Address" #string STR_gEfiMdePkgTokenSpaceGuid_PcdPciExpressBaseAddress_PROMPT #language en-US "PCI Express Base Address"
#string STR_gEfiMdePkgTokenSpaceGuid_PcdPciExpressBaseAddress_HELP #language en-US "This value is used to set the base address of PCI express hierarchy." #string STR_gEfiMdePkgTokenSpaceGuid_PcdPciExpressBaseAddress_HELP #language en-US "This value is used to set the base address of PCI express hierarchy."