From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f172.google.com (mail-pf1-f172.google.com [209.85.210.172]) by mx.groups.io with SMTP id smtpd.web10.1085.1685143064561239794 for ; Fri, 26 May 2023 16:17:44 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@ventanamicro.com header.s=google header.b=Bjh9dHrC; spf=pass (domain: ventanamicro.com, ip: 209.85.210.172, mailfrom: tphan@ventanamicro.com) Received: by mail-pf1-f172.google.com with SMTP id d2e1a72fcca58-64d3491609fso1146465b3a.3 for ; Fri, 26 May 2023 16:17:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1685143063; x=1687735063; 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=xj5eT9FrQ3624l+NhLTpQsLe2H6nrD3Lw/7JMn0YsUo=; b=Bjh9dHrC3o/F7ts1tn8dzvv+jS6KlTwrco2T/sq1Ri6pqSmSHDHcud85rz8/wgUQK5 kgTlq0D8r7C5YYVtQ0O1qSKZBsfXYbjqGWpQEPbqMWQqNzda4MM4fLOpJF1zvR5DqAnS he+hQuFlJ3fewOOaqqFdHijsYhxaZ4Gjn54w6NzMNLonZ2fj4Xu+BkSx/Y/8mdyyuKJB 79xq8NV76x/p7AwDDBN8myvCGKlexoWueXdYKRTeEetmn/u3Sn8dB/lCBAlWHtoAQ7xP d2wLchwb3+2M9zWprtq6UsVrfqJaL6lXhceCPUD/as6xB99xhwx8IxoWtqF6h65a9xTx N1jA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685143063; x=1687735063; 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=xj5eT9FrQ3624l+NhLTpQsLe2H6nrD3Lw/7JMn0YsUo=; b=aWV0Bll+jKXQDXd2acSebkEshLEBRbGEt8jIM3ZxwreLWTnwa4PaSr2iK1IGQI49Tf Tf7GbIGdFluy6WGymna8b8GVita1SG1kIpwwDMlrIj20K69hBW1bbnwlBoF4+TONyScj CaaiVLJ0U/Iv9A7D9COnLyKI3qERi4TFtG6IkeM37XW6fMyaR1//9+ThmtF2UN5/55Zp 6pL/Z74Qx2SxUcltmwWWkqsI2cwQqbVmQwrbqjutNUYF0DcX4nXTSlyYzwNWDEqaXivg XQG5FMrdgA4r2MYkOjLQzGGHLR11vDJY/7WfGL9OmXCtEVYM4Ius4LNWw9NYaOHl+BE8 JMXg== X-Gm-Message-State: AC+VfDyqAH5jzqvr8kaI2gsbF66YLd2ha1M/SHm6xfsRhbe0qwcY8opw kC4Kb98h5KX26fD3jbjA2hcaf0LuqMgshvsThyU= X-Google-Smtp-Source: ACHHUZ6Vjnl8MoNNA3I457O6CCWGur5/iQJTCFNS1GYR7RFWOBKDaAmO0Qlmnw+sctwkuLvyVUG7RA== X-Received: by 2002:a05:6a21:6710:b0:10b:8e96:561 with SMTP id wh16-20020a056a21671000b0010b8e960561mr774248pzb.62.1685143063457; Fri, 26 May 2023 16:17:43 -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 k3-20020aa792c3000000b005d22639b577sm3106308pfa.165.2023.05.26.16.17.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 May 2023 16:17:43 -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 v3 3/7] UefiCpuPkg: RISC-V: Support MMU with SV39/48/57 mode Date: Fri, 26 May 2023 16:17:29 -0700 Message-Id: <20230526231733.6755-4-tphan@ventanamicro.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230526231733.6755-1-tphan@ventanamicro.com> References: <20230526231733.6755-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 Reviewed-by: Andrei Warkentin --- UefiCpuPkg/CpuDxeRiscV64/CpuDxe.c | 9 +- UefiCpuPkg/CpuDxeRiscV64/CpuDxe.h | 2 + UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf | 2 + UefiCpuPkg/Include/Library/BaseRiscVMmuLib.h | 39 ++ .../Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c | 569 ++++++++++++++++++ .../BaseRiscVMmuLib/BaseRiscVMmuLib.inf | 26 + .../Library/BaseRiscVMmuLib/RiscVMmuCore.S | 31 + 7 files changed, 676 insertions(+), 2 deletions(-) create mode 100644 UefiCpuPkg/Include/Library/BaseRiscVMmuLib.h create mode 100644 UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c create mode 100644 UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf create mode 100644 UefiCpuPkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S 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 diff --git a/UefiCpuPkg/Include/Library/BaseRiscVMmuLib.h b/UefiCpuPkg/Incl= ude/Library/BaseRiscVMmuLib.h new file mode 100644 index 000000000000..f71d6a4a1e7b --- /dev/null +++ b/UefiCpuPkg/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/UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c b/UefiCpu= Pkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.c new file mode 100644 index 000000000000..230f34261d8b --- /dev/null +++ b/UefiCpuPkg/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/UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf b/UefiC= puPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf new file mode 100644 index 000000000000..b8a95feee683 --- /dev/null +++ b/UefiCpuPkg/Library/BaseRiscVMmuLib/BaseRiscVMmuLib.inf @@ -0,0 +1,26 @@ +## @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 + UefiCpuPkg/UefiCpuPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D diff --git a/UefiCpuPkg/Library/BaseRiscVMmuLib/RiscVMmuCore.S b/UefiCpuPkg= /Library/BaseRiscVMmuLib/RiscVMmuCore.S new file mode 100644 index 000000000000..42eec4cbdf83 --- /dev/null +++ b/UefiCpuPkg/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 --=20 2.25.1