From nobody Fri Apr 26 18:29:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+96276+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+96276+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1668157962; cv=none; d=zohomail.com; s=zohoarc; b=abHLbhd92E1f89Ddjk6ocnVJ7nYZDA+NteFhAqCTASSqlcRXVFq03xFZkT6cGcL4cCmN082CqrwlmbqQTRP+pQLKROWtKWunh6awoi9mtz6coDo+ugBon50Ied3KzkbMTuBQPRhAWyhnHRTKSZ/wdfZs5iGo9Uh7besDnJ89vJk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1668157962; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=BL+Jh1aGdgpEN0Yh+Wvo4yWOKq4Gz/OX1WFqebhB3CQ=; b=YuAVArk8Vb1fL8n+sM3d7grFfCrIvu2ZahzjYqwPxAFX9Gz2x85on1hXYNNFlkJzsfl8j+IFFSkFQwQGiPltZQ53MP5CCuV2yRUEDpyEWndVQTZFTp5mA67QElzYxGe8BM3HjFb/t5YqLVr8fb/TlhgqTrnC+30p4Ei6iNKATYY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+96276+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1668157962913444.02984303044684; Fri, 11 Nov 2022 01:12:42 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id llOxYY1788612x4P6Rzy1I8q; Fri, 11 Nov 2022 01:12:42 -0800 X-Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web08.3549.1668157959834733276 for ; Fri, 11 Nov 2022 01:12:41 -0800 X-Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8BxXbcGEm5jghMGAA--.9766S3; Fri, 11 Nov 2022 17:12:38 +0800 (CST) X-Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxFlcAEm5jXc0QAA--.27651S7; Fri, 11 Nov 2022 17:12:37 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: Bibo Mao , Chao Li , Leif Lindholm , Liming Gao , Michael D Kinney Subject: [edk2-devel] [edk2-platforms][PATCH V5 05/15] Platform/Loongson: Add MmuLib. Date: Fri, 11 Nov 2022 17:12:20 +0800 Message-Id: <40c87e6da8780f77f841e5b531c866596ff26048.1668157715.git.lixianglai@loongson.cn> In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxFlcAEm5jXc0QAA--.27651S7 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWDWF1kWw1kZF1fJw15Jr17Awb_yoW7CrW3uo WY9F4ruw4UJw4rZr4rCwn2gayxtFsYq39xXr1FvF4jqFsYvrs0kFWUtay5J34fZ34Svrnr GrykXaykJFWS9r1rn29KB7ZKAUJUUUU7529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUyS1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64 kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY 1x0267AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIE14v26F4UJVW0owA2z4x0Y4vEx4A2jsIEc7 CjxVAFwI0_Cr1j6rxdM2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc80 4VCY07AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VCjz48v1sIEY2 0_WwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VWrMxC20s026xCaFVCjc4AY6r1j6r4UMxCIbckI1I0E14v26r 1Y6r17MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CE b7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26ryj6F1UMIIF0x vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAI cVC2z280aVAFwI0_Cr0_Gr1UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxh VjvjDU0xZFpf9x0zRByIUUUUUU= Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: d62kOjx2EpYkE8THJPm1WhFmx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1668157962; bh=/pI0PnniE/RKFPsRYIRgAQ55OOFSRPyIX+ZsIrGgBQs=; h=Cc:Date:From:Reply-To:Subject:To; b=WyO/lgNir2K//EEyBJuaKyusP7/wReE6uDgiPtpDhriWyREzyPjOCYt3US9GOXDgHSA RsvMEwROdMsMtfTHB7l3B/rnMutjojQy7gVjjkX1pACM7D6OqBicow+1/0dyq3Eyam00r K0dVds+ZJm+YIfm+u1LhaDnM9KGuAUdrc78= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1668157964530100030 Content-Type: text/plain; charset="utf-8" Read the memory map information through the QemuFwCfg interface, then build the page table through the memory map information, and finally enable Mmu. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Cc: Bibo Mao Cc: Chao Li Cc: Leif Lindholm Cc: Liming Gao Cc: Michael D Kinney Signed-off-by: xianglai li Reviewed-by: Chao Li --- .../LoongArchQemuPkg/Include/Library/MmuLib.h | 85 ++ .../LoongArchQemuPkg/Library/MmuLib/Mmu.S | 155 ++++ .../Library/MmuLib/MmuBaseLib.inf | 40 + .../Library/MmuLib/MmuBaseLibPei.inf | 47 + .../Library/MmuLib/MmuLibCore.c | 831 ++++++++++++++++++ .../Library/MmuLib/MmuLibCore.h | 40 + .../Library/MmuLib/MmuLibCorePei.c | 231 +++++ .../LoongArchQemuPkg/Library/MmuLib/mmu.h | 190 ++++ .../LoongArchQemuPkg/Library/MmuLib/page.h | 280 ++++++ .../LoongArchQemuPkg/Library/MmuLib/pte.h | 57 ++ 10 files changed, 1956 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuL= ib.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBa= seLib.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBa= seLibPei.inf create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLi= bCore.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLi= bCore.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLi= bCorePei.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h b/= Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h new file mode 100644 index 0000000000..9880fc385c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h @@ -0,0 +1,85 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - EXC - execute +**/ +#ifndef MMU_LIB_H_ +#define MMU_LIB_H_ +/** + write operation is performed Count times from the first element of Buffe= r. + Convert EFI Attributes to Loongarch Attributes. + @param[in] EfiAttributes Efi Attributes. + + @retval LoongArch Attributes. +**/ +UINTN +EfiAttributeToLoongArchAttribute ( + IN UINTN EfiAttributes + ); + +/** + Finds the length and memory properties of the memory region correspondin= g to the specified base address. + + @param[in] BaseAddress To find the base address of the memory region. + @param[in] EndAddress To find the end address of the memory region. + @param[out] RegionLength The length of the memory region found. + @param[out] RegionAttributes Properties of the memory region found. + + @retval EFI_SUCCESS The corresponding memory area was successfully f= ound + EFI_NOT_FOUND No memory area found +**/ +EFI_STATUS +GetLoongArchMemoryRegion ( + IN UINTN BaseAddress, + IN UINTN EndAddress, + OUT UINTN *RegionLength, + OUT UINTN *RegionAttributes + ); + +/** + Sets the Attributes of the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + @param[in] Attributes The Attributes to be set. + + @retval EFI_SUCCESS The Attributes was set successfully +**/ +EFI_STATUS +LoongArchSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length, + IN UINTN Attributes + ); + +/** + Sets the non-executable Attributes for the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + + @retval EFI_SUCCESS The Attributes was set successfully +**/ +EFI_STATUS +LoongArchSetMemoryRegionNoExec ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length + ); + +/** + Create a page table and initialize the MMU. + + @param[] VOID + + @retval VOID +**/ +VOID +EFIAPI +ConfigureMmu ( + VOID + ); +#endif // MMU_LIB_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S b/Plat= form/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S new file mode 100644 index 0000000000..d5863de072 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S @@ -0,0 +1,155 @@ +#-------------------------------------------------------------------------= ----- +# +# LoongArch for LoongArch +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#-------------------------------------------------------------------------= ---- + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "Library/Cpu.h" +#include "mmu.h" + +ASM_GLOBAL ASM_PFX(HandleTlbRefill) +ASM_GLOBAL HandleTlbRefillEnd +ASM_GLOBAL ASM_PFX(LoongarchInvalidTlb) +ASM_GLOBAL ASM_PFX(SetTlbRefillFuncBase) +ASM_GLOBAL ASM_PFX(WriteCsrPageSize) +ASM_GLOBAL ASM_PFX(WriteCsrTlbRefillPageSize) +ASM_GLOBAL ASM_PFX(WriteCsrStlbPageSize) +ASM_GLOBAL ASM_PFX(LoongArchWriteqCsrPwctl0) +ASM_GLOBAL ASM_PFX(LoongArchWriteqCsrPwctl1) +ASM_GLOBAL ASM_PFX(LoongArchWriteqCsrPgdl) +ASM_GLOBAL ASM_PFX(LoongArchWriteqCsrPgdh) +ASM_GLOBAL ASM_PFX(LoongArchXchgCsrCrmd) + +# +# Refill the page table. +# @param VOID +# @retval VOID +# + +ASM_PFX(HandleTlbRefill): + csrwr T0, LOONGARCH_CSR_TLBRSAVE + csrrd T0, LOONGARCH_CSR_PGD + lddir T0, T0, 3 #Put pud BaseAddress into T0 + lddir T0, T0, 2 #Put pmd BaseAddress into T0 + lddir T0, T0, 1 #Put pte BaseAddress into T0 + ldpte T0, 0 + ldpte T0, 1 + tlbfill + csrrd T0, LOONGARCH_CSR_TLBRSAVE + ertn +HandleTlbRefillEnd: + +# +# Invalid corresponding TLB entries are based on the address given +# @param A0 The address corresponding to the invalid page table entry +# @retval none +# + +ASM_PFX(LoongarchInvalidTlb): + invtlb INVTLB_ADDR_GTRUE_OR_ASID, ZERO, A0 + jirl ZERO, RA, 0 + +# +# Set Tlb Refill function to hardware +# @param A0 The address of tlb refill function +# @retval none +# + +ASM_PFX(SetTlbRefillFuncBase): + csrwr A0, LOONGARCH_CSR_TLBREBASE + jirl ZERO, RA,0 + +# +# Set Cpu Status Register Page Size. +# @param A0 Page Size. +# @retval none +# + +ASM_PFX(WriteCsrPageSize): + li.d T0, CSR_TLBIDX_SIZE + sll.d A0, A0, T0 + li.d T0, CSR_TLBIDX_SIZE_MASK + csrxchg A0, T0, LOONGARCH_CSR_TLBIDX + jirl ZERO, RA,0 + +# +# Set Cpu Status Register TLBREFILL Page Size. +# @param A0 Page Size. +# @retval none +# + +ASM_PFX(WriteCsrTlbRefillPageSize): + li.d T0, CSR_TLBREHI_PS_SHIFT + sll.d A0, A0, T0 + li.d T0, CSR_TLBREHI_PS + csrxchg A0, T0, LOONGARCH_CSR_TLBREHI + jirl ZERO, RA,0 + +# +# Set Cpu Status Register STLB Page Size. +# @param val Page Size. +# @retval VOID +# + +ASM_PFX(WriteCsrStlbPageSize): + csrwr A0, LOONGARCH_CSR_STLBPGSIZE + jirl ZERO, RA,0 + +# +# Write Csr PWCTL0 register. +# @param A0 The value used to write to the PWCTL0 register +# @retval none +# + +ASM_PFX(LoongArchWriteqCsrPwctl0): + csrwr A0, LOONGARCH_CSR_PWCTL0 + jirl ZERO, RA,0 + +# +# Write Csr PWCTL1 register. +# @param A0 The value used to write to the PWCTL1 register +# @retval none +# + +ASM_PFX(LoongArchWriteqCsrPwctl1): + csrwr A0, LOONGARCH_CSR_PWCTL1 + jirl ZERO, RA,0 + +# +# Write Csr PGDL register. +# @param A0 The value used to write to the PGDL register +# @retval none +# + +ASM_PFX(LoongArchWriteqCsrPgdl): + csrwr A0, LOONGARCH_CSR_PGDL + jirl ZERO, RA,0 + +# +# Write Csr PGDH register. +# @param A0 The value used to write to the PGDH register +# @retval none +# + +ASM_PFX(LoongArchWriteqCsrPgdh): + csrwr A0, LOONGARCH_CSR_PGDH + jirl ZERO, RA,0 + +# +# Exchange specified bit data with the Csr CRMD register. +# @param[IN] A0 The value Exchanged with the CSR CRMD register. +# @param[IN] A1 Specifies the mask for swapping bits +# @retval VOID +# + +ASM_PFX(LoongArchXchgCsrCrmd): + csrxchg A0, A1, LOONGARCH_CSR_CRMD + jirl ZERO, RA,0 diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.i= nf b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf new file mode 100644 index 0000000000..abd864a324 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf @@ -0,0 +1,40 @@ +## @file +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D MmuBaseLib + FILE_GUID =3D da8f0232-fb14-42f0-922c-63104d2c70be + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MmuLib + CONSTRUCTOR =3D MmuInitialize + +# +# VALID_ARCHITECTURES =3D LOONGARCH64 +# + +[Sources] + MmuLibCore.c + Mmu.S + +[Packages] + MdePkg/MdePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[PCD] + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte + +[LibraryClasses] + MemoryAllocationLib + PcdLib + DebugLib diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPe= i.inf b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf new file mode 100644 index 0000000000..12848eecfe --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf @@ -0,0 +1,47 @@ +## @file +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D MmuPeiLib + FILE_GUID =3D da8f0232-fb14-42f0-922c-63104d2c70bd + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MmuLib | SEC PEIM + +# +# VALID_ARCHITECTURES =3D LOONGARCH64 +# + +[Sources] + MmuLibCorePei.c + Mmu.S + MmuLibCore.h + MmuLibCore.c + +[Packages] + MdePkg/MdePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + OvmfPkg/OvmfPkg.dec + +[PCD] + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase + gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize + +[LibraryClasses] + MemoryAllocationLib + CacheMaintenanceLib + PcdLib + DebugLib + QemuFwCfgLib diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c= b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c new file mode 100644 index 0000000000..b932e3d568 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c @@ -0,0 +1,831 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Pgd or Pgd or PGD - Page Global Directory + - Pud or Pud or PUD - Page Upper Directory + - Pmd or Pmd or PMD - Page Middle Directory + - Pte or pte or PTE - Page Table Entry + - Val or VAL or val - Value + - Dir - Directory +**/ +#include +#include +#include +#include +#include +#include "Library/Cpu.h" +#include "pte.h" +#include "page.h" +#include "mmu.h" + +BOOLEAN mMmuInited =3D FALSE; +/** + Check to see if mmu successfully initializes. + + @param VOID. + + @retval TRUE Initialization has been completed. + FALSE Initialization did not complete. +**/ +BOOLEAN +MmuIsInit (VOID) { + if ((mMmuInited =3D=3D TRUE) || + (PcdGet64 (PcdSwapPageDir) !=3D 0)) { + return TRUE; + } + return FALSE; +} + +/** + Iterates through the page directory to initialize it. + + @param Dst A pointer to the directory of the page to initialize. + @param Num The number of page directories to initialize. + @param Src A pointer to the data used to initialize the page directory. + + @retval VOID. +**/ +VOID +PageDirInit ( + IN VOID *Dst, + IN UINTN Num, + IN VOID *Src + ) +{ + UINTN *Ptr; + UINTN *End; + UINTN Entry; + + Entry =3D (UINTN)Src; + Ptr =3D (UINTN *)Dst; + End =3D Ptr + Num; + + for ( ;Ptr < End; Ptr++) { + *Ptr =3D Entry; + } + + return ; +} + +/** + Gets the virtual address corresponding to the page global directory tabl= e entry. + + @param Address the virtual address for the table entry. + + @retval PGD A pointer to get the table item. +**/ +PGD * +PgdOffset ( + IN UINTN Address + ) +{ + return ((PGD *)PcdGet64 (PcdSwapPageDir)) + PGD_INDEX (Address); +} + +/** + Gets the virtual address corresponding to the page upper directory table= entry. + + @param Pgd A pointer to a page global directory table entry. + @param Address the virtual address for the table entry. + + @retval PUD A pointer to get the table item. +**/ +PUD * +PudOffset ( + IN PGD *Pgd, + IN UINTN Address + ) +{ + UINTN PgdVal =3D (UINTN)PGD_VAL (*Pgd); + return (PUD *)PgdVal + PUD_INDEX (Address); +} + +/** + Gets the virtual address corresponding to the page middle directory tabl= e entry. + + @param Pud A pointer to a page upper directory table entry. + @param Address the virtual address for the table entry. + + @retval PMD A pointer to get the table item. +**/ +PMD * +PmdOffset ( + IN PUD *Pud, + IN UINTN Address + ) +{ + UINTN PudVal =3D PUD_VAL (*Pud); + return (PMD *)PudVal + PMD_INDEX (Address); +} + +/** + Gets the virtual address corresponding to the page table entry. + + @param Pmd A pointer to a page middle directory table entry. + @param Address the virtual address for the table entry. + + @retval PTE A pointer to get the table item. +**/ +PTE * +PteOffset ( + IN PMD *Pmd, + IN UINTN Address + ) +{ + UINTN PmdVal =3D (UINTN)PMD_VAL (*Pmd); + return (PTE *)PmdVal + PTE_INDEX (Address); +} + +/** + Sets the value of the page table entry. + + @param Pte A pointer to a page table entry. + @param PteVal The value of the page table entry to set. + + @retval VOID +**/ +VOID +SetPte ( + IN PTE *Pte, + IN PTE PteVal + ) +{ + *Pte =3D PteVal; +} + +/** + Sets the value of the page global directory. + + @param Pgd A pointer to a page global directory. + @param Pud The value of the page global directory to set. + + @retval VOID +**/ +VOID +SetPgd ( + IN PGD *Pgd, + IN PUD *Pud + ) +{ + *Pgd =3D (PGD) {((UINTN)Pud)}; +} + +/** + Sets the value of the page upper directory. + + @param Pud A pointer to a page upper directory. + @param Pmd The value of the page upper directory to set. + + @retval VOID +**/ +VOID +SetPud ( + IN PUD *Pud, + IN PMD *Pmd + ) +{ + *Pud =3D (PUD) {((UINTN)Pmd)}; +} + +/** + Sets the value of the page middle directory. + + @param Pmd A pointer to a page middle directory. + @param Pte The value of the page middle directory to set. + + @retval VOID +**/ +VOID +SetPmd ( + IN PMD *Pmd, + IN PTE *Pte + ) +{ + *Pmd =3D (PMD) {((UINTN)Pte)}; +} + +/** + Free up memory space occupied by page tables. + + @param Pte A pointer to the page table. + + @retval VOID +**/ +VOID +PteFree ( + IN PTE *Pte + ) +{ + FreePages ((VOID *)Pte, 1); +} + +/** + Free up memory space occupied by page middle directory. + + @param Pmd A pointer to the page middle directory. + + @retval VOID +**/ +VOID +PmdFree ( + IN PMD *Pmd + ) +{ + FreePages ((VOID *)Pmd, 1); +} + +/** + Free up memory space occupied by page upper directory. + + @param Pud A pointer to the page upper directory. + + @retval VOID +**/ +VOID +PudFree ( + IN PUD *Pud + ) +{ + FreePages ((VOID *)Pud, 1); +} + +/** + Requests the memory space required for the page upper directory, + initializes it, and places it in the specified page global directory + + @param Pgd A pointer to the page global directory. + + @retval EFI_SUCCESS Memory request successful. + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory. +**/ +INTN +PudAlloc ( + IN PGD *Pgd + ) +{ + PUD *Pud =3D (PUD *) AllocatePages (1); + if (!Pud) { + return EFI_OUT_OF_RESOURCES; + } + + PageDirInit ((VOID *)Pud, ENTRYS_PER_PUD, (VOID *)PcdGet64 (PcdInvalidPm= d)); + + if (pgd_none (*Pgd)) { + SetPgd (Pgd, Pud); + } else { /* Another has populated it */ + PudFree (Pud); + } + + return EFI_SUCCESS; +} + +/** + Requests the memory space required for the page middle directory, + initializes it, and places it in the specified page upper directory + + @param Pud A pointer to the page upper directory. + + @retval EFI_SUCCESS Memory request successful. + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory. +**/ +EFI_STATUS +PmdAlloc ( + IN PUD *Pud + ) +{ + PMD *Pmd; + + Pmd =3D (PMD *) AllocatePages (1); + if (!Pmd) { + return EFI_OUT_OF_RESOURCES; + } + + PageDirInit ((VOID *)Pmd, ENTRYS_PER_PMD, (VOID *)PcdGet64 (PcdInvalidPt= e)); + + if (pud_none (*Pud)) { + SetPud (Pud, Pmd); + } else {/* Another has populated it */ + PmdFree (Pmd); + } + + return EFI_SUCCESS; +} + +/** + Requests the memory space required for the page table, + initializes it, and places it in the specified page middle directory + + @param Pmd A pointer to the page middle directory. + + @retval EFI_SUCCESS Memory request successful. + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory. +**/ +INTN +PteAlloc ( + IN PMD *Pmd + ) +{ + PTE *Pte; + + Pte =3D (PTE *) AllocatePages (1); + if (!Pte) { + return EFI_OUT_OF_RESOURCES; + } + + Pte =3D ZeroMem (Pte, EFI_PAGE_SIZE); + + if (pmd_none (*Pmd)) { + SetPmd (Pmd, Pte); + } else { /* Another has populated it */ + PteFree (Pte); + } + + return EFI_SUCCESS; +} + +/** + Requests the memory space required for the page upper directory, + initializes it, and places it in the specified page global directory, + and get the page upper directory entry corresponding to the virtual addr= ess + + @param Pgd A pointer to the page global directory. + + @retval Gets the page upper directory entry +**/ +PUD * +PudAllocGet ( + IN PGD *Pgd, + IN UINTN Address + ) +{ + return ((pgd_none (*(Pgd)) && PudAlloc (Pgd)) ? + NULL : PudOffset (Pgd, Address)); +} + +/** + Requests the memory space required for the page middle directory, + initializes it, and places it in the specified page upper directory, + and get the page middle directory entry corresponding to the virtual add= ress + + @param Pud A pointer to the page upper directory. + + @retval Gets the page middle directory entry +**/ +PMD * +PmdAllocGet ( + IN PUD *Pud, + IN UINTN Address + ) +{ + PMD * ret =3D (pud_none (*Pud) && PmdAlloc (Pud))? + NULL: PmdOffset (Pud, Address); + DEBUG ((DEBUG_VERBOSE, "%a %d PudVal %p PmdOffset %p PMD_INDEX %p .\n", = __func__, __LINE__, + Pud->PudVal, PmdOffset (Pud, Address), PMD_INDEX (Address) )); + + return ret; +} + +/** + Requests the memory space required for the page table, + initializes it, and places it in the specified page middle directory, + and get the page table entry corresponding to the virtual address + + @param Pmd A pointer to the page upper directory. + + @retval Gets the page table entry +**/ +PTE * +PteAllocGet ( + IN PMD *Pmd, + IN UINTN Address + ) +{ + return (pmd_none (*Pmd) && PteAlloc (Pmd))? + NULL: PteOffset (Pmd, Address); +} + +/** + Gets the physical address of the page table entry corresponding to the s= pecified virtual address. + + @param Address the corresponding virtual address of the page table ent= ry. + + @retval A pointer to the page table entry. + @retval NULL +**/ +PTE * +GetPteAddress ( + IN UINTN Address + ) +{ + PGD *Pgd; + PUD *Pud; + PMD *Pmd; + + Pgd =3D PgdOffset (Address); + + if (pgd_none (*Pgd)) { + return NULL; + } + + Pud =3D PudOffset (Pgd, Address); + + if (pud_none (*Pud)) { + return NULL; + } + + Pmd =3D PmdOffset (Pud, Address); + if (pmd_none (*Pmd)) { + return NULL; + } + + if (IS_HUGE_PAGE (Pmd->PmdVal)) { + return ((PTE *)Pmd); + } + + return PteOffset (Pmd, Address); +} + +/** + Establishes a page table entry based on the specified memory region. + + @param Pmd A pointer to the page middle directory. + @param Address The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page table entry was created successfully. + @retval EFI_OUT_OF_RESOURCES Page table entry establishment failed = due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPteRange ( + IN PMD *Pmd, + IN UINTN Address, + IN UINTN End, + IN UINTN Attributes + ) +{ + PTE *Pte; + PTE PteVal; + BOOLEAN UpDate; + + Pte =3D PteAllocGet (Pmd, Address); + if (!Pte) { + return EFI_OUT_OF_RESOURCES; + } + + do { + UpDate =3D FALSE; + PteVal =3D MAKE_PTE (Address, Attributes); + DEBUG ((DEBUG_VERBOSE, + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p PTE_IND= EX %p MAKE_PTE %p\n", + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Addres= s), PMD_INDEX (Address), + PTE_INDEX (Address), PteVal)); + + if ((!pte_none (*Pte)) && + (PTE_VAL(*Pte) !=3D PTE_VAL(PteVal))) + { + UpDate =3D TRUE; + } + + SetPte (Pte, PteVal); + if (UpDate) { + LoongarchInvalidTlb(Address); + } + } while (Pte++, Address +=3D EFI_PAGE_SIZE, Address !=3D End); + + return EFI_SUCCESS; +} + +/** + Establishes a page middle directory based on the specified memory region. + + @param Pud A pointer to the page upper directory. + @param Address The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page middle directory was created successf= ully. + @retval EFI_OUT_OF_RESOURCES Page middle directory establishment fa= iled due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPmdRange ( + IN PUD *Pud, + IN UINTN Address, + IN UINTN End, + IN UINTN Attributes + ) +{ + PMD *Pmd; + PTE *Pte; + UINTN Next; + UINTN AddressStart_HugePage; + UINTN AddressEnd_HugePage; + + Pmd =3D PmdAllocGet (Pud, Address); + if (!Pmd) { + return EFI_OUT_OF_RESOURCES; + } + + do { + Next =3D PMD_ADDRESS_END (Address, End); + if (((Address & (~PMD_MASK)) =3D=3D 0) && + ((Next & (~PMD_MASK)) =3D=3D 0) && + (pmd_none (*Pmd))) + { + DEBUG ((DEBUG_VERBOSE, + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p MAKE_= HUGE_PTE %p\n", + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Addr= ess), PMD_INDEX (Address), + MAKE_HUGE_PTE (Address, Attributes))); + + SetPmd (Pmd, (PTE *)MAKE_HUGE_PTE (Address, Attributes)); + } else { + if ((pmd_none (*Pmd)) || + ((!pmd_none (*Pmd)) && + (!IS_HUGE_PAGE (Pmd->PmdVal)))) + { + if (MemoryMapPteRange (Pmd, Address, Next, Attributes)) { + return EFI_OUT_OF_RESOURCES; + } + } else { + SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte)); + AddressStart_HugePage =3D Address & PMD_MASK; + AddressEnd_HugePage =3D AddressStart_HugePage + HUGE_PAGE_SIZE; + if (MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_Hug= ePage, Attributes)) { + return EFI_OUT_OF_RESOURCES; + } + Pte =3D GetPteAddress (AddressStart_HugePage); + if (Pte =3D=3D NULL) { + continue ; + } + if (AddressEnd_HugePage > End) { + Next =3D End; + } + } + } + } while (Pmd++, Address =3D Next, Address !=3D End); + + return 0; +} + +/** + Establishes a page upper directory based on the specified memory region. + + @param Pgd A pointer to the page global directory. + @param Address The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page upper directory was created successfu= lly. + @retval EFI_OUT_OF_RESOURCES Page upper directory establishment fai= led due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPudRange ( + IN PGD *Pgd, + IN UINTN Address, + IN UINTN End, + IN UINTN Attributes + ) +{ + PUD *Pud; + UINTN Next; + + Pud =3D PudAllocGet (Pgd, Address); + if (!Pud) { + return EFI_OUT_OF_RESOURCES; + } + + do { + Next =3D PUD_ADDRESS_END (Address, End); + if (MemoryMapPmdRange (Pud, Address, Next, Attributes)) { + return EFI_OUT_OF_RESOURCES; + } + } while (Pud++, Address =3D Next, Address !=3D End); + return EFI_SUCCESS; +} + +/** + Establishes a page global directory based on the specified memory region. + + @param Start The memory space start address. + @param End The end address of the memory space. + @param Attributes Memory space Attributes. + + @retval EFI_SUCCESS The page global directory was created successf= ully. + @retval EFI_OUT_OF_RESOURCES Page global directory establishment fa= iled due to resource exhaustion. +**/ +EFI_STATUS +MemoryMapPageRange ( + IN UINTN Start, + IN UINTN End, + IN UINTN Attributes + ) +{ + PGD *Pgd; + UINTN Next; + UINTN Address =3D Start; + EFI_STATUS Err; + + Pgd =3D PgdOffset (Address); + do { + Next =3D PGD_ADDRESS_END (Address, End); + Err =3D MemoryMapPudRange (Pgd, Address, Next, Attributes); + if (Err) { + return Err; + } + } while (Pgd++, Address =3D Next, Address !=3D End); + + return EFI_SUCCESS; +} + +/** + Page tables are established from memory-mapped tables. + + @param MemoryRegion A pointer to a memory-mapped table entry. + + @retval EFI_SUCCESS The page table was created successfully. + @retval EFI_OUT_OF_RESOURCES Page table establishment failed due t= o resource exhaustion. +**/ +EFI_STATUS +FillTranslationTable ( + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + return MemoryMapPageRange (MemoryRegion->VirtualBase, + (MemoryRegion->Length + MemoryRegion->VirtualBase), + MemoryRegion->Attributes); +} + +/** + write operation is performed Count times from the first element of Buffe= r. + Convert EFI Attributes to Loongarch Attributes. + @param[in] EfiAttributes Efi Attributes. + + @retval LoongArch Attributes. +**/ +UINTN +EfiAttributeToLoongArchAttribute ( + IN UINTN EfiAttributes + ) +{ + UINTN LoongArchAttributes =3D PAGE_VALID | PAGE_DIRTY | CACHE_CC | PAGE= _USER | PAGE_GLOBAL; + switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) { + case EFI_MEMORY_UC: + LoongArchAttributes |=3D CACHE_SUC; + break; + case EFI_MEMORY_WC: + case EFI_MEMORY_WT: + case EFI_MEMORY_WB: + LoongArchAttributes |=3D CACHE_CC; + break; + default : + LoongArchAttributes |=3D CACHE_CC; + break; + } + + // Write protection attributes + if ((EfiAttributes & EFI_MEMORY_RO) !=3D 0) { + LoongArchAttributes &=3D ~PAGE_DIRTY; + } + + //eXecute protection attribute + if ((EfiAttributes & EFI_MEMORY_XP) !=3D 0) { + LoongArchAttributes |=3D PAGE_NO_EXEC; + } + + return LoongArchAttributes; +} + +/** + Finds the length and memory properties of the memory region correspondin= g to the specified base address. + + @param[in] BaseAddress To find the base address of the memory region. + @param[in] EndAddress To find the end address of the memory region. + @param[out] RegionLength The length of the memory region found. + @param[out] RegionAttributes Properties of the memory region found. + + @retval EFI_SUCCESS The corresponding memory area was successfully f= ound + EFI_NOT_FOUND No memory area found +**/ +EFI_STATUS +GetLoongArchMemoryRegion ( + IN UINTN BaseAddress, + IN UINTN EndAddress, + OUT UINTN *RegionLength, + OUT UINTN *RegionAttributes + ) +{ + PTE *Pte; + UINTN Attributes; + UINTN AttributesTmp; + UINTN MaxAddress; + MaxAddress =3D LShiftU64 (1ULL, MAX_VA_BITS) - 1; + Pte =3D GetPteAddress (BaseAddress); + + if (!MmuIsInit ()) { + return EFI_SUCCESS; + } + if (Pte =3D=3D NULL) { + return EFI_NOT_FOUND; + } + Attributes =3D GET_PAGE_ATTRIBUTES (*Pte); + if (IS_HUGE_PAGE (Pte->PteVal)) { + *RegionAttributes =3D Attributes & (~(PAGE_HUGE)); + *RegionLength +=3D HUGE_PAGE_SIZE; + } else { + *RegionLength +=3D EFI_PAGE_SIZE; + *RegionAttributes =3D Attributes; + } + + while (BaseAddress <=3D MaxAddress) { + Pte =3D GetPteAddress (BaseAddress); + if (Pte =3D=3D NULL) { + return EFI_SUCCESS; + } + AttributesTmp =3D GET_PAGE_ATTRIBUTES (*Pte); + if (IS_HUGE_PAGE (Pte->PteVal)) { + if (AttributesTmp =3D=3D Attributes) { + *RegionLength +=3D HUGE_PAGE_SIZE; + } + BaseAddress +=3D HUGE_PAGE_SIZE; + } else { + if (AttributesTmp =3D=3D Attributes) { + *RegionLength +=3D EFI_PAGE_SIZE; + } + BaseAddress +=3D EFI_PAGE_SIZE; + } + + if (BaseAddress > EndAddress) { + break; + } + } + return EFI_SUCCESS; +} + +/** + Sets the Attributes of the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + @param[in] Attributes The Attributes to be set. + + @retval EFI_SUCCESS The Attributes was set successfully +**/ +EFI_STATUS +LoongArchSetMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length, + IN UINTN Attributes + ) +{ + + if (!MmuIsInit ()) { + return EFI_SUCCESS; + } + Attributes =3D EfiAttributeToLoongArchAttribute (Attributes); + DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddr= ess , Length, Attributes)); + MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes); + + return EFI_SUCCESS; +} + +/** + Sets the non-executable Attributes for the specified memory region + + @param[in] BaseAddress The base address of the memory region to set th= e Attributes. + @param[in] Length The length of the memory region to set the Attr= ibutes. + + @retval EFI_SUCCESS The Attributes was set successfully +**/ +EFI_STATUS +LoongArchSetMemoryRegionNoExec ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN Length + ) +{ + if (MmuIsInit ()) { + Length =3D EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Length)); + LoongArchSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP); + } + return EFI_SUCCESS; +} + +/** + Check to see if mmu successfully initializes and saves the result. + + @param VOID. + + @retval EFI_SUCCESS Initialization succeeded. +**/ +EFI_STATUS +MmuInitialize (VOID) +{ + if (PcdGet64 (PcdSwapPageDir) !=3D 0) { + mMmuInited =3D TRUE; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h= b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h new file mode 100644 index 0000000000..7a5e8ea0dd --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h @@ -0,0 +1,40 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Dir - Directory +**/ +#ifndef MMU_LIB_CORE_H_ +#define MMU_LIB_CORE_H_ +/** + Iterates through the page directory to initialize it. + + @param Dst A pointer to the directory of the page to initialize. + @param Num The number of page directories to initialize. + @param Src A pointer to the data used to initialize the page directory. + + @retval VOID. +**/ +VOID +PageDirInit ( + IN VOID *dest, + IN UINTN Count, + IN VOID *src + ); + +/** + Page tables are established from memory-mapped tables. + + @param MemoryRegion A pointer to a memory-mapped table entry. + + @retval EFI_SUCCESS The page table was created successfully. + @retval EFI_OUT_OF_RESOURCES Page table establishment failed due t= o resource exhaustion. +**/ +EFI_STATUS +FillTranslationTable ( + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion + ); +#endif // MMU_LIB_CORE_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePe= i.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c new file mode 100644 index 0000000000..32a7fc0beb --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c @@ -0,0 +1,231 @@ +/** @file + Platform PEI driver + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - FwCfg - Firmeware Config + - Tlb - Translation Lookaside Buffer +**/ +#include +#include +#include +#include +#include +#include "Library/Cpu.h" +#include "pte.h" +#include "page.h" +#include "mmu.h" +#include +#include "MmuLibCore.h" +#include + +/** + Return the Virtual Memory Map of your platform + + This Virtual Memory Map is used by MemoryInitPei Module to initialize th= e MMU + on your platform. + + @param[out] VirtualMemoryMap Array of MEMORY_REGION_DESCRIPTOR + describing a Physical-to-Virtual Memory + mapping. This array must be ended by a + zero-filled entry. The allocated memory + will not be freed. +**/ +VOID +GetMemoryMapFromFwCfg ( + OUT MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap + ) +{ + + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + LOONGARCH_MEMMAP_ENTRY MemoryMapEntry; + LOONGARCH_MEMMAP_ENTRY *StartEntry; + LOONGARCH_MEMMAP_ENTRY *pEntry; + UINTN Processed; + MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; + UINTN Index =3D 0; + ASSERT (VirtualMemoryMap !=3D NULL); + + VirtualMemoryTable =3D AllocatePool ( + sizeof (MEMORY_REGION_DESCRIPTOR) * + MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS + ); + VirtualMemoryTable[Index].PhysicalBase =3D 0x10000000; + VirtualMemoryTable[Index].VirtualBase =3D VirtualMemoryTable[Index].Phy= sicalBase; + VirtualMemoryTable[Index].Length =3D 0x10000000; + VirtualMemoryTable[Index].Attributes =3D PAGE_VALID | PLV_KERNEL | CA= CHE_SUC | PAGE_DIRTY | PAGE_GLOBAL; + ++Index; + + Status =3D QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __fun= c__, __LINE__, Status)); + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR)= ); + *VirtualMemoryMap =3D VirtualMemoryTable; + return ; + } + if (FwCfgSize % sizeof MemoryMapEntry !=3D 0) { + DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize)); + } + + QemuFwCfgSelectItem (FwCfgItem); + StartEntry =3D AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize)); + QemuFwCfgReadBytes (FwCfgSize, StartEntry); + for (Processed =3D 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); P= rocessed++) { + pEntry =3D StartEntry + Processed; + if (pEntry->Length =3D=3D 0) { + continue; + } + + DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry= ->BaseAddr, pEntry->Length, pEntry->Type)); + VirtualMemoryTable[Index].PhysicalBase =3D pEntry->BaseAddr; + VirtualMemoryTable[Index].VirtualBase =3D VirtualMemoryTable[Index].P= hysicalBase; + VirtualMemoryTable[Index].Length =3D pEntry->Length; + VirtualMemoryTable[Index].Attributes =3D PAGE_VALID | PLV_KERNEL | = CACHE_CC | PAGE_DIRTY | PAGE_GLOBAL; + ++Index; + } + + FreePages (StartEntry, EFI_SIZE_TO_PAGES (FwCfgSize)); + // End of Table + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR)); + *VirtualMemoryMap =3D VirtualMemoryTable; + return ; +} + +/** + Create a page table and initialize the MMU. + + @param[] VOID + + @retval VOID +**/ +EFIAPI +VOID +ConfigureMmu (VOID) +{ + PGD *SwapperPageDir =3D NULL; + PGD *InvalidPgd =3D NULL; + PUD *InvalidPudTable =3D NULL; + PMD *InvalidPmdTable =3D NULL; + PTE *InvalidPteTable =3D NULL; + MEMORY_REGION_DESCRIPTOR *MemoryTable =3D NULL; + RETURN_STATUS PcdStatus; + UINTN PgdShift =3D PGD_SHIFT; + UINTN PgdWide =3D PGD_WIDE; + UINTN PudShift =3D PUD_SHIFT; + UINTN PudWide =3D PUD_WIDE; + UINTN PmdShift =3D PMD_SHIFT; + UINTN PmdWide =3D PMD_WIDE; + UINTN PteShift =3D PTE_SHIFT; + UINTN PteWide =3D PTE_WIDE; + UINTN PageEnable =3D 1 << 4; + VOID *TlbReEntry; + + SwapperPageDir =3D AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + InvalidPgd =3D AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + InvalidPudTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE)); + InvalidPmdTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE)); + InvalidPteTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE)); + ZeroMem (InvalidPteTable, PTE_TABLE_SIZE); + + if ((!InvalidPgd) || + (!InvalidPudTable) || + (!InvalidPmdTable) || + (!InvalidPteTable)) + { + goto FreeTranslationTable; + } + + /*pgd init*/ + PageDirInit (SwapperPageDir , ENTRYS_PER_PGD, InvalidPudTable); + /*pgd init*/ + PageDirInit (InvalidPgd, ENTRYS_PER_PGD, InvalidPudTable); + /*pud init*/ + PageDirInit (InvalidPudTable, ENTRYS_PER_PUD, InvalidPmdTable); + /*pmd init*/ + PageDirInit (InvalidPmdTable, ENTRYS_PER_PMD, InvalidPteTable); + GetMemoryMapFromFwCfg (&MemoryTable); + + PcdStatus |=3D PcdSet64S (PcdSwapPageDir, (UINTN)SwapperPageDir); + PcdStatus |=3D PcdSet64S (PcdInvalidPgd, (UINTN)InvalidPgd); + PcdStatus |=3D PcdSet64S (PcdInvalidPud, (UINTN)InvalidPudTable); + PcdStatus |=3D PcdSet64S (PcdInvalidPmd, (UINTN)InvalidPmdTable); + PcdStatus |=3D PcdSet64S (PcdInvalidPte, (UINTN)InvalidPteTable); + ASSERT_RETURN_ERROR (PcdStatus); + + while (MemoryTable->Length !=3D 0) { + DEBUG ((DEBUG_VERBOSE, "%a %d VirtualBase %p VirtualEnd %p Attributes = %p .\n", __func__, __LINE__, + MemoryTable->VirtualBase, + (MemoryTable->Length + MemoryTable->VirtualBase), + MemoryTable->Attributes)); + + PcdStatus =3D FillTranslationTable (MemoryTable); + if (EFI_ERROR (PcdStatus)) { + goto FreeTranslationTable; + } + MemoryTable++; + } + + TlbReEntry =3D AllocatePages (1); + if (TlbReEntry =3D=3D NULL) { + goto FreeTranslationTable; + } + CopyMem ((char *)TlbReEntry, HandleTlbRefill, (HandleTlbRefillEnd - Hand= leTlbRefill)); + InvalidateInstructionCacheRange ((VOID *)(UINTN)HandleTlbRefill, (UINTN)= (HandleTlbRefillEnd - HandleTlbRefill)); + + DEBUG ((DEBUG_VERBOSE, + "%a %d PteShift %d PteWide %d PmdShift %d PmdWide %d PudShift %d PudW= ide %d PgdShift %d PgdWide %d.\n", + __func__, __LINE__, + PteShift, PteWide, PmdShift, PmdWide,PudShift, PudWide, PgdShift, PgdW= ide)); + + SetTlbRefillFuncBase ((UINTN)TlbReEntry); + /*set page size*/ + WriteCsrPageSize (DEFAULT_PAGE_SIZE); + WriteCsrStlbPageSize (DEFAULT_PAGE_SIZE); + WriteCsrTlbRefillPageSize (DEFAULT_PAGE_SIZE); + + LoongArchWriteqCsrPwctl0 ((PteShift | PteWide << 5 | PmdShift << 10 | Pm= dWide << 15 | PudShift << 20 | PudWide << 25 + )); + LoongArchWriteqCsrPwctl1 (PgdShift | PgdWide << 6); + LoongArchWriteqCsrPgdl ((UINTN)SwapperPageDir); + LoongArchWriteqCsrPgdh ((UINTN)InvalidPgd); + + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu Start PageBassAddress %p.\n", __fu= nc__, __LINE__, SwapperPageDir)); + LoongArchXchgCsrCrmd ( PageEnable, 1 << 4); + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu End.\n", __func__, __LINE__)); + + return ; + +FreeTranslationTable: + if (SwapperPageDir) { + FreePages (SwapperPageDir, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + } + + if (InvalidPgd) { + FreePages (InvalidPgd, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE)); + } + + if (InvalidPudTable) { + FreePages (InvalidPudTable, EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE)); + } + + if (InvalidPmdTable) { + FreePages (InvalidPmdTable, EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE)); + } + + if (InvalidPteTable) { + FreePages (InvalidPteTable, EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE)); + } + + PcdSet64S (PcdSwapPageDir, (UINTN)0); + PcdSet64S (PcdInvalidPgd, (UINTN)0); + PcdSet64S (PcdInvalidPud, (UINTN)0); + PcdSet64S (PcdInvalidPmd, (UINTN)0); + PcdSet64S (PcdInvalidPte, (UINTN)0); + + return ; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h b/Plat= form/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h new file mode 100644 index 0000000000..8e284a2ecd --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h @@ -0,0 +1,190 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Tlb or TLB - Translation Lookaside Buffer + - CSR - Cpu State Register + - PGDL - Page Global Directory Low + - PGDH - Page Global Directory High + - TLBIDX - TLB Index + - TLBREHI - TLB Refill Entry High + - PWCTL - Page Walk Control + - STLB - Singular Page Size TLB + - PS - Page Size +**/ +#ifndef MMU_H_ +#define MMU_H_ +/*page size 4k*/ +#define DEFAULT_PAGE_SIZE 0x0c +#define LOONGARCH_CSR_PGDL 0x19 /* Page table base address when VA[= 47] =3D 0 */ +#define LOONGARCH_CSR_PGDH 0x1a /* Page table base address when VA[= 47] =3D 1 */ +#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */ +#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */ +#define LOONGARCH_CSR_TLBELO0 0x12 /* TLB EntryLo0 */ +#define LOONGARCH_CSR_TLBELO1 0x13 /* TLB EntryLo1 */ +#define LOONGARCH_CSR_TLBREHI 0x8e /* TLB refill entryhi */ +#define LOONGARCH_CSR_PWCTL0 0x1c /* PWCtl0 */ +#define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */ +#define LOONGARCH_CSR_STLBPGSIZE 0x1e +#define CSR_TLBIDX_SIZE_MASK 0x3f000000 +#define CSR_TLBIDX_PS_SHIFT 24 +#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT + +#define CSR_TLBREHI_PS_SHIFT 0 +#define CSR_TLBREHI_PS 0x3f + +#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \ + EFI_MEMORY_WC | \ + EFI_MEMORY_WT | \ + EFI_MEMORY_WB | \ + EFI_MEMORY_UCE \ + ) + +typedef struct { + EFI_PHYSICAL_ADDRESS PhysicalBase; + EFI_VIRTUAL_ADDRESS VirtualBase; + UINTN Length; + UINTN Attributes; +} MEMORY_REGION_DESCRIPTOR; + +// The total number of descriptors, including the final "end-of-table" des= criptor. +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS (128) + +extern CHAR8 HandleTlbRefill[], HandleTlbRefillEnd[]; + +/* + Invalid corresponding TLB entries are based on the address given + + @param Address The address corresponding to the invalid page table entry + + @retval none +*/ +extern +VOID +LoongarchInvalidTlb ( + UINTN Address + ); + +/* + Set Tlb Refill function to hardware + + @param A0 The address of tlb refill function + + @retval none +*/ +extern +VOID +SetTlbRefillFuncBase ( + UINTN Address + ); + +/* + Set Cpu Status Register Page Size. + + @param PageSize Page Size. + + @retval none +*/ +extern +VOID +WriteCsrPageSize ( + UINTN PageSize + ); + +/* + Set Cpu Status Register TLBREFILL Page Size. + + @param PageSize Page Size. + + @retval none +*/ +extern +VOID +WriteCsrTlbRefillPageSize ( + UINTN PageSize + ); + +/* + Set Cpu Status Register STLB Page Size. + + @param PageSize Page Size. + + @retval VOID +*/ +extern +VOID +WriteCsrStlbPageSize ( + UINTN PageSize +); + +/* + Write Csr PWCTL0 register. + + @param Val The value used to write to the PWCTL0 register + + @retval none +*/ +extern +VOID +LoongArchWriteqCsrPwctl0 ( + UINTN Val + ); + +/* + Write Csr PWCTL1 register. + + @param Val The value used to write to the PWCTL1 register + + @retval none +*/ +extern +VOID +LoongArchWriteqCsrPwctl1 ( + UINTN Val + ); + +/* + Write Csr PGDL register. + + @param Val The value used to write to the PGDL register + + @retval none +*/ +extern +VOID +LoongArchWriteqCsrPgdl ( + UINTN Val + ); + +/* + Write Csr PGDH register. + + @param Val The value used to write to the PGDH register + + @retval none +*/ +extern +VOID +LoongArchWriteqCsrPgdh ( + UINTN Val + ); + +/* + Exchange specified bit data with the Csr CRMD register. + + @param[IN] Val The value Exchanged with the CSR CRMD register. + @param[IN] Mask Specifies the mask for swapping bits + + @retval VOID +*/ +extern +VOID +LoongArchXchgCsrCrmd ( + UINTN Val, + UINTN Mask + ); + +#endif // MMU_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Pla= tform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h new file mode 100644 index 0000000000..6ab07e7900 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h @@ -0,0 +1,280 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Pgd or Pgd or PGD - Page Global Directory + - Pud or Pud or PUD - Page Upper Directory + - Pmd or Pmd or PMD - Page Middle Directory + - Pte or pte or PTE - Page Table Entry + - Val or VAL or val - Value + - Dir - Directory +**/ +#ifndef PAGE_H_ +#define PAGE_H_ + +#define MAX_VA_BITS 47 +#define PGD_WIDE (8) +#define PUD_WIDE (9) +#define PMD_WIDE (9) +#define PTE_WIDE (9) + +#define ENTRYS_PER_PGD (1 << PGD_WIDE) +#define ENTRYS_PER_PUD (1 << PUD_WIDE) +#define ENTRYS_PER_PMD (1 << PMD_WIDE) +#define ENTRYS_PER_PTE (1 << PTE_WIDE) + +#define PGD_SHIFT (PUD_SHIFT + PUD_WIDE) +#define PUD_SHIFT (PMD_SHIFT + PMD_WIDE) +#define PMD_SHIFT (EFI_PAGE_SHIFT + PTE_WIDE) +#define PTE_SHIFT (EFI_PAGE_SHIFT) + +#define PGD_SIZE (1UL << PGD_SHIFT) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PMD_SIZE (1UL << PMD_SHIFT) + +#define PGD_MASK (~(PGD_SIZE-1)) +#define PUD_MASK (~(PUD_SIZE-1)) +#define PMD_MASK (~(PMD_SIZE-1)) +#define PAGE_MASK (~(EFI_PAGE_SIZE - 1)) +#define PFN_MASK (~(((UINTN)(1) << (EFI_PAGE_SH= IFT)) - 1) & \ + (((UINTN)(1) << (PAGE_PFN_END= _SHIFT)) - 1)) + +typedef struct { UINTN PgdVal; } PGD; +typedef struct { UINTN PudVal; } PUD; +typedef struct { UINTN PmdVal; } PMD; +typedef struct { UINTN PteVal; } PTE; +/** + Gets the value of the page global directory table entry. + + @param x Page global directory struct variables. + + @retval the value of the page global directory table entry. + **/ +#define PGD_VAL(x) ((x).PgdVal) +/** + Gets the value of the page upper directory table entry. + + @param x Page upper directory struct variables. + + @retval the value of the page upper directory table entry. + **/ +#define PUD_VAL(x) ((x).PudVal) +/** + Gets the value of the page middle directory table entry. + + @param x Page middle directory struct variables. + + @retval the value of the page middle directory table entry. + **/ +#define PMD_VAL(x) ((x).PmdVal) +/** + Gets the value of the page table entry. + + @param x Page table entry struct variables. + + @retval the value of the page table entry. + **/ +#define PTE_VAL(x) ((x).PteVal) + +#define PGD_TABLE_SIZE (ENTRYS_PER_PGD * sizeof(PGD)) +#define PUD_TABLE_SIZE (ENTRYS_PER_PUD * sizeof(PUD)) +#define PMD_TABLE_SIZE (ENTRYS_PER_PMD * sizeof(PMD)) +#define PTE_TABLE_SIZE (ENTRYS_PER_PTE * sizeof(PTE)) +/** + Gets the physical address of the record in the page table entry. + + @param x Page table entry struct variables. + + @retval the value of the physical address. + **/ +#define GET_PAGE_ATTRIBUTES(x) (UINTN) {(PTE_VAL(x) & ~PFN_MA= SK)} +/** + Gets the virtual address of the next block of the specified virtual addr= ess + that is aligned with the size of the global page directory mapping. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the specified virtual address of the next block. + **/ +#define PGD_ADDRESS_END(Address, End) \ +({ \ + UINTN Boundary =3D ((Address) + PGD_SIZE) & PGD_MASK; \ + (Boundary - 1 < (End) - 1)? Boundary: (End); \ +}) +/** + Gets the virtual address of the next block of the specified virtual addr= ess + that is aligned with the size of the page upper directory mapping. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the specified virtual address of the next block. + **/ +#define PUD_ADDRESS_END(Address, End) \ +({ \ + UINTN Boundary =3D ((Address) + PUD_SIZE) & PUD_MASK; \ + (Boundary - 1 < (End) - 1)? Boundary: (End); \ +}) +/** + Gets the virtual address of the next block of the specified virtual addr= ess + that is aligned with the size of the page middle directory mapping. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the specified virtual address of the next block. + **/ +#define PMD_ADDRESS_END(Address, End) \ +({ \ + UINTN Boundary =3D ((Address) + PMD_SIZE) & PMD_MASK; \ + (Boundary - 1 < (End) - 1)? Boundary: (End); \ +}) +/** + Get Specifies the virtual address corresponding to the index of the page= global directory table entry. + + @param Address Specifies the virtual address. + + @retval the index of the page global directory table entry. + **/ +#define PGD_INDEX(Address) (((Address) >> PGD_SHIFT) & (E= NTRYS_PER_PGD-1)) +/** + Get Specifies the virtual address corresponding to the index of the page= upper directory table entry. + + @param Address Specifies the virtual address. + @param End The end address of the memory region. + + @retval the index of the page upper directory table entry. + **/ +#define PUD_INDEX(Address) (((Address) >> PUD_SHIFT) & (E= NTRYS_PER_PUD - 1)) +/** + Get Specifies the virtual address corresponding to the index of the page= middle directory table entry. + + @param Address Specifies the virtual address. + + @retval the index of the page middle directory table entry. + **/ +#define PMD_INDEX(Address) (((Address) >> PMD_SHIFT) & (E= NTRYS_PER_PMD - 1)) +/** + Get Specifies the virtual address corresponding to the index of the page= table entry. + + @param Address Specifies the virtual address. + + @retval the index of the page table entry. + **/ +#define PTE_INDEX(Address) (((Address) >> EFI_PAGE_SHIFT)= & (ENTRYS_PER_PTE - 1)) + +/** + Calculates the value of the page table entry based on the specified virt= ual address and properties. + + @param Address Specifies the virtual address. + @param Attributes Specifies the Attributes. + + @retval the value of the page table entry. + **/ +#define MAKE_PTE(Address, Attributes) (PTE){((((Address) >> EFI_PAGE= _SHIFT) << 12) | (Attributes))} +/** + Get Global bit from Attributes + + @param Attributes Specifies the Attributes. + * */ +#define GET_GLOBALBIT(Attributes) ((Attributes & PAGE_GLOBAL) >>= PAGE_GLOBAL_SHIFT) +/** + Calculates the value of the Huge page table entry based on the specified= virtual address and properties. + + @param Address Specifies the virtual address. + @param Attributes Specifies the Attributes. + + @retval the value of the HUGE page table entry. + **/ +#define MAKE_HUGE_PTE(Address, Attributes) (((((Address) >> PMD_SHIFT) <<= PMD_SHIFT) | \ + ((Attributes) | (GET_GLOBALBI= T(Attributes) << PAGE_HGLOBAL_SHIFT) | \ + PAGE_HUGE))) + + /** + Check whether the large page table entry is. + + @param Val The value of the page table entry. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +#define IS_HUGE_PAGE(Val) ((((Val) & PAGE_HUGE) =3D=3D P= AGE_HUGE) && \ + (((Val) & PAGE_HGLOBAL) =3D= =3D PAGE_HGLOBAL)) + +#define HUGE_PAGE_SIZE (PMD_SIZE) + + /** + Check that the global page directory table entry is empty. + + @param pgd the global page directory struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pgd_none ( + IN PGD pgd + ) +{ + return (PGD_VAL(pgd) =3D=3D (UINTN)PcdGet64(PcdInvalidPud)); +} + + /** + Check that the page upper directory table entry is empty. + + @param pud Page upper directory struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pud_none ( + IN PUD pud + ) +{ + return (PUD_VAL(pud) =3D=3D (UINTN)PcdGet64 (PcdInvalidPmd)); +} + + /** + Check that the page middle directory table entry is empty. + + @param pmd Page middle directory struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pmd_none ( + IN PMD pmd + ) +{ + return (PMD_VAL(pmd) =3D=3D (UINTN)PcdGet64(PcdInvalidPte)); +} + /** + Check that the page table entry is empty. + + @param pmd Page table entry struct variables. + + @retval 1 Is huge page table entry. + @retval 0 Isn't huge page table entry. + **/ +STATIC +inline +UINTN +pte_none ( + IN PTE pte + ) +{ + return (!(PTE_VAL(pte) & (~PAGE_GLOBAL))); +} +#endif // PAGE_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h b/Plat= form/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h new file mode 100644 index 0000000000..aacbf81744 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h @@ -0,0 +1,57 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Tlb or TLB - Translation Lookaside Buffer + - HGLOBAL - Huge Global + - PFN - Page Frame number + - EXEC - Execute + - PLV - Privilege Level + - RPLV - Restricted Privilege Level + - SUC - Strong-ordered UnCached + - CC - Coherent Cached + - WUC - Weak-ordered UnCached +**/ +#ifndef PTE_H_ +#define PTE_H_ +/*Page table property definitions */ +#define PAGE_VALID_SHIFT 0 +#define PAGE_DIRTY_SHIFT 1 +#define PAGE_PLV_SHIFT 2 /* 2~3, two bits */ +#define CACHE_SHIFT 4 /* 4~5, two bits */ +#define PAGE_GLOBAL_SHIFT 6 +#define PAGE_HUGE_SHIFT 6 /* HUGE is a PMD bit */ + +#define PAGE_HGLOBAL_SHIFT 12 /* HGlobal is a PMD bit */ +#define PAGE_PFN_SHIFT 12 +#define PAGE_PFN_END_SHIFT 48 +#define PAGE_NO_READ_SHIFT 61 +#define PAGE_NO_EXEC_SHIFT 62 +#define PAGE_RPLV_SHIFT 63 + +/* Used by TLB hardware (placed in EntryLo*) */ +#define PAGE_VALID ((UINTN)(1) << PAGE_VALID_SHIFT) +#define PAGE_DIRTY ((UINTN)(1) << PAGE_DIRTY_SHIFT) +#define PAGE_PLV ((UINTN)(3) << PAGE_PLV_SHIFT) +#define PAGE_GLOBAL ((UINTN)(1) << PAGE_GLOBAL_SHIFT) +#define PAGE_HUGE ((UINTN)(1) << PAGE_HUGE_SHIFT) +#define PAGE_HGLOBAL ((UINTN)(1) << PAGE_HGLOBAL_SHIFT) +#define PAGE_NO_READ ((UINTN)(1) << PAGE_NO_READ_SHIFT) +#define PAGE_NO_EXEC ((UINTN)(1) << PAGE_NO_EXEC_SHIFT) +#define PAGE_RPLV ((UINTN)(1) << PAGE_RPLV_SHIFT) +#define CACHE_MASK ((UINTN)(3) << CACHE_SHIFT) +#define PFN_SHIFT (EFI_PAGE_SHIFT - 12 + PAGE_PFN_SHIFT) + +#define PLV_KERNEL 0 +#define PLV_USER 3 + +#define PAGE_USER (PLV_USER << PAGE_PLV_SHIFT) +#define PAGE_KERNEL (PLV_KERN << PAGE_PLV_SHIFT) + +#define CACHE_SUC (0 << CACHE_SHIFT) /* Strong-ordered UnCached= */ +#define CACHE_CC (1 << CACHE_SHIFT) /* Coherent Cached */ +#define CACHE_WUC (2 << CACHE_SHIFT) /* Weak-ordered UnCached */ +#endif // PTE_H_ --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#96276): https://edk2.groups.io/g/devel/message/96276 Mute This Topic: https://groups.io/mt/94955173/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-