Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions UefiCpuPkg/Include/Library/BaseRiscVMmuLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#pragma once

#define PTE_ATTRIBUTES_MASK 0xE

/**
The API to flush all local TLBs.

Expand All @@ -31,6 +33,46 @@ RiscVLocalTlbFlush (
UINTN VirtAddr
);

/**
Free resources of translation table recursively.

@param TranslationTable The pointer of table.
@param Level The current level.

**/
VOID
EFIAPI
FreePageTablesRecursive (
IN UINT64 *TranslationTable,
IN UINTN Level
);

/**
Update region mapping at root table.

@param RegionStart The start address of the region.
@param RegionLength The length of the region.
@param AttributeSetMask The attribute mask to be set.
@param AttributeClearMask The attribute mask to be clear.
@param RootTable The pointer of root table.
@param TableIsLive TRUE if this is live update, FALSE otherwise.

@retval EFI_INVALID_PARAMETER The RegionStart or RegionLength was not valid.
@retval EFI_OUT_OF_RESOURCES Not enough resource.
@retval EFI_SUCCESS The operation succesfully.

**/
EFI_STATUS
EFIAPI
UpdateRegionMapping (
IN UINT64 RegionStart,
IN UINT64 RegionLength,
IN UINT64 AttributeSetMask,
IN UINT64 AttributeClearMask,
IN UINT64 *RootTable,
IN BOOLEAN TableIsLive
);

/**
The API to set a GCD attribute on an memory region.

Expand Down
50 changes: 50 additions & 0 deletions UefiCpuPkg/Include/Protocol/RiscVIoMmuPlatformPolicy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/** @file
The definition for the RISC-V IOMMU platform policy protocol.

Copyright (c) 2026, 9elements GmbH. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#ifndef _RISC_V_IO_MMU_PLATFORM_POLICY_H_
#define _RISC_V_IO_MMU_PLATFORM_POLICY_H_

#include <PiDxe.h>

extern EFI_GUID gEdkiiRiscVIoMmuPlatformPolicyProtocolGuid;

typedef struct _EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_PROTOCOL EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_PROTOCOL;

#define EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_PROTOCOL_REVISION 0x00000000

/**
Get the IOMMU device_id and this IOMMU base address from the device handle.
This function is required for non PCI device handles.

@param[in] This The protocol instance pointer.
@param[in] DeviceHandle Device Identifier in UEFI.
@param[out] IoMmuDeviceId IoMmuDeviceId for identifying the device on the IOMMU.
@param[out] IoMmuBaseAddress IoMmuBaseAddress for identifying the upstream IOMMU.

@retval EFI_SUCCESS The IoMmuDeviceId and IoMmuBaseAddress are returned.
@retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.
@retval EFI_INVALID_PARAMETER IoMmuDeviceId or IoMmuBaseAddress are NULL.
@retval EFI_NOT_FOUND The device_id information is NOT found.
@retval EFI_UNSUPPORTED This function is not supported.

**/
typedef
EFI_STATUS
(EFIAPI *EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_GET_DEVICE_ID) (
IN EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
OUT UINT32 *IoMmuDeviceId,
OUT EFI_PHYSICAL_ADDRESS *IoMmuBaseAddress
);

struct _EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_PROTOCOL {
UINT64 Revision;
EDKII_RISC_V_IO_MMU_PLATFORM_POLICY_GET_DEVICE_ID GetDeviceId;
};

#endif
28 changes: 20 additions & 8 deletions UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/** @file
MMU library for RISC-V.

TODO: Migrate some fields into an 'operating context' structure.

Copyright (c) 2011-2020, ARM Limited. All rights reserved.
Copyright (c) 2016, Linaro Limited. All rights reserved.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
Expand Down Expand Up @@ -30,7 +32,6 @@
#define RISCV_PG_G BIT5
#define RISCV_PG_A BIT6
#define RISCV_PG_D BIT7
#define PTE_ATTRIBUTES_MASK 0xE

#define PTE_PPN_MASK 0x3FFFFFFFFFFC00ULL
#define PTE_PPN_SHIFT 10
Expand All @@ -42,9 +43,9 @@
#define PTE_PBMT_MASK (PTE_PBMT_NC | PTE_PBMT_IO)

STATIC UINTN mModeSupport[] = { SATP_MODE_SV57, SATP_MODE_SV48, SATP_MODE_SV39, SATP_MODE_OFF };
STATIC UINTN mMaxRootTableLevel;
STATIC UINTN mBitPerLevel;
STATIC UINTN mTableEntryCount;
UINTN mMaxRootTableLevel;
UINTN mBitPerLevel;
UINTN mTableEntryCount;

/**
Determine if the MMU enabled or not.
Expand Down Expand Up @@ -252,8 +253,8 @@ SetPpnToPte (
@param Level The current level.

**/
STATIC
VOID
EFIAPI
FreePageTablesRecursive (
IN UINT64 *TranslationTable,
IN UINTN Level
Expand Down Expand Up @@ -319,7 +320,7 @@ UpdateRegionMappingRecursive (
BlockMask = MAX_ADDRESS >> (64 - BlockShift);

DEBUG ((
DEBUG_VERBOSE,
DEBUG_INFO,
"%a(%d): %LX - %LX set %LX clr %LX\n",
__func__,
Level,
Expand Down Expand Up @@ -440,7 +441,18 @@ UpdateRegionMappingRecursive (
}

EntryValue = SetPpnToPte (EntryValue, RegionStart);
EntryValue = SetValidPte (EntryValue);

//
// Unmapped memory regions must have the 'valid' bit cleared.
// This is because entries with 'valid' set and RWX clear are considered as "table entries"
// (non-leaves), and trigger the ASSERT above for reaching the leaf-level with a non-leaf.
//
if ((AttributeClearMask == PTE_ATTRIBUTES_MASK) && (AttributeSetMask == 0)) {
EntryValue &= ~RISCV_PG_V;
} else {
EntryValue = SetValidPte (EntryValue);
}

ReplaceTableEntry (Entry, EntryValue, RegionStart, TableIsLive);
}
}
Expand All @@ -463,8 +475,8 @@ UpdateRegionMappingRecursive (
@retval EFI_SUCCESS The operation succesfully.

**/
STATIC
EFI_STATUS
EFIAPI
UpdateRegionMapping (
IN UINT64 RegionStart,
IN UINT64 RegionLength,
Expand Down
17 changes: 17 additions & 0 deletions UefiCpuPkg/RiscVIoMmuDxe/AsmUtilities.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//------------------------------------------------------------------------------
//
// RISC-V CSR helper functions
//
// Copyright (c) 2025, 9elements GmbH. All rights reserved.<BR>
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
//------------------------------------------------------------------------------

#include <Register/RiscV64/RiscVImpl.h>

//
// Get the contents of the Supervisor Status Register.
//
ASM_FUNC (RiscVGetSupervisorStatusRegister)
csrr a0, CSR_SSTATUS
ret
Loading
Loading