From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) by mx.groups.io with SMTP id smtpd.web10.1424.1684952204910000197 for <devel@edk2.groups.io>; Wed, 24 May 2023 11:16:45 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@ventanamicro.com header.s=google header.b=Kl+iIsxt; spf=pass (domain: ventanamicro.com, ip: 209.85.219.51, mailfrom: tphan@ventanamicro.com) Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-62385a3106dso318626d6.2 for <devel@edk2.groups.io>; Wed, 24 May 2023 11:16:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1684952204; x=1687544204; h=mime-version:content-language:accept-language:in-reply-to :references:message-id:date:thread-index:thread-topic:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=/eSrfgqC+prSvsu/Ymv/FdN5knH7gkzCPQD6sVI2xO4=; b=Kl+iIsxtAjUAFXI9hEZVPL5UewXEpk/qD7ZPSR0tUgOe2xgFa5/ZCv/2zyjaeheckD /RE4JdwI9VsgZR7gGPC9WQEYE1X8HWkvYcbI4lrTqCnsvZnmIvTXWm1ZzDSKQ0Md4gAY mSGsCHLa3PQ5jc/mA5ui+zARNMj5J0xUWvMpIs2/3UaxkTkGTo1tBZ551wEQSa8IGOS5 L91+mkIEjm4+unoA6+WpWScaQPq+UZrqOh8D21Q7jY6qkXbkxxFQziU5gRLj3EBQ6d3j 3DnaIkhKE/fk4di1ELO7t6PGTMQlalnQupdNPnRMtGDxcBCa55IR+DDX4AlUqDIBarJl XjMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684952204; x=1687544204; h=mime-version:content-language:accept-language:in-reply-to :references:message-id:date:thread-index:thread-topic:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/eSrfgqC+prSvsu/Ymv/FdN5knH7gkzCPQD6sVI2xO4=; b=HKRsQiMyQRHfffRSJXXbgsg/bd68KHPTgShu0jRnBF7/hCl83186ZpSIbkdgZdqbEF J5bxVR0ybeKzhKsL1iIjC85JF5Zsj4qPQm9UHrorh80NA+LxTp3q1YM/udTexdpBJloi 9ri9R+CohDG+aZqggKeT/RvdmJRFfRmD0gtN41DjlmYK+fQv3OgggAHmgre7q8B1nJIg rf9AhQ+LaJ5FhblrcblSMOIA+xs7VHEQSa9iZ6C1bZZvukhasd9fqVtbub/jj24VRVoY N8+g2h+JWJ341kXChUUXWRcSqkCj4ESWFUaHVJEUtN8CU/McawfLvmLiiJ4RzAj6fdeW l+BA== X-Gm-Message-State: AC+VfDx+ZxAkd5x3bAxO6sp0COciXaPYagvz7JmAy1vWR3MHNG0XoFjp 32NuNKCotHrPAxfvmB1y3IMHN0aqxd5IAJWdMUI= X-Google-Smtp-Source: ACHHUZ5ZfkiAfmQjJ+Kmumi67ZrauCSYnrsv59gK8BB7y+5cwnx+HcTIt6smtV04dUW7+mLYdoPzVQ== X-Received: by 2002:ad4:5ced:0:b0:5c8:403a:22f8 with SMTP id iv13-20020ad45ced000000b005c8403a22f8mr29298750qvb.5.1684952203749; Wed, 24 May 2023 11:16:43 -0700 (PDT) Return-Path: <tphan@ventanamicro.com> Received: from MN2PR13MB3022.namprd13.prod.outlook.com ([2603:1036:302:405e::5]) by smtp.gmail.com with ESMTPSA id cz10-20020a056214088a00b0062120b054easm3730598qvb.20.2023.05.24.11.16.43 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 May 2023 11:16:43 -0700 (PDT) From: "Tuan Phan" <tphan@ventanamicro.com> To: "Ni, Ray" <ray.ni@intel.com>, "devel@edk2.groups.io" <devel@edk2.groups.io>, "lichao@loongson.cn" <lichao@loongson.cn>, Ard Biesheuvel <ardb@kernel.org> CC: "Kinney, Michael D" <michael.d.kinney@intel.com>, "Gao, Liming" <gaoliming@byosoft.com.cn>, "Liu, Zhiguang" <zhiguang.liu@intel.com>, "sunilvl@ventanamicro.com" <sunilvl@ventanamicro.com>, "git@danielschaefer.me" <git@danielschaefer.me>, "Warkentin, Andrei" <andrei.warkentin@intel.com> Subject: Re: [edk2-devel] [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support MMU with SV39/48/57 mode Thread-Topic: [edk2-devel] [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support MMU with SV39/48/57 mode Thread-Index: AQHZbwMga4CTCPv2R0CJThklTy+FM69o692AgACA1QCAAIyRiA== X-MS-Exchange-MessageSentRepresentingType: 1 Date: Wed, 24 May 2023 18:16:26 +0000 Message-ID: <MN2PR13MB30225A5769E6AF33496072E0A7419@MN2PR13MB3022.namprd13.prod.outlook.com> References: <20230414185815.2994-1-tphan@ventanamicro.com> <20230414185815.2994-4-tphan@ventanamicro.com> <f815659f-17c1-356e-4b6a-2313e9080049@loongson.cn> <MN6PR11MB82448B11DE60CDAEB1E4BE088C419@MN6PR11MB8244.namprd11.prod.outlook.com> In-Reply-To: <MN6PR11MB82448B11DE60CDAEB1E4BE088C419@MN6PR11MB8244.namprd11.prod.outlook.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-Exchange-Organization-SCL: -1 X-MS-TNEF-Correlator: X-MS-Exchange-Organization-RecordReviewCfmType: 0 MIME-Version: 1.0 Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_MN2PR13MB30225A5769E6AF33496072E0A7419MN2PR13MB3022namp_" --_000_MN2PR13MB30225A5769E6AF33496072E0A7419MN2PR13MB3022namp_ Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: quoted-printable Agree it makes more sense to put the MMU library into UefiCpuPkg. From: Ni, Ray <ray.ni@intel.com> Date: Wednesday, May 24, 2023 at 2:52 AM To: devel@edk2.groups.io <devel@edk2.groups.io>, lichao@loongson.cn <lichao= @loongson.cn>, tphan@ventanamicro.com <tphan@ventanamicro.com>, Ard Biesheu= vel <ardb@kernel.org> Cc: Kinney, Michael D <michael.d.kinney@intel.com>, Gao, Liming <gaoliming@= byosoft.com.cn>, Liu, Zhiguang <zhiguang.liu@intel.com>, sunilvl@ventanamic= ro.com <sunilvl@ventanamicro.com>, git@danielschaefer.me <git@danielschaefe= r.me>, Warkentin, Andrei <andrei.warkentin@intel.com> Subject: RE: [edk2-devel] [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support MMU wi= th SV39/48/57 mode X86 version is in UefiCpuPkg. So be consistent, I would prefer the LoongArch64 version be in UefiCpuPkg a= s well. I know that ARM has similar code (I didn=1B$B!G=1B(Bt check in detail, +@Ar= d Biesheuvel<mailto:ardb@kernel.org>). The trending is to abstract the memory attribute implementation behind Memo= ryAttribute PPI/Protocol for using by other modules. Thanks, Ray From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Chao Li Sent: Wednesday, May 24, 2023 10:11 AM To: devel@edk2.groups.io; tphan@ventanamicro.com Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <gaoliming@= byosoft.com.cn>; Liu, Zhiguang <zhiguang.liu@intel.com>; sunilvl@ventanamic= ro.com; git@danielschaefer.me; Warkentin, Andrei <andrei.warkentin@intel.co= m>; Ni, Ray <ray.ni@intel.com> Subject: Re: [edk2-devel] [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support MMU wi= th SV39/48/57 mode Dear all, I'm also porting MMU library of LoongArch64 to EDK2, I added it in to UefiC= puPkg and make it possible to use the same headers for both the no-IA32 and= no-X64 platforms, and I also saw that IA32 and X64 added the CpuPageTableL= ib to UefiCpuPkg, this library are similar to MMU libraries. I have a quest= ion, should the MMU library be in the MdePkg or UefiCpuPkg? Thanks, Chao =1B$B:_=1B(B 2023/4/15 02:58, Tuan Phan =1B$B<LF;=1B(B: During CpuDxe initialization, MMU will be setup with the highest mode that HW supports. Signed-off-by: Tuan Phan <tphan@ventanamicro.com><mailto:tphan@ventanamicro= .com> --- MdePkg/Include/Library/BaseRiscVMmuLib.h | 39 ++ .../Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c | 569 ++++++++++++++++++ .../BaseRiscVMmuLib/BaseRiscVMmuLib.inf | 25 + MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S | 31 + OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc | 1 + OvmfPkg/RiscVVirt/Sec/Memory.c | 18 +- UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c | 9 +- UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h | 2 + UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf | 2 + 9 files changed, 678 insertions(+), 18 deletions(-) create mode 100644 MdePkg/Include/Library/BaseRiscVMmuLib.h create mode 100644 MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c create mode 100644 MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf create mode 100644 MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S diff --git a/MdePkg/Include/Library/BaseRiscVMmuLib.h b/MdePkg/Include/Libr= ary/BaseRiscVMmuLib.h new file mode 100644 index 000000000000..f71d6a4a1e7b --- /dev/null +++ b/MdePkg/Include/Library/BaseRiscVMmuLib.h @@ -0,0 +1,39 @@ +/** @file + + Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR> + Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef BASE_RISCV_MMU_LIB_H_ +#define BASE_RISCV_MMU_LIB_H_ + +VOID +EFIAPI +RiscVLocalTlbFlushAll ( + VOID + ); + +VOID +EFIAPI +RiscVLocalTlbFlush ( + UINTN VirtAddr + ); + +EFI_STATUS +EFIAPI +RiscVSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +EFI_STATUS +EFIAPI +RiscVConfigureMmu ( + VOID + ); + +#endif /* BASE_RISCV_MMU_LIB_H_ */ diff --git a/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c b/MdePkg/Libr= ary/BaseRiscVMmuLib/BaseRiscVMmuLib.c new file mode 100644 index 000000000000..230f34261d8b --- /dev/null +++ b/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c @@ -0,0 +1,569 @@ +/** @file +* MMU implementation for RISC-V +* +* 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> +* Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.<BR> +* +* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ + +#include <PiDxe.h> +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseRiscVMmuLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/DebugLib.h> +#include <Library/DxeServicesTableLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Register/RiscV64/RiscVEncoding.h> + +#define RISCV_PG_V BIT0 +#define RISCV_PG_R BIT1 +#define RISCV_PG_W BIT2 +#define RISCV_PG_X BIT3 +#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 +#define RISCV_MMU_PAGE_SHIFT 12 + +STATIC UINTN mMaxRootTableLevel; +STATIC UINTN mBitPerLevel; +STATIC UINTN mTableEntryCount; + +STATIC +BOOLEAN +RiscVMmuEnabled ( + VOID + ) +{ + return ((RiscVGetSupervisorAddressTranslationRegister () & + SATP64_MODE) !=3D (SATP_MODE_OFF << SATP64_MODE_SHIFT)); +} + +STATIC +UINTN +RiscVGetRootTranslateTable ( + VOID + ) +{ + return (RiscVGetSupervisorAddressTranslationRegister () & SATP64_PPN) << + RISCV_MMU_PAGE_SHIFT; +} + +STATIC +BOOLEAN +IsValidPte ( + IN UINTN Entry + ) +{ + if (!(Entry & RISCV_PG_V) || + (((Entry & (RISCV_PG_R | RISCV_PG_W)) =3D=3D RISCV_PG_W))) + { + return FALSE; + } + + return TRUE; +} + +STATIC +UINTN +SetValidPte ( + IN UINTN Entry + ) +{ + /* Set Valid and Global mapping bits */ + return Entry | RISCV_PG_G | RISCV_PG_V; +} + +STATIC +BOOLEAN +IsBlockEntry ( + IN UINTN Entry + ) +{ + return IsValidPte (Entry) && + (Entry & (RISCV_PG_X | RISCV_PG_R)); +} + +STATIC +BOOLEAN +IsTableEntry ( + IN UINTN Entry + ) +{ + return IsValidPte (Entry) && + !IsBlockEntry (Entry); +} + +STATIC +UINTN +SetTableEntry ( + IN UINTN Entry + ) +{ + Entry =3D SetValidPte (Entry); + Entry &=3D ~(RISCV_PG_X | RISCV_PG_W | RISCV_PG_R); + + return Entry; +} + +STATIC +VOID +ReplaceTableEntry ( + IN UINTN *Entry, + IN UINTN Value, + IN UINTN RegionStart, + IN BOOLEAN IsLiveBlockMapping + ) +{ + *Entry =3D Value; + + if (IsLiveBlockMapping && RiscVMmuEnabled ()) { + RiscVLocalTlbFlush (RegionStart); + } +} + +STATIC +UINTN +GetPpnfromPte ( + UINTN Entry, + UINTN Level + ) +{ + return ((Entry & PTE_PPN_MASK) >> PTE_PPN_SHIFT); +} + +STATIC +UINTN +SetPpnToPte ( + UINTN Entry, + UINTN Address, + UINTN Level + ) +{ + UINTN Ppn; + + Ppn =3D ((Address >> RISCV_MMU_PAGE_SHIFT) << PTE_PPN_SHIFT); + ASSERT (~(Ppn & ~PTE_PPN_MASK)); + Entry &=3D ~PTE_PPN_MASK; + return Entry | Ppn; +} + +STATIC +VOID +FreePageTablesRecursive ( + IN UINTN *TranslationTable, + IN UINTN Level + ) +{ + UINTN Index; + + if (Level < mMaxRootTableLevel - 1) { + for (Index =3D 0; Index < mTableEntryCount; Index++) { + if (IsTableEntry (TranslationTable[Index])) { + FreePageTablesRecursive ( + (UINTN *)(GetPpnfromPte ((TranslationTabl= e[Index]), Level) << + RISCV_MMU_PAGE_SHIFT), + Level + 1 + ); + } + } + } + + FreePages (TranslationTable, 1); +} + +STATIC +EFI_STATUS +UpdateRegionMappingRecursive ( + IN UINTN RegionStart, + IN UINTN RegionEnd, + IN UINTN AttributeSetMask, + IN UINTN AttributeClearMask, + IN UINTN *PageTable, + IN UINTN Level, + IN BOOLEAN TableIsLive + ) +{ + EFI_STATUS Status; + UINTN BlockShift; + UINTN BlockMask; + UINTN BlockEnd; + UINTN *Entry; + UINTN EntryValue; + UINTN *TranslationTable; + BOOLEAN NextTableIsLive; + + ASSERT (Level < mMaxRootTableLevel); + ASSERT (((RegionStart | RegionEnd) & EFI_PAGE_MASK) =3D=3D 0); + + BlockShift =3D (mMaxRootTableLevel - Level - 1) * mBitPerLevel + RISCV_M= MU_PAGE_SHIFT; + BlockMask =3D MAX_ADDRESS >> (64 - BlockShift); + + DEBUG ( + ( + DEBUG_VERBOSE, + "%a(%d): %llx - %llx set %lx clr %lx\n", + __func__, + Level, + RegionStart, + RegionEnd, + AttributeSetMask, + AttributeClearMask + ) + ); + + for ( ; RegionStart < RegionEnd; RegionStart =3D BlockEnd) { + BlockEnd =3D MIN (RegionEnd, (RegionStart | BlockMask) + 1); + Entry =3D &PageTable[(RegionStart >> BlockShift) & (mTableEntryCoun= t - 1)]; + + // + // If RegionStart or BlockEnd is not aligned to the block size at this + // level, we will have to create a table mapping in order to map less + // than a block, and recurse to create the block or page entries at + // the next level. No block mappings are allowed at all at level 0, + // so in that case, we have to recurse unconditionally. + // + if ((Level =3D=3D 0) || + (((RegionStart | BlockEnd) & BlockMask) !=3D 0) || IsTableEntry (*= Entry)) + { + ASSERT (Level < mMaxRootTableLevel - 1); + if (!IsTableEntry (*Entry)) { + // + // No table entry exists yet, so we need to allocate a page table + // for the next level. + // + TranslationTable =3D AllocatePages (1); + if (TranslationTable =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (TranslationTable, EFI_PAGE_SIZE); + + if (IsBlockEntry (*Entry)) { + // + // We are splitting an existing block entry, so we have to popul= ate + // the new table with the attributes of the block entry it repla= ces. + // + Status =3D UpdateRegionMappingRecursive ( + RegionStart & ~BlockMask, + (RegionStart | BlockMask)= + 1, + *Entry & PTE_ATTRIBUTES_M= ASK, + PTE_ATTRIBUTES_MASK, + TranslationTable, + Level + 1, + FALSE + ); + if (EFI_ERROR (Status)) { + // + // The range we passed to UpdateRegionMappingRecursive () is b= lock + // aligned, so it is guaranteed that no further pages were all= ocated + // by it, and so we only have to free the page we allocated he= re. + // + FreePages (TranslationTable, 1); + return Status; + } + } + + NextTableIsLive =3D FALSE; + } else { + TranslationTable =3D (UINTN *)(GetPpnfromPte (*Entry, Level) << RI= SCV_MMU_PAGE_SHIFT); + NextTableIsLive =3D TableIsLive; + } + + // + // Recurse to the next level + // + Status =3D UpdateRegionMappingRecursive ( + RegionStart, + BlockEnd, + AttributeSetMask, + AttributeClearMask, + TranslationTable, + Level + 1, + NextTableIsLive + ); + if (EFI_ERROR (Status)) { + if (!IsTableEntry (*Entry)) { + // + // We are creating a new table entry, so on failure, we can free= all + // allocations we made recursively, given that the whole subhier= archy + // has not been wired into the live page tables yet. (This is no= t + // possible for existing table entries, since we cannot revert t= he + // modifications we made to the subhierarchy it represents.) + // + FreePageTablesRecursive (TranslationTable, Level + 1); + } + + return Status; + } + + if (!IsTableEntry (*Entry)) { + EntryValue =3D SetPpnToPte (0, (UINTN)TranslationTable, Level); + EntryValue =3D SetTableEntry (EntryValue); + ReplaceTableEntry ( + Entry, + EntryValue, + RegionStart, + TableIsLive + ); + } + } else { + EntryValue =3D (*Entry & ~AttributeClearMask) | AttributeSetMask; + // + // We don't have page fault exception handler when a virtual page is= accessed and + // the A bit is clear, or is written and the D bit is clear. + // So just set A for read and D for write permission. + // + if (AttributeSetMask & RISCV_PG_R) { + EntryValue |=3D RISCV_PG_A; + } + + if (AttributeSetMask & RISCV_PG_W) { + EntryValue |=3D RISCV_PG_D; + } + + EntryValue =3D SetPpnToPte (EntryValue, RegionStart, Level); + EntryValue =3D SetValidPte (EntryValue); + ReplaceTableEntry (Entry, EntryValue, RegionStart, TableIsLive); + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +UpdateRegionMapping ( + IN UINTN RegionStart, + IN UINTN RegionLength, + IN UINTN AttributeSetMask, + IN UINTN AttributeClearMask, + IN UINTN *RootTable, + IN BOOLEAN TableIsLive + ) +{ + if (((RegionStart | RegionLength) & EFI_PAGE_MASK) !=3D 0) { + return EFI_INVALID_PARAMETER; + } + + return UpdateRegionMappingRecursive ( + RegionStart, + RegionStart + RegionLength, + AttributeSetMask, + AttributeClearMask, + RootTable, + 0, + TableIsLive + ); +} + +STATIC +UINTN +GcdAttributeToPageAttribute ( + IN UINTN GcdAttributes + ) +{ + UINTN RiscVAttributes =3D RISCV_PG_R | RISCV_PG_W | RISCV_PG_X; + + // Determine protection attributes + if (GcdAttributes & EFI_MEMORY_RO) { + RiscVAttributes &=3D ~(RISCV_PG_W); + } + + // Process eXecute Never attribute + if (GcdAttributes & EFI_MEMORY_XP) { + RiscVAttributes &=3D ~RISCV_PG_X; + } + + return RiscVAttributes; +} + +EFI_STATUS +EFIAPI +RiscVSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length, + IN UINTN Attributes + ) +{ + UINTN PageAttributesSet =3D GcdAttributeToPageAttribute (Attributes); + + if (!RiscVMmuEnabled ()) { + return EFI_SUCCESS; + } + + DEBUG ( + ( + DEBUG_VERBOSE, + "%a: Set %llX page attribute 0x%X\n", + __func__, + BaseAddress, + PageAttributesSet + ) + ); + + return UpdateRegionMapping ( + BaseAddress, + Length, + PageAttributesSet, + PTE_ATTRIBUTES_MASK, + (UINTN *)RiscVGetRootTranslateTable (), + TRUE + ); +} + +STATIC +EFI_STATUS +RiscVMmuSetSatpMode ( + UINTN SatpMode + ) +{ + VOID *TranslationTable; + UINTN SatpReg; + UINTN Ppn; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemoryMap; + UINTN NumberOfDescriptors; + UINTN Index; + EFI_STATUS Status; + + switch (SatpMode) { + case SATP_MODE_OFF: + return EFI_SUCCESS; + case SATP_MODE_SV39: + mMaxRootTableLevel =3D 3; + mBitPerLevel =3D 9; + mTableEntryCount =3D 512; + break; + case SATP_MODE_SV48: + mMaxRootTableLevel =3D 4; + mBitPerLevel =3D 9; + mTableEntryCount =3D 512; + break; + case SATP_MODE_SV57: + mMaxRootTableLevel =3D 5; + mBitPerLevel =3D 9; + mTableEntryCount =3D 512; + break; + default: + return EFI_INVALID_PARAMETER; + } + + // Allocate pages for translation table + TranslationTable =3D AllocatePages (1); + if (TranslationTable =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (TranslationTable, mTableEntryCount * sizeof (UINTN)); + + NumberOfDescriptors =3D 0; + MemoryMap =3D NULL; + Status =3D gDS->GetMemorySpaceMap ( + &NumberOfDescriptors, + &MemoryMap + ); + ASSERT_EFI_ERROR (Status); + + for (Index =3D 0; Index < NumberOfDescriptors; Index++) { + if (MemoryMap[Index].GcdMemoryType =3D=3D EfiGcdMemoryTypeMemoryMapped= Io) { + // Default Read/Write attribute for memory mapped IO + UpdateRegionMapping ( + MemoryMap[Index].BaseAddress, + MemoryMap[Index].Length, + RISCV_PG_R | RISCV_PG_W, + PTE_ATTRIBUTES_MASK, + TranslationTable, + FALSE + ); + } else if (MemoryMap[Index].GcdMemoryType =3D=3D EfiGcdMemoryTypeSyste= mMemory) { + // Default Read/Write/Execute attribute for system memory + UpdateRegionMapping ( + MemoryMap[Index].BaseAddress, + MemoryMap[Index].Length, + RISCV_PG_R | RISCV_PG_W | RISCV_PG_X, + PTE_ATTRIBUTES_MASK, + TranslationTable, + FALSE + ); + } + } + + FreePool ((VOID *)MemoryMap); + + if (GetInterruptState ()) { + DisableInterrupts (); + } + + Ppn =3D (UINTN)TranslationTable >> RISCV_MMU_PAGE_SHIFT; + ASSERT (!(Ppn & ~(SATP64_PPN))); + + SatpReg =3D Ppn; + SatpReg |=3D (SatpMode << + SATP64_MODE_SHIFT) & SATP64_MODE; + RiscVSetSupervisorAddressTranslationRegister (SatpReg); + /* Check if HW support the setup satp mode */ + if (SatpReg !=3D RiscVGetSupervisorAddressTranslationRegister ()) { + DEBUG ( + ( + DEBUG_VERBOSE, + "%a: HW does not support SATP mode:%d\n", + __func__, + SatpMode + ) + ); + FreePageTablesRecursive (TranslationTable, 0); + return EFI_DEVICE_ERROR; + } + + RiscVLocalTlbFlushAll (); + + if (GetInterruptState ()) { + EnableInterrupts (); + } + + return Status; +} + +EFI_STATUS +EFIAPI +RiscVConfigureMmu ( + VOID + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + INTN ModeSupport[] =3D { SATP_MODE_SV57, SATP_MODE_SV48, SATP_MOD= E_SV39 }; + INTN Idx; + + /* Try to setup MMU with highest mode as possible */ + for (Idx =3D 0; Idx < ARRAY_SIZE (ModeSupport); Idx++) { + Status =3D RiscVMmuSetSatpMode (ModeSupport[Idx]); + if (Status =3D=3D EFI_DEVICE_ERROR) { + continue; + } else if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ( + ( + DEBUG_INFO, + "%a: SATP mode %d successfully configured\n", + __func__, + ModeSupport[Idx] + ) + ); + break; + } + + return Status; +} diff --git a/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf b/MdePkg/Li= brary/BaseRiscVMmuLib/BaseRiscVMmuLib.inf new file mode 100644 index 000000000000..8ee0127c2144 --- /dev/null +++ b/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf @@ -0,0 +1,25 @@ +## @file +# +# Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001b + BASE_NAME =3D BaseRiscVMmuLib + FILE_GUID =3D d3bc42ee-c9eb-4339-ba11-06747083d3ae + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D RiscVMmuLib + +[Sources] + BaseRiscVMmuLib.c + RiscVMmuCore.S + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib diff --git a/MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S b/MdePkg/Library= /BaseRiscVMmuLib/RiscVMmuCore.S new file mode 100644 index 000000000000..42eec4cbdf83 --- /dev/null +++ b/MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S @@ -0,0 +1,31 @@ +/** @file +* +* Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.<BR> +* +* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ + +#include <Base.h> +#include <Register/RiscV64/RiscVImpl.h> + +.text + .align 3 + +// +// Local tlb flush all. +// +// +ASM_FUNC (RiscVLocalTlbFlushAll) +sfence.vma +ret + +// +// Local tlb flush at a virtual address +// @retval a0 : virtual address. +// +ASM_FUNC ( + RiscVLocalTlbFlush + ) +sfence.vma a0 +ret diff --git a/OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc b/OvmfPkg/RiscVVirt/RiscVV= irt.dsc.inc index 731f54f73f81..083a182655d3 100644 --- a/OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc +++ b/OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc @@ -83,6 +83,7 @@ # RISC-V Architectural Libraries CpuExceptionHandlerLib|UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandler= Lib/BaseRiscV64CpuExceptionHandlerLib.inf RiscVSbiLib|MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf + RiscVMmuLib|MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf PlatformBootManagerLib|OvmfPkg/RiscVVirt/Library/PlatformBootManagerLib/= PlatformBootManagerLib.inf ResetSystemLib|OvmfPkg/RiscVVirt/Library/ResetSystemLib/BaseResetSystemL= ib.inf diff --git a/OvmfPkg/RiscVVirt/Sec/Memory.c b/OvmfPkg/RiscVVirt/Sec/Memory.= c index 0e2690c73687..69041f6404a4 100644 --- a/OvmfPkg/RiscVVirt/Sec/Memory.c +++ b/OvmfPkg/RiscVVirt/Sec/Memory.c @@ -85,21 +85,6 @@ AddMemoryRangeHob ( AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase)); } -/** - Configure MMU -**/ -STATIC -VOID -InitMmu ( - ) -{ - // - // Set supervisor translation mode to Bare mode - // - RiscVSetSupervisorAddressTranslationRegister ((UINT64)SATP_MODE_OFF << 6= 0); - DEBUG ((DEBUG_INFO, "%a: Set Supervisor address mode to bare-metal mode.= \n", __func__)); -} - /** Publish system RAM and reserve memory regions. @@ -327,7 +312,8 @@ MemoryPeimInitialization ( AddReservedMemoryMap (FdtPointer); - InitMmu (); + /* Make sure SEC is booting with bare mode*/ + ASSERT ((RiscVGetSupervisorAddressTranslationRegister () & SATP64_MODE) = =3D=3D (SATP_MODE_OFF << SATP64_MODE_SHIFT)); BuildMemoryTypeInformationHob (); diff --git a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c b/UefiCpuPkg/CpuDxeRiscV64/C= puDxe.c index 25fe3f54c325..2af3b6223450 100644 --- a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c +++ b/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c @@ -296,8 +296,7 @@ CpuSetMemoryAttributes ( IN UINT64 Attributes ) { - DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __f= unc__)); - return EFI_SUCCESS; + return RiscVSetMemoryAttributes (BaseAddress, Length, Attributes); } /** @@ -340,6 +339,12 @@ InitializeCpu ( // DisableInterrupts (); + // + // Enable MMU + // + Status =3D RiscVConfigureMmu (); + ASSERT_EFI_ERROR (Status); + // // Install Boot protocol // diff --git a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h b/UefiCpuPkg/CpuDxeRiscV64/C= puDxe.h index 49f4e119665a..68e6d038b66e 100644 --- a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h +++ b/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h @@ -15,11 +15,13 @@ #include <Protocol/Cpu.h> #include <Protocol/RiscVBootProtocol.h> #include <Library/BaseRiscVSbiLib.h> +#include <Library/BaseRiscVMmuLib.h> #include <Library/BaseLib.h> #include <Library/CpuExceptionHandlerLib.h> #include <Library/DebugLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/UefiDriverEntryPoint.h> +#include <Register/RiscV64/RiscVEncoding.h> /** Flush CPU data cache. If the instruction cache is fully coherent diff --git a/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf b/UefiCpuPkg/CpuDxe= RiscV64/CpuDxeRiscV64.inf index e8fa25446aef..9d9a5ef8f247 100644 --- a/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf +++ b/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf @@ -37,6 +37,8 @@ TimerLib PeCoffGetEntryPointLib RiscVSbiLib + RiscVMmuLib + CacheMaintenanceLib [Sources] CpuDxe.c --_000_MN2PR13MB30225A5769E6AF33496072E0A7419MN2PR13MB3022namp_ Content-Type: text/html; charset="iso-2022-jp" Content-Transfer-Encoding: quoted-printable <html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr= osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" = xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:= //www.w3.org/TR/REC-html40"> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-2022-= jp"> <meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)"> <!--[if !mso]><style>v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style><![endif]--><style><!-- /* Font Definitions */ @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4;} @font-face {font-family:Consolas; panose-1:2 11 6 9 2 2 4 3 2 4;} @font-face {font-family:"Microsoft YaHei"; panose-1:2 11 5 3 2 2 4 2 2 4;} @font-face {font-family:"\@Microsoft YaHei";} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {margin:0in; font-size:10.0pt; font-family:"Calibri",sans-serif;} a:link, span.MsoHyperlink {mso-style-priority:99; color:blue; text-decoration:underline;} a:visited, span.MsoHyperlinkFollowed {mso-style-priority:99; color:purple; text-decoration:underline;} pre {mso-style-priority:99; mso-style-link:"HTML Preformatted Char"; margin:0in; font-size:10.0pt; font-family:"Courier New";} p.msonormal0, li.msonormal0, div.msonormal0 {mso-style-name:msonormal; mso-margin-top-alt:auto; margin-right:0in; mso-margin-bottom-alt:auto; margin-left:0in; font-size:10.0pt; font-family:"Calibri",sans-serif;} span.HTMLPreformattedChar {mso-style-name:"HTML Preformatted Char"; mso-style-priority:99; mso-style-link:"HTML Preformatted"; font-family:Consolas;} span.EmailStyle20 {mso-style-type:personal; font-family:"Calibri",sans-serif; color:windowtext;} span.EmailStyle23 {mso-style-type:personal-reply; font-family:"Calibri",sans-serif; color:windowtext;} .MsoChpDefault {mso-style-type:export-only; font-size:10.0pt; mso-ligatures:none;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in;} div.WordSection1 {page:WordSection1;} --></style><!--[if gte mso 9]><xml> <o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" /> </xml><![endif]--><!--[if gte mso 9]><xml> <o:shapelayout v:ext=3D"edit"> <o:idmap v:ext=3D"edit" data=3D"1" /> </o:shapelayout></xml><![endif]--> </head> <body lang=3D"EN-US" link=3D"blue" vlink=3D"purple" style=3D"word-wrap:brea= k-word"> <div class=3D"WordSection1"> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt">Agree it makes more= sense to put the MMU library into UefiCpuPkg.<o:p></o:p></span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"><o:p> </o:p></= span></p> <div style=3D"border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in = 0in 0in"> <p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt"><b><span style=3D"fon= t-size:12.0pt;color:black">From: </span></b><span style=3D"font-size:12.0pt;color:black">Ni, Ray <ray.ni@= intel.com><br> <b>Date: </b>Wednesday, May 24, 2023 at 2:52 AM<br> <b>To: </b>devel@edk2.groups.io <devel@edk2.groups.io>, lichao@loongs= on.cn <lichao@loongson.cn>, tphan@ventanamicro.com <tphan@ventanam= icro.com>, Ard Biesheuvel <ardb@kernel.org><br> <b>Cc: </b>Kinney, Michael D <michael.d.kinney@intel.com>, Gao, Limin= g <gaoliming@byosoft.com.cn>, Liu, Zhiguang <zhiguang.liu@intel.co= m>, sunilvl@ventanamicro.com <sunilvl@ventanamicro.com>, git@danie= lschaefer.me <git@danielschaefer.me>, Warkentin, Andrei <andrei.warkentin@intel.com><br> <b>Subject: </b>RE: [edk2-devel] [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support= MMU with SV39/48/57 mode<o:p></o:p></span></p> </div> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt">X86 version is in U= efiCpuPkg.<o:p></o:p></span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt">So be consistent, I= would prefer the LoongArch64 version be in UefiCpuPkg as well.<o:p></o:p><= /span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt">I know that ARM has= similar code (I didn=1B$B!G=1B(Bt check in detail, +<a id=3D"OWAAM03DE82E0= 29B74AA8AC5778E62E4A5CEC" href=3D"mailto:ardb@kernel.org"><span style=3D"fo= nt-family:"Calibri",sans-serif;text-decoration:none">@Ard Biesheuvel</span></a>).<o:p></o:p></span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"> <o:p></o:p></= span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt">The trending is to = abstract the memory attribute implementation behind MemoryAttribute PPI/Pro= tocol for using by other modules.<o:p></o:p></span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"> <o:p></o:p></= span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"> <o:p></o:p></= span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt">Thanks,<br> Ray<o:p></o:p></span></p> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"> <o:p></o:p></= span></p> <div> <div style=3D"border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in = 0in 0in"> <p class=3D"MsoNormal"><b><span style=3D"font-size:11.0pt">From:</span></b>= <span style=3D"font-size:11.0pt"> devel@edk2.groups.io <devel@edk2.group= s.io> <b>On Behalf Of </b>Chao Li<br> <b>Sent:</b> Wednesday, May 24, 2023 10:11 AM<br> <b>To:</b> devel@edk2.groups.io; tphan@ventanamicro.com<br> <b>Cc:</b> Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Limin= g <gaoliming@byosoft.com.cn>; Liu, Zhiguang <zhiguang.liu@intel.co= m>; sunilvl@ventanamicro.com; git@danielschaefer.me; Warkentin, Andrei &= lt;andrei.warkentin@intel.com>; Ni, Ray <ray.ni@intel.com><br> <b>Subject:</b> Re: [edk2-devel] [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support= MMU with SV39/48/57 mode<o:p></o:p></span></p> </div> </div> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"> <o:p></o:p></= span></p> <p><span style=3D"font-size:10.0pt">Dear all,</span><o:p></o:p></p> <p><span style=3D"font-size:10.0pt">I'm also porting MMU library of LoongAr= ch64 to EDK2, I added it in to UefiCpuPkg and make it possible to use the s= ame headers for both the no-IA32 and no-X64 platforms, and I also saw that = IA32 and X64 added the CpuPageTableLib to UefiCpuPkg, this library are similar to MMU libraries. I have a questio= n, should the MMU library be in the MdePkg or UefiCpuPkg?</span><o:p></o:p>= </p> <div> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"> <o:p></o:p></= span></p> <div> <p class=3D"MsoNormal"><span style=3D"font-size:8.5pt">Thanks,<br> Chao</span><span style=3D"font-size:11.0pt"><o:p></o:p></span></p> </div> </div> <div> <p class=3D"MsoNormal"><span lang=3D"ZH-CN" style=3D"font-size:11.0pt;font-= family:"Microsoft YaHei",sans-serif;mso-fareast-language:ZH-CN">= =1B$B:_=1B(B</span><span style=3D"font-size:11.0pt"> 2023/4/15 02:58, Tuan = Phan </span><span lang=3D"ZH-CN" style=3D"font-size:11.0pt;font-family:"Mic= rosoft YaHei",sans-serif;mso-fareast-language:ZH-CN">=1B$B<LF;=1B(B</s= pan><span style=3D"font-size:11.0pt">:<o:p></o:p></span></p> </div> <blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt"> <pre>During CpuDxe initialization, MMU will be setup with the highest<o:p><= /o:p></pre> <pre>mode that HW supports.<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre>Signed-off-by: Tuan Phan <a href=3D"mailto:tphan@ventanamicro.com"><= ;tphan@ventanamicro.com></a><o:p></o:p></pre> <pre>---<o:p></o:p></pre> <pre> MdePkg/Include/Library/BaseRiscVMmuLib.h  = ; | 39 ++<o:p></o:p></pre> <pre> .../Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c | 569 +++++++++++++++++= +<o:p></o:p></pre> <pre> .../BaseRiscVMmuLib/BaseRiscVMmuLib.inf = | 25 +<o:p></o:p></pre> <pre> MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S | 31 +<o:p></o:p>= </pre> <pre> OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc &nbs= p; | 1 +<o:p></o:p></pre> <pre> OvmfPkg/RiscVVirt/Sec/Memory.c &nb= sp; | 18 +-<o:p></o:p= ></pre> <pre> UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c = | 9 +-<o:p></o:p></pre> <pre> UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h = | 2 +<o:p></o:p></pre> <pre> UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf | &= nbsp; 2 +<o:p></o:p></pre> <pre> 9 files changed, 678 insertions(+), 18 deletions(-)<o:p></o:p></pre> <pre> create mode 100644 MdePkg/Include/Library/BaseRiscVMmuLib.h<o:p></o:p= ></pre> <pre> create mode 100644 MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c<o= :p></o:p></pre> <pre> create mode 100644 MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf= <o:p></o:p></pre> <pre> create mode 100644 MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S<o:p>= </o:p></pre> <pre> <o:p></o:p></pre> <pre>diff --git a/MdePkg/Include/Library/BaseRiscVMmuLib.h b/MdePkg/Include= /Library/BaseRiscVMmuLib.h<o:p></o:p></pre> <pre>new file mode 100644<o:p></o:p></pre> <pre>index 000000000000..f71d6a4a1e7b<o:p></o:p></pre> <pre>--- /dev/null<o:p></o:p></pre> <pre>+++ b/MdePkg/Include/Library/BaseRiscVMmuLib.h<o:p></o:p></pre> <pre>@@ -0,0 +1,39 @@<o:p></o:p></pre> <pre>+/** @file<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<= ;BR><o:p></o:p></pre> <pre>+ Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Rese= rved.<BR><o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ SPDX-License-Identifier: BSD-2-Clause-Patent<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+**/<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+#ifndef BASE_RISCV_MMU_LIB_H_<o:p></o:p></pre> <pre>+#define BASE_RISCV_MMU_LIB_H_<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+VOID<o:p></o:p></pre> <pre>+EFIAPI<o:p></o:p></pre> <pre>+RiscVLocalTlbFlushAll (<o:p></o:p></pre> <pre>+ VOID<o:p></o:p></pre> <pre>+ );<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+VOID<o:p></o:p></pre> <pre>+EFIAPI<o:p></o:p></pre> <pre>+RiscVLocalTlbFlush (<o:p></o:p></pre> <pre>+ UINTN VirtAddr<o:p></o:p></pre> <pre>+ );<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+EFIAPI<o:p></o:p></pre> <pre>+RiscVSetMemoryAttributes (<o:p></o:p></pre> <pre>+ IN EFI_PHYSICAL_ADDRESS BaseAddress,<o:p></o:p></pre> <pre>+ IN UINT64  = ; Length,<o:p></o:p></pre> <pre>+ IN UINT64  = ; Attributes<o:p></o:p></pre> <pre>+ );<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+EFIAPI<o:p></o:p></pre> <pre>+RiscVConfigureMmu (<o:p></o:p></pre> <pre>+ VOID<o:p></o:p></pre> <pre>+ );<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+#endif /* BASE_RISCV_MMU_LIB_H_ */<o:p></o:p></pre> <pre>diff --git a/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c b/MdePkg= /Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c<o:p></o:p></pre> <pre>new file mode 100644<o:p></o:p></pre> <pre>index 000000000000..230f34261d8b<o:p></o:p></pre> <pre>--- /dev/null<o:p></o:p></pre> <pre>+++ b/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c<o:p></o:p></pre= > <pre>@@ -0,0 +1,569 @@<o:p></o:p></pre> <pre>+/** @file<o:p></o:p></pre> <pre>+* MMU implementation for RISC-V<o:p></o:p></pre> <pre>+*<o:p></o:p></pre> <pre>+* Copyright (c) 2011-2020, ARM Limited. All rights reserved.<o:= p></o:p></pre> <pre>+* Copyright (c) 2016, Linaro Limited. All rights reserved.<o:p>= </o:p></pre> <pre>+* Copyright (c) 2017, Intel Corporation. All rights reserved.&l= t;BR><o:p></o:p></pre> <pre>+* Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Res= erved.<BR><o:p></o:p></pre> <pre>+*<o:p></o:p></pre> <pre>+* SPDX-License-Identifier: BSD-2-Clause-Patent<o:p></o:p></pre> <pre>+*<o:p></o:p></pre> <pre>+**/<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+#include <PiDxe.h><o:p></o:p></pre> <pre>+#include <Uefi.h><o:p></o:p></pre> <pre>+#include <Library/BaseLib.h><o:p></o:p></pre> <pre>+#include <Library/BaseMemoryLib.h><o:p></o:p></pre> <pre>+#include <Library/BaseRiscVMmuLib.h><o:p></o:p></pre> <pre>+#include <Library/CacheMaintenanceLib.h><o:p></o:p></pre> <pre>+#include <Library/DebugLib.h><o:p></o:p></pre> <pre>+#include <Library/DxeServicesTableLib.h><o:p></o:p></pre> <pre>+#include <Library/UefiBootServicesTableLib.h><o:p></o:p></pre> <pre>+#include <Library/MemoryAllocationLib.h><o:p></o:p></pre> <pre>+#include <Library/PcdLib.h><o:p></o:p></pre> <pre>+#include <Register/RiscV64/RiscVEncoding.h><o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+#define RISCV_PG_V &nb= sp; BIT0<o:p></o:p></pre> <pre>+#define RISCV_PG_R &nb= sp; BIT1<o:p></o:p></pre> <pre>+#define RISCV_PG_W &nb= sp; BIT2<o:p></o:p></pre> <pre>+#define RISCV_PG_X &nb= sp; BIT3<o:p></o:p></pre> <pre>+#define RISCV_PG_G &nb= sp; BIT5<o:p></o:p></pre> <pre>+#define RISCV_PG_A &nb= sp; BIT6<o:p></o:p></pre> <pre>+#define RISCV_PG_D &nb= sp; BIT7<o:p></o:p></pre> <pre>+#define PTE_ATTRIBUTES_MASK 0xE<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+#define PTE_PPN_MASK &= nbsp; 0x3FFFFFFFFFFC00ULL<o:p></o:p></pre> <pre>+#define PTE_PPN_SHIFT = 10<o:p></o:p></pre> <pre>+#define RISCV_MMU_PAGE_SHIFT 12<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC UINTN mMaxRootTableLevel;<o:p></o:p></pre> <pre>+STATIC UINTN mBitPerLevel;<o:p></o:p></pre> <pre>+STATIC UINTN mTableEntryCount;<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+BOOLEAN<o:p></o:p></pre> <pre>+RiscVMmuEnabled (<o:p></o:p></pre> <pre>+ VOID<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ return ((RiscVGetSupervisorAddressTranslationRegister () &= <o:p></o:p></pre> <pre>+ SATP64_M= ODE) !=3D (SATP_MODE_OFF << SATP64_MODE_SHIFT));<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+UINTN<o:p></o:p></pre> <pre>+RiscVGetRootTranslateTable (<o:p></o:p></pre> <pre>+ VOID<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ return (RiscVGetSupervisorAddressTranslationRegister () & = SATP64_PPN) <<<o:p></o:p></pre> <pre>+ RISCV_MMU_PAGE_SHIFT= ;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+BOOLEAN<o:p></o:p></pre> <pre>+IsValidPte (<o:p></o:p></pre> <pre>+ IN UINTN Entry<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ if (!(Entry & RISCV_PG_V) ||<o:p></o:p></pre> <pre>+ (((Entry & (RISCV_PG_R | RISCV_PG_= W)) =3D=3D RISCV_PG_W)))<o:p></o:p></pre> <pre>+ {<o:p></o:p></pre> <pre>+ return FALSE;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return TRUE;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+UINTN<o:p></o:p></pre> <pre>+SetValidPte (<o:p></o:p></pre> <pre>+ IN UINTN Entry<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ /* Set Valid and Global mapping bits */<o:p></o:p></pre> <pre>+ return Entry | RISCV_PG_G | RISCV_PG_V;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+BOOLEAN<o:p></o:p></pre> <pre>+IsBlockEntry (<o:p></o:p></pre> <pre>+ IN UINTN Entry<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ return IsValidPte (Entry) &&<o:p></o:p></pre> <pre>+ (Entry & (RISCV_= PG_X | RISCV_PG_R));<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+BOOLEAN<o:p></o:p></pre> <pre>+IsTableEntry (<o:p></o:p></pre> <pre>+ IN UINTN Entry<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ return IsValidPte (Entry) &&<o:p></o:p></pre> <pre>+ !IsBlockEntry (Entry= );<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+UINTN<o:p></o:p></pre> <pre>+SetTableEntry (<o:p></o:p></pre> <pre>+ IN UINTN Entry<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ Entry =3D SetValidPte (Entry);<o:p></o:p></pre> <pre>+ Entry &=3D ~(RISCV_PG_X | RISCV_PG_W | RISCV_PG_R);<o:p></= o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return Entry;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+VOID<o:p></o:p></pre> <pre>+ReplaceTableEntry (<o:p></o:p></pre> <pre>+ IN UINTN *Entry,<o:p></o:p></pre> <pre>+ IN UINTN Value,<o:p></o:p></pre> <pre>+ IN UINTN RegionStart,<o:p></o:p></pre> <pre>+ IN BOOLEAN IsLiveBlockMapping<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ *Entry =3D Value;<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (IsLiveBlockMapping && RiscVMmuEnabled ()) {<o:p></= o:p></pre> <pre>+ RiscVLocalTlbFlush (RegionStart);<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+UINTN<o:p></o:p></pre> <pre>+GetPpnfromPte (<o:p></o:p></pre> <pre>+ UINTN Entry,<o:p></o:p></pre> <pre>+ UINTN Level<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ return ((Entry & PTE_PPN_MASK) >> PTE_PPN_SHIFT);<o:= p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+UINTN<o:p></o:p></pre> <pre>+SetPpnToPte (<o:p></o:p></pre> <pre>+ UINTN Entry,<o:p></o:p></pre> <pre>+ UINTN Address,<o:p></o:p></pre> <pre>+ UINTN Level<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ UINTN Ppn;<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ Ppn =3D ((Address >> RISCV_MMU_PAGE_SHIFT) << PTE_= PPN_SHIFT);<o:p></o:p></pre> <pre>+ ASSERT (~(Ppn & ~PTE_PPN_MASK));<o:p></o:p></pre> <pre>+ Entry &=3D ~PTE_PPN_MASK;<o:p></o:p></pre> <pre>+ return Entry | Ppn;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+VOID<o:p></o:p></pre> <pre>+FreePageTablesRecursive (<o:p></o:p></pre> <pre>+ IN UINTN *TranslationTable,<o:p></o:p></pre> <pre>+ IN UINTN Level<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ UINTN Index;<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (Level < mMaxRootTableLevel - 1) {<o:p></o:p></pre> <pre>+ for (Index =3D 0; Index < mTableEntryCount; Ind= ex++) {<o:p></o:p></pre> <pre>+ if (IsTableEntry (TranslationTable[Ind= ex])) {<o:p></o:p></pre> <pre>+ FreePageTablesRecursive (<= o:p></o:p></pre> <pre>+ &nb= sp; = (UINTN *)(GetPpnfromPte ((= TranslationTable[Index]), Level) <<<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; RISCV_MMU_PAGE_SHIFT),<o:p></o:p></pre> <pre>+ &nb= sp; = Level + 1<o:p></o:p></pre> <pre>+ &nb= sp; = );<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ FreePages (TranslationTable, 1);<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+UpdateRegionMappingRecursive (<o:p></o:p></pre> <pre>+ IN UINTN RegionStart,<o:p></o:p></pre> <pre>+ IN UINTN RegionEnd,<o:p></o:p></pre> <pre>+ IN UINTN AttributeSetMask,<o:p></o:p><= /pre> <pre>+ IN UINTN AttributeClearMask,<o:p></o:p= ></pre> <pre>+ IN UINTN *PageTable,<o:p></o:p></pre> <pre>+ IN UINTN Level,<o:p></o:p></pre> <pre>+ IN BOOLEAN TableIsLive<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ EFI_STATUS Status;<o:p></o:p></pre> <pre>+ UINTN BlockShift;<o:p></o:= p></pre> <pre>+ UINTN BlockMask;<o:p></o:p= ></pre> <pre>+ UINTN BlockEnd;<o:p></o:p>= </pre> <pre>+ UINTN *Entry;<o:p></o:p></= pre> <pre>+ UINTN EntryValue;<o:p></o:= p></pre> <pre>+ UINTN *TranslationTable;<o= :p></o:p></pre> <pre>+ BOOLEAN NextTableIsLive;<o:p></o:p></p= re> <pre>+<o:p></o:p></pre> <pre>+ ASSERT (Level < mMaxRootTableLevel);<o:p></o:p></pre> <pre>+ ASSERT (((RegionStart | RegionEnd) & EFI_PAGE_MASK) =3D=3D= 0);<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ BlockShift =3D (mMaxRootTableLevel - Level - 1) * mBitPerLevel= + RISCV_MMU_PAGE_SHIFT;<o:p></o:p></pre> <pre>+ BlockMask =3D MAX_ADDRESS >> (64 - BlockShift);<o:= p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ DEBUG (<o:p></o:p></pre> <pre>+ (<o:p></o:p></pre> <pre>+ DEBUG_VERBOSE,= <o:p></o:p></pre> <pre>+ "%a(%d): = %llx - %llx set %lx clr %lx\n",<o:p></o:p></pre> <pre>+ __func__,<o:p>= </o:p></pre> <pre>+ Level,<o:p></o= :p></pre> <pre>+ RegionStart,<o= :p></o:p></pre> <pre>+ RegionEnd,<o:p= ></o:p></pre> <pre>+ AttributeSetMa= sk,<o:p></o:p></pre> <pre>+ AttributeClear= Mask<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+ );<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ for ( ; RegionStart < RegionEnd; RegionStart =3D BlockEnd) = {<o:p></o:p></pre> <pre>+ BlockEnd =3D MIN (RegionEnd, (RegionStart | BlockM= ask) + 1);<o:p></o:p></pre> <pre>+ Entry =3D &PageTable[(Region= Start >> BlockShift) & (mTableEntryCount - 1)];<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ // If RegionStart or BlockEnd is not aligned to th= e block size at this<o:p></o:p></pre> <pre>+ // level, we will have to create a table mapping i= n order to map less<o:p></o:p></pre> <pre>+ // than a block, and recurse to create the block o= r page entries at<o:p></o:p></pre> <pre>+ // the next level. No block mappings are allowed a= t all at level 0,<o:p></o:p></pre> <pre>+ // so in that case, we have to recurse uncondition= ally.<o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ if ((Level =3D=3D 0) ||<o:p></o:p></pre> <pre>+ (((RegionStart | BlockEnd)= & BlockMask) !=3D 0) || IsTableEntry (*Entry))<o:p></o:p></pre> <pre>+ {<o:p></o:p></pre> <pre>+ ASSERT (Level < mMaxRootTableLevel = - 1);<o:p></o:p></pre> <pre>+ if (!IsTableEntry (*Entry)) {<o:p></o:= p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ // No table entry exists y= et, so we need to allocate a page table<o:p></o:p></pre> <pre>+ // for the next level.<o:p= ></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ TranslationTable =3D Alloc= atePages (1);<o:p></o:p></pre> <pre>+ if (TranslationTable =3D= =3D NULL) {<o:p></o:p></pre> <pre>+ return EFI_OUT= _OF_RESOURCES;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ ZeroMem (TranslationTable,= EFI_PAGE_SIZE);<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (IsBlockEntry (*Entry))= {<o:p></o:p></pre> <pre>+ //<o:p></o:p><= /pre> <pre>+ // We are spli= tting an existing block entry, so we have to populate<o:p></o:p></pre> <pre>+ // the new tab= le with the attributes of the block entry it replaces.<o:p></o:p></pre> <pre>+ //<o:p></o:p><= /pre> <pre>+ Status =3D Upd= ateRegionMappingRecursive (<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; Regio= nStart & ~BlockMask,<o:p></o:p></pre> <pre>+ &n= bsp;  = ; &n= bsp; (Regi= onStart | BlockMask) + 1,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; *Entr= y & PTE_ATTRIBUTES_MASK,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; PTE_A= TTRIBUTES_MASK,<o:p></o:p></pre> <pre>+ &nb= sp; = &n= bsp; Trans= lationTable,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; Level= + 1,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; FALSE= <o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; );<o:= p></o:p></pre> <pre>+ if (EFI_ERROR = (Status)) {<o:p></o:p></pre> <pre>+ //= <o:p></o:p></pre> <pre>+ //= The range we passed to UpdateRegionMappingRecursive () is block<o:p></o:p>= </pre> <pre>+ //= aligned, so it is guaranteed that no further pages were allocated<o:p></o:= p></pre> <pre>+ //= by it, and so we only have to free the page we allocated here.<o:p></o:p><= /pre> <pre>+ //= <o:p></o:p></pre> <pre>+ Fr= eePages (TranslationTable, 1);<o:p></o:p></pre> <pre>+ re= turn Status;<o:p></o:p></pre> <pre>+ }<o:p></o:p></= pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ NextTableIsLive =3D FALSE;= <o:p></o:p></pre> <pre>+ } else {<o:p></o:p></pre> <pre>+ TranslationTable =3D (UINT= N *)(GetPpnfromPte (*Entry, Level) << RISCV_MMU_PAGE_SHIFT);<o:p></o:= p></pre> <pre>+ NextTableIsLive =3D = TableIsLive;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ // Recurse to the next level<o:p></o:p= ></pre> <pre>+ //<o:p></o:p></pre> <pre>+ Status =3D UpdateRegionMappingRecursiv= e (<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; RegionStart,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; BlockEnd,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; AttributeSetMask,<o:p></o:p><= /pre> <pre>+ &nb= sp; = &nb= sp; AttributeClearMask,<o:p></o:p= ></pre> <pre>+ &nb= sp; = &nb= sp; TranslationTable,<o:p></o:p><= /pre> <pre>+ &nb= sp; = &nb= sp; Level + 1,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; NextTableIsLive<o:p></o:p></p= re> <pre>+ &nb= sp; = &nb= sp; );<o:p></o:p></pre> <pre>+ if (EFI_ERROR (Status)) {<o:p></o:p></= pre> <pre>+ if (!IsTableEntry (*Entry)= ) {<o:p></o:p></pre> <pre>+ //<o:p></o:p><= /pre> <pre>+ // We are crea= ting a new table entry, so on failure, we can free all<o:p></o:p></pre> <pre>+ // allocations= we made recursively, given that the whole subhierarchy<o:p></o:p></pre> <pre>+ // has not bee= n wired into the live page tables yet. (This is not<o:p></o:p></pre> <pre>+ // possible fo= r existing table entries, since we cannot revert the<o:p></o:p></pre> <pre>+ // modificatio= ns we made to the subhierarchy it represents.)<o:p></o:p></pre> <pre>+ //<o:p></o:p><= /pre> <pre>+ FreePageTables= Recursive (TranslationTable, Level + 1);<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return Status;<o:p></o:p><= /pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (!IsTableEntry (*Entry)) {<o:p></o:= p></pre> <pre>+ EntryValue =3D SetPpnToPte= (0, (UINTN)TranslationTable, Level);<o:p></o:p></pre> <pre>+ EntryValue =3D SetTableEnt= ry (EntryValue);<o:p></o:p></pre> <pre>+ ReplaceTableEntry (<o:p></= o:p></pre> <pre>+ &nb= sp; = Entry,<o:p></o:p></pre> <pre>+ &nb= sp; = EntryValue,<o:p></o:p></pre> <pre>+ &nb= sp; = RegionStart,<o:p></o:p></pre> <pre>+ &nb= sp; = TableIsLive<o:p></o:p></pre> <pre>+ &nb= sp; = );<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+ } else {<o:p></o:p></pre> <pre>+ EntryValue =3D (*Entry & ~Attribut= eClearMask) | AttributeSetMask;<o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ // We don't have page fault exception = handler when a virtual page is accessed and<o:p></o:p></pre> <pre>+ // the A bit is clear, or is written a= nd the D bit is clear.<o:p></o:p></pre> <pre>+ // So just set A for read and D for wr= ite permission.<o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ if (AttributeSetMask & RISCV_PG_R)= {<o:p></o:p></pre> <pre>+ EntryValue |=3D RISCV_PG_A= ;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (AttributeSetMask & RISCV_PG_W)= {<o:p></o:p></pre> <pre>+ EntryValue |=3D RISCV_PG_D= ;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ EntryValue =3D SetPpnToPte (EntryValue= , RegionStart, Level);<o:p></o:p></pre> <pre>+ EntryValue =3D SetValidPte (EntryValue= );<o:p></o:p></pre> <pre>+ ReplaceTableEntry (Entry, EntryValue, = RegionStart, TableIsLive);<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return EFI_SUCCESS;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+UpdateRegionMapping (<o:p></o:p></pre> <pre>+ IN UINTN RegionStart,<o:p></o:p></pre> <pre>+ IN UINTN RegionLength,<o:p></o:p></pre= > <pre>+ IN UINTN AttributeSetMask,<o:p></o:p><= /pre> <pre>+ IN UINTN AttributeClearMask,<o:p></o:p= ></pre> <pre>+ IN UINTN *RootTable,<o:p></o:p></pre> <pre>+ IN BOOLEAN TableIsLive<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ if (((RegionStart | RegionLength) & EFI_PAGE_MASK) !=3D 0)= {<o:p></o:p></pre> <pre>+ return EFI_INVALID_PARAMETER;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return UpdateRegionMappingRecursive (<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; RegionStart,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; RegionStart + RegionLength,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; AttributeSetMask,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; AttributeClearMask,<o:p></o:p></pre> <pre>+ &n= bsp;  = ; &n= bsp; RootTable,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; 0,<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; TableIsLive<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; );<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+UINTN<o:p></o:p></pre> <pre>+GcdAttributeToPageAttribute (<o:p></o:p></pre> <pre>+ IN UINTN GcdAttributes<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ UINTN RiscVAttributes =3D RISCV_PG_R | RISCV_PG_W | RISC= V_PG_X;<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ // Determine protection attributes<o:p></o:p></pre> <pre>+ if (GcdAttributes & EFI_MEMORY_RO) {<o:p></o:p></pre> <pre>+ RiscVAttributes &=3D ~(RISCV_PG_W);<o:p></o:p>= </pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ // Process eXecute Never attribute<o:p></o:p></pre> <pre>+ if (GcdAttributes & EFI_MEMORY_XP) {<o:p></o:p></pre> <pre>+ RiscVAttributes &=3D ~RISCV_PG_X;<o:p></o:p></= pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return RiscVAttributes;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+EFIAPI<o:p></o:p></pre> <pre>+RiscVSetMemoryAttributes (<o:p></o:p></pre> <pre>+ IN EFI_PHYSICAL_ADDRESS BaseAddress,<o:p></o:p></pre> <pre>+ IN UINTN  = ; Length,<o:p></o:p></pre> <pre>+ IN UINTN = Attributes<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ UINTN PageAttributesSet =3D GcdAttributeToPageAttribute = (Attributes);<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (!RiscVMmuEnabled ()) {<o:p></o:p></pre> <pre>+ return EFI_SUCCESS;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ DEBUG (<o:p></o:p></pre> <pre>+ (<o:p></o:p></pre> <pre>+ DEBUG_VERBOSE,= <o:p></o:p></pre> <pre>+ "%a: Set = %llX page attribute 0x%X\n",<o:p></o:p></pre> <pre>+ __func__,<o:p>= </o:p></pre> <pre>+ BaseAddress,<o= :p></o:p></pre> <pre>+ PageAttributes= Set<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+ );<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return UpdateRegionMapping (<o:p></o:p></pre> <pre>+ &nb= sp; = BaseAddress,<o:p></o:p></pre> <pre>+ &nb= sp;  = ; Length,<o:p></o:p></pre> <pre>+ &nb= sp; = PageAttributesSet,<o:p></o:p></pre> <pre>+ &nb= sp; = PTE_ATTRIBUTES_MASK,<o:p></o:p></pre> <pre>+ &nb= sp; = (UINTN *)RiscVGetRootTranslateTable (),<o:p>= </o:p></pre> <pre>+ &nb= sp; = TRUE<o:p></o:p></pre> <pre>+ &nb= sp;  = ; );<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+STATIC<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+RiscVMmuSetSatpMode (<o:p></o:p></pre> <pre>+ UINTN SatpMode<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ VOID &nbs= p; &= nbsp; *TranslationTable;<o:p></o:p></pre> <pre>+ UINTN &nb= sp; = SatpReg;<o:p></o:p></pre> <pre>+ UINTN &nb= sp; = Ppn;<o:p></o:p></pre> <pre>+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemoryMap;<o:p></o:p></= pre> <pre>+ UINTN &nb= sp; = NumberOfDescriptors;<o:p></o:p></pre> <pre>+ UINTN &nb= sp; = Index;<o:p></o:p></pre> <pre>+ EFI_STATUS &nbs= p; &= nbsp; Status;<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ switch (SatpMode) {<o:p></o:p></pre> <pre>+ case SATP_MODE_OFF:<o:p></o:p></pre> <pre>+ return EFI_SUCCESS;<o:p></o:p></pre> <pre>+ case SATP_MODE_SV39:<o:p></o:p></pre> <pre>+ mMaxRootTableLevel =3D 3;<o:p></o:p></= pre> <pre>+ mBitPerLevel &n= bsp; =3D 9;<o:p></o:p></pre> <pre>+ mTableEntryCount =3D 512;<= o:p></o:p></pre> <pre>+ break;<o:p></o:p></pre> <pre>+ case SATP_MODE_SV48:<o:p></o:p></pre> <pre>+ mMaxRootTableLevel =3D 4;<o:p></o:p></= pre> <pre>+ mBitPerLevel &n= bsp; =3D 9;<o:p></o:p></pre> <pre>+ mTableEntryCount =3D 512;<= o:p></o:p></pre> <pre>+ break;<o:p></o:p></pre> <pre>+ case SATP_MODE_SV57:<o:p></o:p></pre> <pre>+ mMaxRootTableLevel =3D 5;<o:p></o:p></= pre> <pre>+ mBitPerLevel &n= bsp; =3D 9;<o:p></o:p></pre> <pre>+ mTableEntryCount =3D 512;<= o:p></o:p></pre> <pre>+ break;<o:p></o:p></pre> <pre>+ default:<o:p></o:p></pre> <pre>+ return EFI_INVALID_PARAMETER;<o:p></o:= p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ // Allocate pages for translation table<o:p></o:p></pre> <pre>+ TranslationTable =3D AllocatePages (1);<o:p></o:p></pre> <pre>+ if (TranslationTable =3D=3D NULL) {<o:p></o:p></pre> <pre>+ return EFI_OUT_OF_RESOURCES;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ ZeroMem (TranslationTable, mTableEntryCount * sizeof (UINTN));= <o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ NumberOfDescriptors =3D 0;<o:p></o:p></pre> <pre>+ MemoryMap  = ; =3D NULL;<o:p></o:p></pre> <pre>+ Status &n= bsp; =3D gDS->GetMemorySpaceMap (<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; &Number= OfDescriptors,<o:p></o:p></pre> <pre>+ &n= bsp;  = ; &n= bsp; &Memory= Map<o:p></o:p></pre> <pre>+ &nb= sp; = &nb= sp; );<o:p></o:= p></pre> <pre>+ ASSERT_EFI_ERROR (Status);<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ for (Index =3D 0; Index < NumberOfDescriptors; Index++) {<o= :p></o:p></pre> <pre>+ if (MemoryMap[Index].GcdMemoryType =3D=3D EfiGcdMe= moryTypeMemoryMappedIo) {<o:p></o:p></pre> <pre>+ // Default Read/Write attribute for me= mory mapped IO<o:p></o:p></pre> <pre>+ UpdateRegionMapping (<o:p></o:p></pre> <pre>+ &nb= sp; = MemoryMap[Index].BaseAddress,<o:p></o:p></pre> <pre>+ &nb= sp; = MemoryMap[Index].Length,<o:p></o:p></pre> <pre>+ &nb= sp; = RISCV_PG_R | RISCV_PG_W,<o:p></o:p></pre> <pre>+ &nb= sp; = PTE_ATTRIBUTES_MASK,<o:p></o:p></pre> <pre>+ &nb= sp; = TranslationTable,<o:p></o:p></pre> <pre>+ &nb= sp; = FALSE<o:p></o:p></pre> <pre>+ &nb= sp; = );<o:p></o:p></pre> <pre>+ } else if (MemoryMap[Index].GcdMemoryType =3D=3D E= fiGcdMemoryTypeSystemMemory) {<o:p></o:p></pre> <pre>+ // Default Read/Write/Execute attribut= e for system memory<o:p></o:p></pre> <pre>+ UpdateRegionMapping (<o:p></o:p></pre> <pre>+ &nb= sp; = MemoryMap[Index].BaseAddress,<o:p></o:p></pre> <pre>+ &nb= sp; = MemoryMap[Index].Length,<o:p></o:p></pre> <pre>+ &nb= sp; = RISCV_PG_R | RISCV_PG_W | RISCV_PG_X,<o:p></o:p></pre> <pre>+ &nb= sp; = PTE_ATTRIBUTES_MASK,<o:p></o:p></pre> <pre>+ &nb= sp; = TranslationTable,<o:p></o:p></pre> <pre>+ &nb= sp; = FALSE<o:p></o:p></pre> <pre>+ &nb= sp; = );<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ FreePool ((VOID *)MemoryMap);<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (GetInterruptState ()) {<o:p></o:p></pre> <pre>+ DisableInterrupts ();<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ Ppn =3D (UINTN)TranslationTable >> RISCV_MMU_PAGE_SHIFT;= <o:p></o:p></pre> <pre>+ ASSERT (!(Ppn & ~(SATP64_PPN)));<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ SatpReg =3D Ppn;<o:p></o:p></pre> <pre>+ SatpReg |=3D (SatpMode <<<o:p></o:p></pre> <pre>+ &nb= sp; SATP64_MODE_SHIFT) & SATP64_MODE;<o:p></o:p></pre> <pre>+ RiscVSetSupervisorAddressTranslationRegister (SatpReg);<o:p></= o:p></pre> <pre>+ /* Check if HW support the setup satp mode */<o:p></o:p></pre> <pre>+ if (SatpReg !=3D RiscVGetSupervisorAddressTranslationRegister = ()) {<o:p></o:p></pre> <pre>+ DEBUG (<o:p></o:p></pre> <pre>+ (<o:p></= o:p></pre> <pre>+ DE= BUG_VERBOSE,<o:p></o:p></pre> <pre>+ &q= uot;%a: HW does not support SATP mode:%d\n",<o:p></o:p></pre> <pre>+ __= func__,<o:p></o:p></pre> <pre>+ Sa= tpMode<o:p></o:p></pre> <pre>+ )<o:p></= o:p></pre> <pre>+ );<o:p><= /o:p></pre> <pre>+ FreePageTablesRecursive (TranslationTable, 0);<o:p= ></o:p></pre> <pre>+ return EFI_DEVICE_ERROR;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ RiscVLocalTlbFlushAll ();<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ if (GetInterruptState ()) {<o:p></o:p></pre> <pre>+ EnableInterrupts ();<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return Status;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+EFI_STATUS<o:p></o:p></pre> <pre>+EFIAPI<o:p></o:p></pre> <pre>+RiscVConfigureMmu (<o:p></o:p></pre> <pre>+ VOID<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+{<o:p></o:p></pre> <pre>+ EFI_STATUS Status =3D EFI_SUCCESS;<o:p></o:p></pre> <pre>+ INTN ModeSupport[] = =3D { SATP_MODE_SV57, SATP_MODE_SV48, SATP_MODE_SV39 };<o:p></o:p></pre> <pre>+ INTN Idx;<o:p></o:p>= </pre> <pre>+<o:p></o:p></pre> <pre>+ /* Try to setup MMU with highest mode as possible */<o:p></o:p= ></pre> <pre>+ for (Idx =3D 0; Idx < ARRAY_SIZE (ModeSupport); Idx++) {<o:= p></o:p></pre> <pre>+ Status =3D RiscVMmuSetSatpMode (ModeSupport[Idx]);= <o:p></o:p></pre> <pre>+ if (Status =3D=3D EFI_DEVICE_ERROR) {<o:p></o:p></= pre> <pre>+ continue;<o:p></o:p></pre> <pre>+ } else if (EFI_ERROR (Status)) {<o:p></o:p></pre> <pre>+ return Status;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ DEBUG (<o:p></o:p></pre> <pre>+ (<o:p></= o:p></pre> <pre>+ DE= BUG_INFO,<o:p></o:p></pre> <pre>+ &q= uot;%a: SATP mode %d successfully configured\n",<o:p></o:p></pre> <pre>+ __= func__,<o:p></o:p></pre> <pre>+ Mo= deSupport[Idx]<o:p></o:p></pre> <pre>+ )<o:p></= o:p></pre> <pre>+ );<o:p><= /o:p></pre> <pre>+ break;<o:p></o:p></pre> <pre>+ }<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+ return Status;<o:p></o:p></pre> <pre>+}<o:p></o:p></pre> <pre>diff --git a/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf b/MdeP= kg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf<o:p></o:p></pre> <pre>new file mode 100644<o:p></o:p></pre> <pre>index 000000000000..8ee0127c2144<o:p></o:p></pre> <pre>--- /dev/null<o:p></o:p></pre> <pre>+++ b/MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf<o:p></o:p></p= re> <pre>@@ -0,0 +1,25 @@<o:p></o:p></pre> <pre>+## @file<o:p></o:p></pre> <pre>+#<o:p></o:p></pre> <pre>+# Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Res= erved.<BR><o:p></o:p></pre> <pre>+#<o:p></o:p></pre> <pre>+# SPDX-License-Identifier: BSD-2-Clause-Patent<o:p></o:p></pre> <pre>+#<o:p></o:p></pre> <pre>+##<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+[Defines]<o:p></o:p></pre> <pre>+ INF_VERSION = =3D 0x0001001b<o:p></o:p></pre> <pre>+ BASE_NAME  = ; =3D BaseRiscVMmuLib<o:p></o:p></pre> <pre>+ FILE_GUID  = ; =3D d3bc42ee-c9eb-4339-ba11-06747083d3ae<o:p></o:p></pre> <pre>+ MODULE_TYPE = =3D BASE<o:p></o:p></pre> <pre>+ VERSION_STRING =3D 1.0<o:p></o:p= ></pre> <pre>+ LIBRARY_CLASS =3D RiscVMmu= Lib<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+[Sources]<o:p></o:p></pre> <pre>+ BaseRiscVMmuLib.c<o:p></o:p></pre> <pre>+ RiscVMmuCore.S<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+[Packages]<o:p></o:p></pre> <pre>+ MdePkg/MdePkg.dec<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+[LibraryClasses]<o:p></o:p></pre> <pre>+ BaseLib<o:p></o:p></pre> <pre>diff --git a/MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S b/MdePkg/Li= brary/BaseRiscVMmuLib/RiscVMmuCore.S<o:p></o:p></pre> <pre>new file mode 100644<o:p></o:p></pre> <pre>index 000000000000..42eec4cbdf83<o:p></o:p></pre> <pre>--- /dev/null<o:p></o:p></pre> <pre>+++ b/MdePkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S<o:p></o:p></pre> <pre>@@ -0,0 +1,31 @@<o:p></o:p></pre> <pre>+/** @file<o:p></o:p></pre> <pre>+*<o:p></o:p></pre> <pre>+* Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Res= erved.<BR><o:p></o:p></pre> <pre>+*<o:p></o:p></pre> <pre>+* SPDX-License-Identifier: BSD-2-Clause-Patent<o:p></o:p></pre> <pre>+*<o:p></o:p></pre> <pre>+**/<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+#include <Base.h><o:p></o:p></pre> <pre>+#include <Register/RiscV64/RiscVImpl.h><o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+.text<o:p></o:p></pre> <pre>+ .align 3<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+//<o:p></o:p></pre> <pre>+// Local tlb flush all.<o:p></o:p></pre> <pre>+//<o:p></o:p></pre> <pre>+//<o:p></o:p></pre> <pre>+ASM_FUNC (RiscVLocalTlbFlushAll)<o:p></o:p></pre> <pre>+sfence.vma<o:p></o:p></pre> <pre>+ret<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre>+//<o:p></o:p></pre> <pre>+// Local tlb flush at a virtual address<o:p></o:p></pre> <pre>+// @retval a0 : virtual address.<o:p></o:p></pre> <pre>+//<o:p></o:p></pre> <pre>+ASM_FUNC (<o:p></o:p></pre> <pre>+ RiscVLocalTlbFlush<o:p></o:p></pre> <pre>+ )<o:p></o:p></pre> <pre>+sfence.vma a0<o:p></o:p></pre> <pre>+ret<o:p></o:p></pre> <pre>diff --git a/OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc b/OvmfPkg/RiscVVirt/R= iscVVirt.dsc.inc<o:p></o:p></pre> <pre>index 731f54f73f81..083a182655d3 100644<o:p></o:p></pre> <pre>--- a/OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc<o:p></o:p></pre> <pre>+++ b/OvmfPkg/RiscVVirt/RiscVVirt.dsc.inc<o:p></o:p></pre> <pre>@@ -83,6 +83,7 @@<o:p></o:p></pre> <pre> # RISC-V Architectural Libraries<o:p></o:p></pre> <pre> CpuExceptionHandlerLib|UefiCpuPkg/Library/BaseRiscV64CpuE= xceptionHandlerLib/BaseRiscV64CpuExceptionHandlerLib.inf<o:p></o:p></pre> <pre> RiscVSbiLib|MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLi= b.inf<o:p></o:p></pre> <pre>+ RiscVMmuLib|MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf= <o:p></o:p></pre> <pre> PlatformBootManagerLib|OvmfPkg/RiscVVirt/Library/Platform= BootManagerLib/PlatformBootManagerLib.inf<o:p></o:p></pre> <pre> ResetSystemLib|OvmfPkg/RiscVVirt/Library/ResetSystemLib/B= aseResetSystemLib.inf<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre>diff --git a/OvmfPkg/RiscVVirt/Sec/Memory.c b/OvmfPkg/RiscVVirt/Sec/Me= mory.c<o:p></o:p></pre> <pre>index 0e2690c73687..69041f6404a4 100644<o:p></o:p></pre> <pre>--- a/OvmfPkg/RiscVVirt/Sec/Memory.c<o:p></o:p></pre> <pre>+++ b/OvmfPkg/RiscVVirt/Sec/Memory.c<o:p></o:p></pre> <pre>@@ -85,21 +85,6 @@ AddMemoryRangeHob (<o:p></o:p></pre> <pre> AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - = MemoryBase));<o:p></o:p></pre> <pre> }<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre>-/**<o:p></o:p></pre> <pre>- Configure MMU<o:p></o:p></pre> <pre>-**/<o:p></o:p></pre> <pre>-STATIC<o:p></o:p></pre> <pre>-VOID<o:p></o:p></pre> <pre>-InitMmu (<o:p></o:p></pre> <pre>- )<o:p></o:p></pre> <pre>-{<o:p></o:p></pre> <pre>- //<o:p></o:p></pre> <pre>- // Set supervisor translation mode to Bare mode<o:p></o:p></pr= e> <pre>- //<o:p></o:p></pre> <pre>- RiscVSetSupervisorAddressTranslationRegister ((UINT64)SATP_MOD= E_OFF << 60);<o:p></o:p></pre> <pre>- DEBUG ((DEBUG_INFO, "%a: Set Supervisor address mode to b= are-metal mode.\n", __func__));<o:p></o:p></pre> <pre>-}<o:p></o:p></pre> <pre>-<o:p></o:p></pre> <pre> /**<o:p></o:p></pre> <pre> Publish system RAM and reserve memory regions.<o:p></o:p>= </pre> <pre> <o:p></o:p></pre> <pre>@@ -327,7 +312,8 @@ MemoryPeimInitialization (<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre> AddReservedMemoryMap (FdtPointer);<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre>- InitMmu ();<o:p></o:p></pre> <pre>+ /* Make sure SEC is booting with bare mode*/<o:p></o:p></pre> <pre>+ ASSERT ((RiscVGetSupervisorAddressTranslationRegister () &= SATP64_MODE) =3D=3D (SATP_MODE_OFF << SATP64_MODE_SHIFT));<o:p></o:p= ></pre> <pre> <o:p></o:p></pre> <pre> BuildMemoryTypeInformationHob ();<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre>diff --git a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c b/UefiCpuPkg/CpuDxeRisc= V64/CpuDxe.c<o:p></o:p></pre> <pre>index 25fe3f54c325..2af3b6223450 100644<o:p></o:p></pre> <pre>--- a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c<o:p></o:p></pre> <pre>+++ b/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c<o:p></o:p></pre> <pre>@@ -296,8 +296,7 @@ CpuSetMemoryAttributes (<o:p></o:p></pre> <pre> IN UINT64 = Attributes<o:p></o:p></pre= > <pre> )<o:p></o:p></pre> <pre> {<o:p></o:p></pre> <pre>- DEBUG ((DEBUG_INFO, "%a: Set memory attributes not suppor= ted yet\n", __func__));<o:p></o:p></pre> <pre>- return EFI_SUCCESS;<o:p></o:p></pre> <pre>+ return RiscVSetMemoryAttributes (BaseAddress, Length, Attribut= es);<o:p></o:p></pre> <pre> }<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre> /**<o:p></o:p></pre> <pre>@@ -340,6 +339,12 @@ InitializeCpu (<o:p></o:p></pre> <pre> //<o:p></o:p></pre> <pre> DisableInterrupts ();<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ // Enable MMU<o:p></o:p></pre> <pre>+ //<o:p></o:p></pre> <pre>+ Status =3D RiscVConfigureMmu ();<o:p></o:p></pre> <pre>+ ASSERT_EFI_ERROR (Status);<o:p></o:p></pre> <pre>+<o:p></o:p></pre> <pre> //<o:p></o:p></pre> <pre> // Install Boot protocol<o:p></o:p></pre> <pre> //<o:p></o:p></pre> <pre>diff --git a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h b/UefiCpuPkg/CpuDxeRisc= V64/CpuDxe.h<o:p></o:p></pre> <pre>index 49f4e119665a..68e6d038b66e 100644<o:p></o:p></pre> <pre>--- a/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h<o:p></o:p></pre> <pre>+++ b/UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h<o:p></o:p></pre> <pre>@@ -15,11 +15,13 @@<o:p></o:p></pre> <pre> #include <Protocol/Cpu.h><o:p></o:p></pre> <pre> #include <Protocol/RiscVBootProtocol.h><o:p></o:p></pre> <pre> #include <Library/BaseRiscVSbiLib.h><o:p></o:p></pre> <pre>+#include <Library/BaseRiscVMmuLib.h><o:p></o:p></pre> <pre> #include <Library/BaseLib.h><o:p></o:p></pre> <pre> #include <Library/CpuExceptionHandlerLib.h><o:p></o:p></pre> <pre> #include <Library/DebugLib.h><o:p></o:p></pre> <pre> #include <Library/UefiBootServicesTableLib.h><o:p></o:p></pre> <pre> #include <Library/UefiDriverEntryPoint.h><o:p></o:p></pre> <pre>+#include <Register/RiscV64/RiscVEncoding.h><o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre> /**<o:p></o:p></pre> <pre> Flush CPU data cache. If the instruction cache is fully c= oherent<o:p></o:p></pre> <pre>diff --git a/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf b/UefiCpuPkg/C= puDxeRiscV64/CpuDxeRiscV64.inf<o:p></o:p></pre> <pre>index e8fa25446aef..9d9a5ef8f247 100644<o:p></o:p></pre> <pre>--- a/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf<o:p></o:p></pre> <pre>+++ b/UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf<o:p></o:p></pre> <pre>@@ -37,6 +37,8 @@<o:p></o:p></pre> <pre> TimerLib<o:p></o:p></pre> <pre> PeCoffGetEntryPointLib<o:p></o:p></pre> <pre> RiscVSbiLib<o:p></o:p></pre> <pre>+ RiscVMmuLib<o:p></o:p></pre> <pre>+ CacheMaintenanceLib<o:p></o:p></pre> <pre> <o:p></o:p></pre> <pre> [Sources]<o:p></o:p></pre> <pre> CpuDxe.c<o:p></o:p></pre> </blockquote> <div> <p class=3D"MsoNormal"><span style=3D"font-size:11.0pt"><o:p></o:p></span><= /p> </div> </div> </body> </html> --_000_MN2PR13MB30225A5769E6AF33496072E0A7419MN2PR13MB3022namp_--