From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) by mx.groups.io with SMTP id smtpd.web11.19132.1681498720289713627 for ; Fri, 14 Apr 2023 11:58:40 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@ventanamicro.com header.s=google header.b=MCpQri9g; spf=pass (domain: ventanamicro.com, ip: 209.85.214.181, mailfrom: tphan@ventanamicro.com) Received: by mail-pl1-f181.google.com with SMTP id y6so18156805plp.2 for ; Fri, 14 Apr 2023 11:58:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1681498719; x=1684090719; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=s+rF/SNvRjDxD2Y+Tze7FuV98d9jkJ6RTP/ll+jHe9w=; b=MCpQri9g6NJ1XmqSTkm+MGvrF5b27+m9QLZ03GCV0b8keON4JhYsVyC4wa9Az7OHO5 T9BOeTqbiCPSNT7bkO3xyQ2rx3lFBQIoRwWAljoAiH5b7xbryROXaftLRxtQmLPB1bUs NbdVzhdOOlISZq7bjJly+t+kzGINBrOxbiC48AaZMQSSE5ltZBuUpT0s/AxwaUo7dN+A RSZPvyuq2n3gK/0ozyPB36HEGB7rNCMC+KkyWo9gXJCB1A2Nvbyaqr5UyJrWQolh+Ik0 r7/MbQclWhT1ZUXiBDLnNDSPRU7j8qE2rz09bYIcZPUjVxPeskI/hToU+tVD4IM43jV7 XnoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681498719; x=1684090719; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=s+rF/SNvRjDxD2Y+Tze7FuV98d9jkJ6RTP/ll+jHe9w=; b=d0lc9P8Zx62PUNNGeCSagF5+f7zNxKP3Leg/3T3g4yPDbY8nMF3d58lOGQy/HBmNyS qICT7AwKEQ9JbgLtNGiBqSGkslD0IlnJFnvuaoc/2W72KVlW2TzVYrj/DsppcmMC1wzZ +Yr1jn6z5tGsHf6hE8qr3Pnalxf1TKi8drJK8TED+MNZ3qVpntR6LzhE9RyMxv8Ec+r9 M7jqquFwALINMVvUtghsSxzKCvIo/tWrXqPOPIYbLMYc4gxweSU4+JNA0jN6Yv9DyGyH SAF0t9PGLX4t6pJAyKCw71dAmhlnSVsx31inoHjplsFEkVc8PrcMIxW+IF10h5EFJzAw 5fYA== X-Gm-Message-State: AAQBX9fwLDrcHdpFSNfJzu/dmoA/iz7dQ32WH5FgcLGimkw4u77WNYnw 5eJ/VYtvn14sngtPGrZ0sKuKeNSaBL1PSQ+W0Gs1KQ== X-Google-Smtp-Source: AKy350ZWRjQmqKpX90Z7B+BjD9f34dyrko097XCd3sFTj4tDkmu5JzbmI90CaunKZ/DbnEHhf+0sZw== X-Received: by 2002:a17:90b:4a0f:b0:246:94cf:6c26 with SMTP id kk15-20020a17090b4a0f00b0024694cf6c26mr6374486pjb.10.1681498719105; Fri, 14 Apr 2023 11:58:39 -0700 (PDT) Return-Path: Received: from localhost.localdomain (c-174-50-177-95.hsd1.ca.comcast.net. [174.50.177.95]) by smtp.gmail.com with ESMTPSA id g20-20020a170902869400b001a681d123a0sm3329760plo.297.2023.04.14.11.58.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 14 Apr 2023 11:58:38 -0700 (PDT) From: "Tuan Phan" To: devel@edk2.groups.io Cc: michael.d.kinney@intel.com, gaoliming@byosoft.com.cn, zhiguang.liu@intel.com, sunilvl@ventanamicro.com, git@danielschaefer.me, andrei.warkentin@intel.com, Tuan Phan Subject: [PATCH v2 3/6] UefiCpuPkg: RISC-V: Support MMU with SV39/48/57 mode Date: Fri, 14 Apr 2023 11:58:12 -0700 Message-Id: <20230414185815.2994-4-tphan@ventanamicro.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230414185815.2994-1-tphan@ventanamicro.com> References: <20230414185815.2994-1-tphan@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable During CpuDxe initialization, MMU will be setup with the highest mode that HW supports. Signed-off-by: Tuan Phan --- 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=0D +=0D + Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.
=0D + Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef BASE_RISCV_MMU_LIB_H_=0D +#define BASE_RISCV_MMU_LIB_H_=0D +=0D +VOID=0D +EFIAPI=0D +RiscVLocalTlbFlushAll (=0D + VOID=0D + );=0D +=0D +VOID=0D +EFIAPI=0D +RiscVLocalTlbFlush (=0D + UINTN VirtAddr=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +RiscVSetMemoryAttributes (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINT64 Length,=0D + IN UINT64 Attributes=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +RiscVConfigureMmu (=0D + VOID=0D + );=0D +=0D +#endif /* BASE_RISCV_MMU_LIB_H_ */=0D 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=0D +* MMU implementation for RISC-V=0D +*=0D +* Copyright (c) 2011-2020, ARM Limited. All rights reserved.=0D +* Copyright (c) 2016, Linaro Limited. All rights reserved.=0D +* Copyright (c) 2017, Intel Corporation. All rights reserved.
=0D +* Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.
= =0D +*=0D +* SPDX-License-Identifier: BSD-2-Clause-Patent=0D +*=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#define RISCV_PG_V BIT0=0D +#define RISCV_PG_R BIT1=0D +#define RISCV_PG_W BIT2=0D +#define RISCV_PG_X BIT3=0D +#define RISCV_PG_G BIT5=0D +#define RISCV_PG_A BIT6=0D +#define RISCV_PG_D BIT7=0D +#define PTE_ATTRIBUTES_MASK 0xE=0D +=0D +#define PTE_PPN_MASK 0x3FFFFFFFFFFC00ULL=0D +#define PTE_PPN_SHIFT 10=0D +#define RISCV_MMU_PAGE_SHIFT 12=0D +=0D +STATIC UINTN mMaxRootTableLevel;=0D +STATIC UINTN mBitPerLevel;=0D +STATIC UINTN mTableEntryCount;=0D +=0D +STATIC=0D +BOOLEAN=0D +RiscVMmuEnabled (=0D + VOID=0D + )=0D +{=0D + return ((RiscVGetSupervisorAddressTranslationRegister () &=0D + SATP64_MODE) !=3D (SATP_MODE_OFF << SATP64_MODE_SHIFT));=0D +}=0D +=0D +STATIC=0D +UINTN=0D +RiscVGetRootTranslateTable (=0D + VOID=0D + )=0D +{=0D + return (RiscVGetSupervisorAddressTranslationRegister () & SATP64_PPN) <<= =0D + RISCV_MMU_PAGE_SHIFT;=0D +}=0D +=0D +STATIC=0D +BOOLEAN=0D +IsValidPte (=0D + IN UINTN Entry=0D + )=0D +{=0D + if (!(Entry & RISCV_PG_V) ||=0D + (((Entry & (RISCV_PG_R | RISCV_PG_W)) =3D=3D RISCV_PG_W)))=0D + {=0D + return FALSE;=0D + }=0D +=0D + return TRUE;=0D +}=0D +=0D +STATIC=0D +UINTN=0D +SetValidPte (=0D + IN UINTN Entry=0D + )=0D +{=0D + /* Set Valid and Global mapping bits */=0D + return Entry | RISCV_PG_G | RISCV_PG_V;=0D +}=0D +=0D +STATIC=0D +BOOLEAN=0D +IsBlockEntry (=0D + IN UINTN Entry=0D + )=0D +{=0D + return IsValidPte (Entry) &&=0D + (Entry & (RISCV_PG_X | RISCV_PG_R));=0D +}=0D +=0D +STATIC=0D +BOOLEAN=0D +IsTableEntry (=0D + IN UINTN Entry=0D + )=0D +{=0D + return IsValidPte (Entry) &&=0D + !IsBlockEntry (Entry);=0D +}=0D +=0D +STATIC=0D +UINTN=0D +SetTableEntry (=0D + IN UINTN Entry=0D + )=0D +{=0D + Entry =3D SetValidPte (Entry);=0D + Entry &=3D ~(RISCV_PG_X | RISCV_PG_W | RISCV_PG_R);=0D +=0D + return Entry;=0D +}=0D +=0D +STATIC=0D +VOID=0D +ReplaceTableEntry (=0D + IN UINTN *Entry,=0D + IN UINTN Value,=0D + IN UINTN RegionStart,=0D + IN BOOLEAN IsLiveBlockMapping=0D + )=0D +{=0D + *Entry =3D Value;=0D +=0D + if (IsLiveBlockMapping && RiscVMmuEnabled ()) {=0D + RiscVLocalTlbFlush (RegionStart);=0D + }=0D +}=0D +=0D +STATIC=0D +UINTN=0D +GetPpnfromPte (=0D + UINTN Entry,=0D + UINTN Level=0D + )=0D +{=0D + return ((Entry & PTE_PPN_MASK) >> PTE_PPN_SHIFT);=0D +}=0D +=0D +STATIC=0D +UINTN=0D +SetPpnToPte (=0D + UINTN Entry,=0D + UINTN Address,=0D + UINTN Level=0D + )=0D +{=0D + UINTN Ppn;=0D +=0D + Ppn =3D ((Address >> RISCV_MMU_PAGE_SHIFT) << PTE_PPN_SHIFT);=0D + ASSERT (~(Ppn & ~PTE_PPN_MASK));=0D + Entry &=3D ~PTE_PPN_MASK;=0D + return Entry | Ppn;=0D +}=0D +=0D +STATIC=0D +VOID=0D +FreePageTablesRecursive (=0D + IN UINTN *TranslationTable,=0D + IN UINTN Level=0D + )=0D +{=0D + UINTN Index;=0D +=0D + if (Level < mMaxRootTableLevel - 1) {=0D + for (Index =3D 0; Index < mTableEntryCount; Index++) {=0D + if (IsTableEntry (TranslationTable[Index])) {=0D + FreePageTablesRecursive (=0D + (UINTN *)(GetPpnfromPte ((TranslationTabl= e[Index]), Level) <<=0D + RISCV_MMU_PAGE_SHIFT),=0D + Level + 1=0D + );=0D + }=0D + }=0D + }=0D +=0D + FreePages (TranslationTable, 1);=0D +}=0D +=0D +STATIC=0D +EFI_STATUS=0D +UpdateRegionMappingRecursive (=0D + IN UINTN RegionStart,=0D + IN UINTN RegionEnd,=0D + IN UINTN AttributeSetMask,=0D + IN UINTN AttributeClearMask,=0D + IN UINTN *PageTable,=0D + IN UINTN Level,=0D + IN BOOLEAN TableIsLive=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN BlockShift;=0D + UINTN BlockMask;=0D + UINTN BlockEnd;=0D + UINTN *Entry;=0D + UINTN EntryValue;=0D + UINTN *TranslationTable;=0D + BOOLEAN NextTableIsLive;=0D +=0D + ASSERT (Level < mMaxRootTableLevel);=0D + ASSERT (((RegionStart | RegionEnd) & EFI_PAGE_MASK) =3D=3D 0);=0D +=0D + BlockShift =3D (mMaxRootTableLevel - Level - 1) * mBitPerLevel + RISCV_M= MU_PAGE_SHIFT;=0D + BlockMask =3D MAX_ADDRESS >> (64 - BlockShift);=0D +=0D + DEBUG (=0D + (=0D + DEBUG_VERBOSE,=0D + "%a(%d): %llx - %llx set %lx clr %lx\n",=0D + __func__,=0D + Level,=0D + RegionStart,=0D + RegionEnd,=0D + AttributeSetMask,=0D + AttributeClearMask=0D + )=0D + );=0D +=0D + for ( ; RegionStart < RegionEnd; RegionStart =3D BlockEnd) {=0D + BlockEnd =3D MIN (RegionEnd, (RegionStart | BlockMask) + 1);=0D + Entry =3D &PageTable[(RegionStart >> BlockShift) & (mTableEntryCoun= t - 1)];=0D +=0D + //=0D + // If RegionStart or BlockEnd is not aligned to the block size at this= =0D + // level, we will have to create a table mapping in order to map less= =0D + // than a block, and recurse to create the block or page entries at=0D + // the next level. No block mappings are allowed at all at level 0,=0D + // so in that case, we have to recurse unconditionally.=0D + //=0D + if ((Level =3D=3D 0) ||=0D + (((RegionStart | BlockEnd) & BlockMask) !=3D 0) || IsTableEntry (*= Entry))=0D + {=0D + ASSERT (Level < mMaxRootTableLevel - 1);=0D + if (!IsTableEntry (*Entry)) {=0D + //=0D + // No table entry exists yet, so we need to allocate a page table= =0D + // for the next level.=0D + //=0D + TranslationTable =3D AllocatePages (1);=0D + if (TranslationTable =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + ZeroMem (TranslationTable, EFI_PAGE_SIZE);=0D +=0D + if (IsBlockEntry (*Entry)) {=0D + //=0D + // We are splitting an existing block entry, so we have to popul= ate=0D + // the new table with the attributes of the block entry it repla= ces.=0D + //=0D + Status =3D UpdateRegionMappingRecursive (=0D + RegionStart & ~BlockMask,= =0D + (RegionStart | BlockMask)= + 1,=0D + *Entry & PTE_ATTRIBUTES_M= ASK,=0D + PTE_ATTRIBUTES_MASK,=0D + TranslationTable,=0D + Level + 1,=0D + FALSE=0D + );=0D + if (EFI_ERROR (Status)) {=0D + //=0D + // The range we passed to UpdateRegionMappingRecursive () is b= lock=0D + // aligned, so it is guaranteed that no further pages were all= ocated=0D + // by it, and so we only have to free the page we allocated he= re.=0D + //=0D + FreePages (TranslationTable, 1);=0D + return Status;=0D + }=0D + }=0D +=0D + NextTableIsLive =3D FALSE;=0D + } else {=0D + TranslationTable =3D (UINTN *)(GetPpnfromPte (*Entry, Level) << RI= SCV_MMU_PAGE_SHIFT);=0D + NextTableIsLive =3D TableIsLive;=0D + }=0D +=0D + //=0D + // Recurse to the next level=0D + //=0D + Status =3D UpdateRegionMappingRecursive (=0D + RegionStart,=0D + BlockEnd,=0D + AttributeSetMask,=0D + AttributeClearMask,=0D + TranslationTable,=0D + Level + 1,=0D + NextTableIsLive=0D + );=0D + if (EFI_ERROR (Status)) {=0D + if (!IsTableEntry (*Entry)) {=0D + //=0D + // We are creating a new table entry, so on failure, we can free= all=0D + // allocations we made recursively, given that the whole subhier= archy=0D + // has not been wired into the live page tables yet. (This is no= t=0D + // possible for existing table entries, since we cannot revert t= he=0D + // modifications we made to the subhierarchy it represents.)=0D + //=0D + FreePageTablesRecursive (TranslationTable, Level + 1);=0D + }=0D +=0D + return Status;=0D + }=0D +=0D + if (!IsTableEntry (*Entry)) {=0D + EntryValue =3D SetPpnToPte (0, (UINTN)TranslationTable, Level);=0D + EntryValue =3D SetTableEntry (EntryValue);=0D + ReplaceTableEntry (=0D + Entry,=0D + EntryValue,=0D + RegionStart,=0D + TableIsLive=0D + );=0D + }=0D + } else {=0D + EntryValue =3D (*Entry & ~AttributeClearMask) | AttributeSetMask;=0D + //=0D + // We don't have page fault exception handler when a virtual page is= accessed and=0D + // the A bit is clear, or is written and the D bit is clear.=0D + // So just set A for read and D for write permission.=0D + //=0D + if (AttributeSetMask & RISCV_PG_R) {=0D + EntryValue |=3D RISCV_PG_A;=0D + }=0D +=0D + if (AttributeSetMask & RISCV_PG_W) {=0D + EntryValue |=3D RISCV_PG_D;=0D + }=0D +=0D + EntryValue =3D SetPpnToPte (EntryValue, RegionStart, Level);=0D + EntryValue =3D SetValidPte (EntryValue);=0D + ReplaceTableEntry (Entry, EntryValue, RegionStart, TableIsLive);=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +STATIC=0D +EFI_STATUS=0D +UpdateRegionMapping (=0D + IN UINTN RegionStart,=0D + IN UINTN RegionLength,=0D + IN UINTN AttributeSetMask,=0D + IN UINTN AttributeClearMask,=0D + IN UINTN *RootTable,=0D + IN BOOLEAN TableIsLive=0D + )=0D +{=0D + if (((RegionStart | RegionLength) & EFI_PAGE_MASK) !=3D 0) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + return UpdateRegionMappingRecursive (=0D + RegionStart,=0D + RegionStart + RegionLength,=0D + AttributeSetMask,=0D + AttributeClearMask,=0D + RootTable,=0D + 0,=0D + TableIsLive=0D + );=0D +}=0D +=0D +STATIC=0D +UINTN=0D +GcdAttributeToPageAttribute (=0D + IN UINTN GcdAttributes=0D + )=0D +{=0D + UINTN RiscVAttributes =3D RISCV_PG_R | RISCV_PG_W | RISCV_PG_X;=0D +=0D + // Determine protection attributes=0D + if (GcdAttributes & EFI_MEMORY_RO) {=0D + RiscVAttributes &=3D ~(RISCV_PG_W);=0D + }=0D +=0D + // Process eXecute Never attribute=0D + if (GcdAttributes & EFI_MEMORY_XP) {=0D + RiscVAttributes &=3D ~RISCV_PG_X;=0D + }=0D +=0D + return RiscVAttributes;=0D +}=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +RiscVSetMemoryAttributes (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINTN Length,=0D + IN UINTN Attributes=0D + )=0D +{=0D + UINTN PageAttributesSet =3D GcdAttributeToPageAttribute (Attributes);=0D +=0D + if (!RiscVMmuEnabled ()) {=0D + return EFI_SUCCESS;=0D + }=0D +=0D + DEBUG (=0D + (=0D + DEBUG_VERBOSE,=0D + "%a: Set %llX page attribute 0x%X\n",=0D + __func__,=0D + BaseAddress,=0D + PageAttributesSet=0D + )=0D + );=0D +=0D + return UpdateRegionMapping (=0D + BaseAddress,=0D + Length,=0D + PageAttributesSet,=0D + PTE_ATTRIBUTES_MASK,=0D + (UINTN *)RiscVGetRootTranslateTable (),=0D + TRUE=0D + );=0D +}=0D +=0D +STATIC=0D +EFI_STATUS=0D +RiscVMmuSetSatpMode (=0D + UINTN SatpMode=0D + )=0D +{=0D + VOID *TranslationTable;=0D + UINTN SatpReg;=0D + UINTN Ppn;=0D + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemoryMap;=0D + UINTN NumberOfDescriptors;=0D + UINTN Index;=0D + EFI_STATUS Status;=0D +=0D + switch (SatpMode) {=0D + case SATP_MODE_OFF:=0D + return EFI_SUCCESS;=0D + case SATP_MODE_SV39:=0D + mMaxRootTableLevel =3D 3;=0D + mBitPerLevel =3D 9;=0D + mTableEntryCount =3D 512;=0D + break;=0D + case SATP_MODE_SV48:=0D + mMaxRootTableLevel =3D 4;=0D + mBitPerLevel =3D 9;=0D + mTableEntryCount =3D 512;=0D + break;=0D + case SATP_MODE_SV57:=0D + mMaxRootTableLevel =3D 5;=0D + mBitPerLevel =3D 9;=0D + mTableEntryCount =3D 512;=0D + break;=0D + default:=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + // Allocate pages for translation table=0D + TranslationTable =3D AllocatePages (1);=0D + if (TranslationTable =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + ZeroMem (TranslationTable, mTableEntryCount * sizeof (UINTN));=0D +=0D + NumberOfDescriptors =3D 0;=0D + MemoryMap =3D NULL;=0D + Status =3D gDS->GetMemorySpaceMap (=0D + &NumberOfDescriptors,=0D + &MemoryMap=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + for (Index =3D 0; Index < NumberOfDescriptors; Index++) {=0D + if (MemoryMap[Index].GcdMemoryType =3D=3D EfiGcdMemoryTypeMemoryMapped= Io) {=0D + // Default Read/Write attribute for memory mapped IO=0D + UpdateRegionMapping (=0D + MemoryMap[Index].BaseAddress,=0D + MemoryMap[Index].Length,=0D + RISCV_PG_R | RISCV_PG_W,=0D + PTE_ATTRIBUTES_MASK,=0D + TranslationTable,=0D + FALSE=0D + );=0D + } else if (MemoryMap[Index].GcdMemoryType =3D=3D EfiGcdMemoryTypeSyste= mMemory) {=0D + // Default Read/Write/Execute attribute for system memory=0D + UpdateRegionMapping (=0D + MemoryMap[Index].BaseAddress,=0D + MemoryMap[Index].Length,=0D + RISCV_PG_R | RISCV_PG_W | RISCV_PG_X,=0D + PTE_ATTRIBUTES_MASK,=0D + TranslationTable,=0D + FALSE=0D + );=0D + }=0D + }=0D +=0D + FreePool ((VOID *)MemoryMap);=0D +=0D + if (GetInterruptState ()) {=0D + DisableInterrupts ();=0D + }=0D +=0D + Ppn =3D (UINTN)TranslationTable >> RISCV_MMU_PAGE_SHIFT;=0D + ASSERT (!(Ppn & ~(SATP64_PPN)));=0D +=0D + SatpReg =3D Ppn;=0D + SatpReg |=3D (SatpMode <<=0D + SATP64_MODE_SHIFT) & SATP64_MODE;=0D + RiscVSetSupervisorAddressTranslationRegister (SatpReg);=0D + /* Check if HW support the setup satp mode */=0D + if (SatpReg !=3D RiscVGetSupervisorAddressTranslationRegister ()) {=0D + DEBUG (=0D + (=0D + DEBUG_VERBOSE,=0D + "%a: HW does not support SATP mode:%d\n",=0D + __func__,=0D + SatpMode=0D + )=0D + );=0D + FreePageTablesRecursive (TranslationTable, 0);=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + RiscVLocalTlbFlushAll ();=0D +=0D + if (GetInterruptState ()) {=0D + EnableInterrupts ();=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +RiscVConfigureMmu (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status =3D EFI_SUCCESS;=0D + INTN ModeSupport[] =3D { SATP_MODE_SV57, SATP_MODE_SV48, SATP_MOD= E_SV39 };=0D + INTN Idx;=0D +=0D + /* Try to setup MMU with highest mode as possible */=0D + for (Idx =3D 0; Idx < ARRAY_SIZE (ModeSupport); Idx++) {=0D + Status =3D RiscVMmuSetSatpMode (ModeSupport[Idx]);=0D + if (Status =3D=3D EFI_DEVICE_ERROR) {=0D + continue;=0D + } else if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + DEBUG (=0D + (=0D + DEBUG_INFO,=0D + "%a: SATP mode %d successfully configured\n",=0D + __func__,=0D + ModeSupport[Idx]=0D + )=0D + );=0D + break;=0D + }=0D +=0D + return Status;=0D +}=0D 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=0D +#=0D +# Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x0001001b=0D + BASE_NAME =3D BaseRiscVMmuLib=0D + FILE_GUID =3D d3bc42ee-c9eb-4339-ba11-06747083d3ae=0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D RiscVMmuLib=0D +=0D +[Sources]=0D + BaseRiscVMmuLib.c=0D + RiscVMmuCore.S=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D 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=0D +*=0D +* Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.
= =0D +*=0D +* SPDX-License-Identifier: BSD-2-Clause-Patent=0D +*=0D +**/=0D +=0D +#include =0D +#include =0D +=0D +.text=0D + .align 3=0D +=0D +//=0D +// Local tlb flush all.=0D +//=0D +//=0D +ASM_FUNC (RiscVLocalTlbFlushAll)=0D +sfence.vma=0D +ret=0D +=0D +//=0D +// Local tlb flush at a virtual address=0D +// @retval a0 : virtual address.=0D +//=0D +ASM_FUNC (=0D + RiscVLocalTlbFlush=0D + )=0D +sfence.vma a0=0D +ret=0D 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=0D CpuExceptionHandlerLib|UefiCpuPkg/Library/BaseRiscV64CpuExceptionHandler= Lib/BaseRiscV64CpuExceptionHandlerLib.inf=0D RiscVSbiLib|MdePkg/Library/BaseRiscVSbiLib/BaseRiscVSbiLib.inf=0D + RiscVMmuLib|MdePkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf=0D PlatformBootManagerLib|OvmfPkg/RiscVVirt/Library/PlatformBootManagerLib/= PlatformBootManagerLib.inf=0D ResetSystemLib|OvmfPkg/RiscVVirt/Library/ResetSystemLib/BaseResetSystemL= ib.inf=0D =0D 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));=0D }=0D =0D -/**=0D - Configure MMU=0D -**/=0D -STATIC=0D -VOID=0D -InitMmu (=0D - )=0D -{=0D - //=0D - // Set supervisor translation mode to Bare mode=0D - //=0D - RiscVSetSupervisorAddressTranslationRegister ((UINT64)SATP_MODE_OFF << 6= 0);=0D - DEBUG ((DEBUG_INFO, "%a: Set Supervisor address mode to bare-metal mode.= \n", __func__));=0D -}=0D -=0D /**=0D Publish system RAM and reserve memory regions.=0D =0D @@ -327,7 +312,8 @@ MemoryPeimInitialization ( =0D AddReservedMemoryMap (FdtPointer);=0D =0D - InitMmu ();=0D + /* Make sure SEC is booting with bare mode*/=0D + ASSERT ((RiscVGetSupervisorAddressTranslationRegister () & SATP64_MODE) = =3D=3D (SATP_MODE_OFF << SATP64_MODE_SHIFT));=0D =0D BuildMemoryTypeInformationHob ();=0D =0D 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=0D )=0D {=0D - DEBUG ((DEBUG_INFO, "%a: Set memory attributes not supported yet\n", __f= unc__));=0D - return EFI_SUCCESS;=0D + return RiscVSetMemoryAttributes (BaseAddress, Length, Attributes);=0D }=0D =0D /**=0D @@ -340,6 +339,12 @@ InitializeCpu ( //=0D DisableInterrupts ();=0D =0D + //=0D + // Enable MMU=0D + //=0D + Status =3D RiscVConfigureMmu ();=0D + ASSERT_EFI_ERROR (Status);=0D +=0D //=0D // Install Boot protocol=0D //=0D 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 =0D #include =0D #include =0D +#include =0D #include =0D #include =0D #include =0D #include =0D #include =0D +#include =0D =0D /**=0D Flush CPU data cache. If the instruction cache is fully coherent=0D 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=0D PeCoffGetEntryPointLib=0D RiscVSbiLib=0D + RiscVMmuLib=0D + CacheMaintenanceLib=0D =0D [Sources]=0D CpuDxe.c=0D --=20 2.25.1