From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web11.2174.1663299400398979630 for ; Thu, 15 Sep 2022 20:36:44 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxPGtB7yNj984aAA--.41628S7; Fri, 16 Sep 2022 11:36:37 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, maobibo@loongson.cn Subject: [edk2-platforms][PATCH V2 05/16] Platform/Loongson: Add MmuLib. Date: Fri, 16 Sep 2022 11:36:22 +0800 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8DxPGtB7yNj984aAA--.41628S7 X-Coremail-Antispam: 1UD129KBjvAXoWDXFW8WryxGw1rtrW8JFyrJFb_yoW7WFy8Ko WY9F4rCw4UJw4rZr4rCwn2gay8tFsYv39xXr1FvF4jqFsYvrs0kFWUtayUJ34fZ34Svrnx GrykXaykAFWSgr1rn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRUUUUUUUUU= X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Content-Transfer-Encoding: quoted-printable 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 Signed-off-by: xianglai li --- .../LoongArchQemuPkg/Include/Library/MmuLib.h | 85 ++ .../LoongArchQemuPkg/Library/MmuLib/Mmu.S | 35 + .../Library/MmuLib/MmuBaseLib.inf | 35 + .../Library/MmuLib/MmuBaseLibPei.inf | 45 + .../Library/MmuLib/MmuLibCore.c | 908 ++++++++++++++++++ .../Library/MmuLib/MmuLibCore.h | 39 + .../Library/MmuLib/MmuLibCorePei.c | 236 +++++ .../LoongArchQemuPkg/Library/MmuLib/mmu.h | 104 ++ .../LoongArchQemuPkg/Library/MmuLib/page.h | 267 +++++ .../LoongArchQemuPkg/Library/MmuLib/pte.h | 57 ++ 10 files changed, 1811 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..6c501eca07 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h @@ -0,0 +1,85 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - EXC - execute=0D +**/=0D +#ifndef MMU_LIB_H_=0D +#define MMU_LIB_H_=0D +/**=0D + write operation is performed Count times from the first element of Buffe= r.=0D +Convert EFI Attributes to Loongarch Attributes.=0D + @param[in] EfiAttributes Efi Attributes.=0D +=0D + @retval LoongArch Attributes.=0D +**/=0D +UINTN=0D +EfiAttributeToLoongArchAttribute (=0D + IN UINTN EfiAttributes=0D + );=0D +=0D +/**=0D + Finds the length and memory properties of the memory region correspondin= g to the specified base address.=0D +=0D + @param[in] BaseAddress To find the base address of the memory region= .=0D + @param[in] EndAddress To find the end address of the memory region.= =0D + @param[out] RegionLength The length of the memory region found.=0D + @param[out] RegionAttributes Properties of the memory region found.= =0D +=0D + @retval EFI_SUCCESS The corresponding memory area was successfully f= ound=0D + EFI_NOT_FOUND No memory area found=0D +**/=0D +EFI_STATUS=0D +GetLoongArchMemoryRegion (=0D + IN UINTN BaseAddress,=0D + IN UINTN EndAddress,=0D + OUT UINTN *RegionLength,=0D + OUT UINTN *RegionAttributes=0D + );=0D +=0D +/**=0D + Sets the Attributes of the specified memory region=0D +=0D + @param[in] BaseAddress The base address of the memory region to set th= e Attributes.=0D + @param[in] Length The length of the memory region to set the Attr= ibutes.=0D + @param[in] Attributes The Attributes to be set.=0D +=0D + @retval EFI_SUCCESS The Attributes was set successfully=0D +=0D +**/=0D +EFI_STATUS=0D +LoongArchSetMemoryAttributes (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINTN Length,=0D + IN UINTN Attributes=0D + );=0D +=0D +/**=0D + Sets the non-executable Attributes for the specified memory region=0D +=0D + @param[in] BaseAddress The base address of the memory region to set th= e Attributes.=0D + @param[in] Length The length of the memory region to set the Attr= ibutes.=0D +=0D + @retval EFI_SUCCESS The Attributes was set successfully=0D +**/=0D +EFI_STATUS=0D +LoongArchSetMemoryRegionNoExec (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINTN Length=0D + );=0D +/**=0D + Create a page table and initialize the MMU.=0D +=0D + @param[] VOID=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +EFIAPI=0D +ConfigureMmu (=0D + VOID=0D + );=0D +#endif=0D 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..a697b54e65 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S @@ -0,0 +1,35 @@ +#-------------------------------------------------------------------------= -----=0D +#=0D +# LoongArch for LoongArch=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +#-------------------------------------------------------------------------= ----=0D +=0D +#ifndef _KERNEL=0D +#define _KERNEL=0D +#endif=0D +=0D +#include "Library/Cpu.h"=0D +#include "LoongArchAsmMacro.h"=0D +=0D +# Query the page table.=0D +#=0D +# @param VOID=0D +#=0D +# @retval VOID=0D +ASM_FUNC(HandleTlbRefill)=0D + csrwr T0, LOONGARCH_CSR_TLBRSAVE=0D + csrrd T0, LOONGARCH_CSR_PGD=0D + lddir T0, T0, 3 #Put pud BaseAddress into T0=0D + lddir T0, T0, 2 #Put pmd BaseAddress into T0=0D + lddir T0, T0, 1 #Put pte BaseAddress into T0=0D + ldpte T0, 0=0D + ldpte T0, 1=0D + tlbfill=0D + csrrd T0, LOONGARCH_CSR_TLBRSAVE=0D + ertn=0D +.globl HandleTlbRefillEnd=0D +HandleTlbRefillEnd:=0D 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..d8cfe6776e --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf @@ -0,0 +1,35 @@ +## @file=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D MmuBaseLib=0D + FILE_GUID =3D da8f0232-fb14-42f0-922c-63104d2c70be= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D MmuLib=0D +=0D + CONSTRUCTOR =3D MmuInitialize=0D +[Sources.common]=0D + MmuLibCore.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=0D +=0D +[PCD]=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte=0D +=0D +[LibraryClasses]=0D + MemoryAllocationLib=0D + PcdLib=0D + DebugLib=0D 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..20e50218af --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf @@ -0,0 +1,45 @@ +## @file=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D MmuPeiLib=0D + FILE_GUID =3D da8f0232-fb14-42f0-922c-63104d2c70bd= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D MmuLib | SEC PEIM=0D +=0D +[Sources.common]=0D + MmuLibCorePei.c=0D + Mmu.S=0D + MmuLibCore.h=0D + MmuLibCore.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=0D + OvmfPkg/OvmfPkg.dec=0D +=0D +[PCD]=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize=0D +=0D +[FixedPcd]=0D + gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom=0D +=0D +[LibraryClasses]=0D + MemoryAllocationLib=0D + PcdLib=0D + DebugLib=0D + QemuFwCfgLib=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c= b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c new file mode 100644 index 0000000000..d737759ad2 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c @@ -0,0 +1,908 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Pgd or Pgd or PGD - Page Global Directory=0D + - Pud or Pud or PUD - Page Upper Directory=0D + - Pmd or Pmd or PMD - Page Middle Directory=0D + - Pte or pte or PTE - Page Table Entry=0D + - Val or VAL or val - Value=0D + - Dir - Directory=0D +**/=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "Library/Cpu.h"=0D +#include "pte.h"=0D +#include "page.h"=0D +#include "mmu.h"=0D +=0D +BOOLEAN mMmuInited =3D FALSE;=0D +/**=0D + Check to see if mmu successfully initializes.=0D +=0D + @param VOID.=0D +=0D + @retval TRUE Initialization has been completed.=0D + FALSE Initialization did not complete.=0D +**/=0D +BOOLEAN=0D +MmuIsInit (VOID) {=0D + if ((mMmuInited =3D=3D TRUE) ||=0D + (PcdGet64 (PcdSwapPageDir) !=3D 0)) {=0D + return TRUE;=0D + }=0D + return FALSE;=0D +}=0D +=0D +/**=0D + Iterates through the page directory to initialize it.=0D +=0D + @param Dst A pointer to the directory of the page to initialize.=0D + @param Num The number of page directories to initialize.=0D + @param Src A pointer to the data used to initialize the page directory= .=0D +=0D + @retval VOID.=0D +**/=0D +VOID=0D +PageDirInit (=0D + IN VOID *Dst,=0D + IN UINTN Num,=0D + IN VOID *Src=0D + )=0D +{=0D + UINTN *Ptr;=0D + UINTN *End;=0D + UINTN Entry;=0D +=0D + Entry =3D (UINTN)Src;=0D + Ptr =3D (UINTN *)Dst;=0D + End =3D Ptr + Num;=0D +=0D + for ( ;Ptr < End; Ptr++) {=0D + *Ptr =3D Entry;=0D + }=0D +=0D + return ;=0D +}=0D +/**=0D + Gets the virtual address corresponding to the page global directory tabl= e entry.=0D +=0D + @param Address the virtual address for the table entry.=0D +=0D + @retval PGD A pointer to get the table item.=0D +**/=0D +PGD *=0D +PgdOffset (=0D + IN UINTN Address=0D + )=0D +{=0D + return ((PGD *)PcdGet64 (PcdSwapPageDir)) + PGD_INDEX (Address);=0D +}=0D +/**=0D + Gets the virtual address corresponding to the page upper directory table= entry.=0D +=0D + @param Pgd A pointer to a page global directory table entry.=0D + @param Address the virtual address for the table entry.=0D +=0D + @retval PUD A pointer to get the table item.=0D +**/=0D +PUD *=0D +PudOffset (=0D + IN PGD *Pgd,=0D + IN UINTN Address=0D + )=0D +{=0D + UINTN PgdVal =3D (UINTN)PGD_VAL (*Pgd);=0D + return (PUD *)PgdVal + PUD_INDEX (Address);=0D +}=0D +/**=0D + Gets the virtual address corresponding to the page middle directory tabl= e entry.=0D +=0D + @param Pud A pointer to a page upper directory table entry.=0D + @param Address the virtual address for the table entry.=0D +=0D + @retval PMD A pointer to get the table item.=0D +**/=0D +PMD *=0D +PmdOffset (=0D + IN PUD *Pud,=0D + IN UINTN Address=0D + )=0D +{=0D + UINTN PudVal =3D PUD_VAL (*Pud);=0D + return (PMD *)PudVal + PMD_INDEX (Address);=0D +}=0D +/**=0D + Gets the virtual address corresponding to the page table entry.=0D +=0D + @param Pmd A pointer to a page middle directory table entry.=0D + @param Address the virtual address for the table entry.=0D +=0D + @retval PTE A pointer to get the table item.=0D +**/=0D +PTE *=0D +PteOffset (=0D + IN PMD *Pmd,=0D + IN UINTN Address=0D + )=0D +{=0D + UINTN PmdVal =3D (UINTN)PMD_VAL (*Pmd);=0D + return (PTE *)PmdVal + PTE_INDEX (Address);=0D +}=0D +=0D +/**=0D + Sets the value of the page table entry.=0D +=0D + @param Pte A pointer to a page table entry.=0D + @param PteVal The value of the page table entry to set.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +SetPte (=0D + IN PTE *Pte,=0D + IN PTE PteVal=0D + )=0D +{=0D + *Pte =3D PteVal;=0D +}=0D +/**=0D + Sets the value of the page global directory.=0D +=0D + @param Pgd A pointer to a page global directory.=0D + @param Pud The value of the page global directory to set.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +SetPgd (=0D + IN PGD *Pgd,=0D + IN PUD *Pud=0D + )=0D +{=0D + *Pgd =3D (PGD) {((UINTN)Pud)};=0D +}=0D +=0D +/**=0D + Sets the value of the page upper directory.=0D +=0D + @param Pud A pointer to a page upper directory.=0D + @param Pmd The value of the page upper directory to set.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +SetPud (=0D + IN PUD *Pud,=0D + IN PMD *Pmd=0D + )=0D +{=0D + *Pud =3D (PUD) {((UINTN)Pmd)};=0D +}=0D +=0D +/**=0D + Sets the value of the page middle directory.=0D +=0D + @param Pmd A pointer to a page middle directory.=0D + @param Pte The value of the page middle directory to set.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +SetPmd (=0D + IN PMD *Pmd,=0D + IN PTE *Pte=0D + )=0D +{=0D + *Pmd =3D (PMD) {((UINTN)Pte)};=0D +}=0D +/**=0D + Free up memory space occupied by page tables.=0D +=0D + @param Pte A pointer to the page table.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +PteFree (=0D + IN PTE *Pte=0D + )=0D +{=0D + FreePages ((VOID *)Pte, 1);=0D +}=0D +/**=0D + Free up memory space occupied by page middle directory.=0D +=0D + @param Pmd A pointer to the page middle directory.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +PmdFree (=0D + IN PMD *Pmd=0D + )=0D +{=0D + FreePages ((VOID *)Pmd, 1);=0D +}=0D +/**=0D + Free up memory space occupied by page upper directory.=0D +=0D + @param Pud A pointer to the page upper directory.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +PudFree (=0D + IN PUD *Pud=0D + )=0D +{=0D + FreePages ((VOID *)Pud, 1);=0D +}=0D +/**=0D + Requests the memory space required for the page upper directory,=0D + initializes it, and places it in the specified page global directory=0D +=0D + @param Pgd A pointer to the page global directory.=0D +=0D + @retval EFI_SUCCESS Memory request successful.=0D + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory.=0D +**/=0D +INTN=0D +PudAlloc (=0D + IN PGD *Pgd=0D + )=0D +{=0D + PUD *Pud =3D (PUD *) AllocatePages (1);=0D + if (!Pud) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + PageDirInit ((VOID *)Pud, ENTRYS_PER_PUD, (VOID *)PcdGet64 (PcdInvalidPm= d));=0D +=0D + if (pgd_none (*Pgd)) {=0D + SetPgd (Pgd, Pud);=0D + } else { /* Another has populated it */=0D + PudFree (Pud);=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +/**=0D + Requests the memory space required for the page middle directory,=0D + initializes it, and places it in the specified page upper directory=0D +=0D + @param Pud A pointer to the page upper directory.=0D +=0D + @retval EFI_SUCCESS Memory request successful.=0D + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory.=0D +**/=0D +EFI_STATUS=0D +PmdAlloc (=0D + IN PUD *Pud=0D + )=0D +{=0D + PMD *Pmd;=0D +=0D + Pmd =3D (PMD *) AllocatePages (1);=0D + if (!Pmd) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + PageDirInit ((VOID *)Pmd, ENTRYS_PER_PMD, (VOID *)PcdGet64 (PcdInvalidPt= e));=0D +=0D + if (pud_none (*Pud)) {=0D + SetPud (Pud, Pmd);=0D + } else {/* Another has populated it */=0D + PmdFree (Pmd);=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +/**=0D + Requests the memory space required for the page table,=0D + initializes it, and places it in the specified page middle directory=0D +=0D + @param Pmd A pointer to the page middle directory.=0D +=0D + @retval EFI_SUCCESS Memory request successful.=0D + @retval EFI_OUT_OF_RESOURCES Resource exhaustion cannot be requested t= o memory.=0D +**/=0D +INTN=0D +PteAlloc (=0D + IN PMD *Pmd=0D + )=0D +{=0D + PTE *Pte;=0D +=0D + Pte =3D (PTE *) AllocatePages (1);=0D + if (!Pte) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + Pte =3D ZeroMem (Pte, EFI_PAGE_SIZE);=0D +=0D + if (pmd_none (*Pmd)) {=0D + SetPmd (Pmd, Pte);=0D + } else { /* Another has populated it */=0D + PteFree (Pte);=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +/**=0D + Requests the memory space required for the page upper directory,=0D + initializes it, and places it in the specified page global directory,=0D + and get the page upper directory entry corresponding to the virtual addr= ess=0D +=0D + @param Pgd A pointer to the page global directory.=0D +=0D + @retval Gets the page upper directory entry=0D +**/=0D +PUD *=0D +PudAllocGet (=0D + IN PGD *Pgd,=0D + IN UINTN Address=0D + )=0D +{=0D + return ((pgd_none (*(Pgd)) && PudAlloc (Pgd)) ?=0D + NULL : PudOffset (Pgd, Address));=0D +}=0D +/**=0D + Requests the memory space required for the page middle directory,=0D + initializes it, and places it in the specified page upper directory,=0D + and get the page middle directory entry corresponding to the virtual add= ress=0D +=0D + @param Pud A pointer to the page upper directory.=0D +=0D + @retval Gets the page middle directory entry=0D +**/=0D +PMD *=0D +PmdAllocGet (=0D + IN PUD *Pud,=0D + IN UINTN Address=0D + )=0D +{=0D + PMD * ret =3D (pud_none (*Pud) && PmdAlloc (Pud))?=0D + NULL: PmdOffset (Pud, Address);=0D + DEBUG ((DEBUG_VERBOSE, "%a %d PudVal %p PmdOffset %p PMD_INDEX %p .\n", = __func__, __LINE__,=0D + Pud->PudVal, PmdOffset (Pud, Address), PMD_INDEX (Address) ));=0D +=0D + return ret;=0D +}=0D +/**=0D + Requests the memory space required for the page table,=0D + initializes it, and places it in the specified page middle directory,=0D + and get the page table entry corresponding to the virtual address=0D +=0D + @param Pmd A pointer to the page upper directory.=0D +=0D + @retval Gets the page table entry=0D +**/=0D +PTE *=0D +PteAllocGet (=0D + IN PMD *Pmd,=0D + IN UINTN Address=0D + )=0D +{=0D + return (pmd_none (*Pmd) && PteAlloc (Pmd))?=0D + NULL: PteOffset (Pmd, Address);=0D +}=0D + /**=0D + Convert page middle directory table entry to tlb entry.=0D +=0D + @param PmdVal page middle directory table entry value.=0D +=0D + @retval tlb entry value.=0D + **/=0D +UINTN=0D +PmdToTlbEntry (=0D + UINTN PmdVal=0D + )=0D +{=0D + UINTN Value;=0D +=0D + Value =3D PmdVal ^ PAGE_HUGE;=0D + Value |=3D ((Value & PAGE_HGLOBAL) >>=0D + (PAGE_HGLOBAL_SHIFT - PAGE_GLOBAL_SHIFT));=0D +=0D + return Value;=0D +}=0D +=0D + /**=0D + Update huge tlb.=0D +=0D + @param address The address corresponding to tlb.=0D + @param Pte A pointer to the page table entry.=0D +=0D + @retval VOID.=0D + **/=0D +VOID=0D +UpdateHugeTlb (=0D + IN UINTN address,=0D + PTE *Pte)=0D +{=0D + INTN Idx;=0D + UINTN TlbEntry;=0D + address &=3D (PAGE_MASK << 1);=0D + LOONGARCH_CSR_WRITEQ (address, LOONGARCH_CSR_TLBEHI);=0D + LOONGARCH_TLB_SRCH();=0D + LOONGARCH_CSR_READQ (Idx, LOONGARCH_CSR_TLBIDX);=0D +=0D + if (Idx < 0) {=0D + return ;=0D + }=0D + WRITE_CSR_PAGE_SIZE (HUGE_PAGE_SIZE);=0D + TlbEntry =3D PmdToTlbEntry(PTE_VAL (*Pte));=0D + LOONGARCH_CSR_WRITEQ(TlbEntry, LOONGARCH_CSR_TLBELO0);=0D + LOONGARCH_CSR_WRITEQ(TlbEntry + (HUGE_PAGE_SIZE >> 1), LOONGARCH_CSR_TLB= ELO1);=0D + LOONGARCH_TLB_WR ();=0D +=0D + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE);=0D +=0D + return ;=0D +}=0D + /**=0D + Update tlb.=0D +=0D + @param address The address corresponding to tlb.=0D + @param Pte A pointer to the page table entry.=0D +=0D + @retval VOID.=0D + **/=0D +VOID=0D +UpdateTlb (=0D + IN UINTN address,=0D + PTE *Pte)=0D +{=0D + INTN Idx;=0D + if (IS_HUGE_PAGE (Pte->PteVal)) {=0D + return UpdateHugeTlb(address, Pte);=0D + }=0D +=0D + address &=3D (PAGE_MASK << 1);=0D + LOONGARCH_CSR_WRITEQ (address, LOONGARCH_CSR_TLBEHI);=0D + LOONGARCH_TLB_SRCH();=0D + LOONGARCH_CSR_READQ (Idx, LOONGARCH_CSR_TLBIDX);=0D +=0D + if (Idx < 0) {=0D + return ;=0D + }=0D +=0D + if ((UINTN)Pte & sizeof(PTE)) {=0D + Pte--;=0D + }=0D +=0D + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE);=0D + LOONGARCH_CSR_WRITEQ(PTE_VAL (*Pte), LOONGARCH_CSR_TLBELO0);=0D + Pte++;=0D + LOONGARCH_CSR_WRITEQ(PTE_VAL (*Pte), LOONGARCH_CSR_TLBELO1);=0D + LOONGARCH_TLB_WR ();=0D +=0D + return ;=0D +}=0D +=0D +/**=0D + Gets the physical address of the page table entry corresponding to the s= pecified virtual address.=0D +=0D + @param Address the corresponding virtual address of the page table ent= ry.=0D +=0D + @retval A pointer to the page table entry.=0D + @retval NULL=0D +**/=0D +PTE *=0D +GetPteAddress (=0D + IN UINTN Address=0D + )=0D +{=0D + PGD *Pgd;=0D + PUD *Pud;=0D + PMD *Pmd;=0D +=0D + Pgd =3D PgdOffset (Address);=0D +=0D + if (pgd_none (*Pgd)) {=0D + return NULL;=0D + }=0D +=0D + Pud =3D PudOffset (Pgd, Address);=0D +=0D + if (pud_none (*Pud)) {=0D + return NULL;=0D + }=0D +=0D + Pmd =3D PmdOffset (Pud, Address);=0D + if (pmd_none (*Pmd)) {=0D + return NULL;=0D + }=0D +=0D + if (IS_HUGE_PAGE (Pmd->PmdVal)) {=0D + return ((PTE *)Pmd);=0D + }=0D +=0D + return PteOffset (Pmd, Address);=0D +}=0D +/**=0D + Establishes a page table entry based on the specified memory region.=0D +=0D + @param Pmd A pointer to the page middle directory.=0D + @param Address The memory space start address.=0D + @param End The end address of the memory space.=0D + @param Attributes Memory space Attributes.=0D +=0D + @retval EFI_SUCCESS The page table entry was created successfully.= =0D + @retval EFI_OUT_OF_RESOURCES Page table entry establishment failed = due to resource exhaustion.=0D +**/=0D +EFI_STATUS=0D +MemoryMapPteRange (=0D + IN PMD *Pmd,=0D + IN UINTN Address,=0D + IN UINTN End,=0D + IN UINTN Attributes=0D + )=0D +{=0D + PTE *Pte;=0D + PTE PteVal;=0D + BOOLEAN UpDate;=0D +=0D + Pte =3D PteAllocGet (Pmd, Address);=0D + if (!Pte) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + do {=0D + UpDate =3D FALSE;=0D + PteVal =3D MAKE_PTE (Address, Attributes);=0D + DEBUG ((DEBUG_VERBOSE,=0D + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p PTE_IND= EX %p MAKE_PTE %p\n",=0D + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Addres= s), PMD_INDEX (Address),=0D + PTE_INDEX (Address), PteVal));=0D +=0D + if ((!pte_none (*Pte)) &&=0D + (PTE_VAL(*Pte) !=3D PTE_VAL(PteVal)))=0D + {=0D + UpDate =3D TRUE;=0D + }=0D +=0D + SetPte (Pte, PteVal);=0D + if (UpDate) {=0D + UpdateTlb (Address, Pte);=0D + }=0D + } while (Pte++, Address +=3D EFI_PAGE_SIZE, Address !=3D End);=0D +=0D + return EFI_SUCCESS;=0D +}=0D +/**=0D + Establishes a page middle directory based on the specified memory region= .=0D +=0D + @param Pud A pointer to the page upper directory.=0D + @param Address The memory space start address.=0D + @param End The end address of the memory space.=0D + @param Attributes Memory space Attributes.=0D +=0D + @retval EFI_SUCCESS The page middle directory was created successf= ully.=0D + @retval EFI_OUT_OF_RESOURCES Page middle directory establishment fa= iled due to resource exhaustion.=0D +**/=0D +EFI_STATUS=0D +MemoryMapPmdRange (=0D + IN PUD *Pud,=0D + IN UINTN Address,=0D + IN UINTN End,=0D + IN UINTN Attributes=0D + )=0D +{=0D + PMD *Pmd;=0D + PTE *Pte;=0D + UINTN Next;=0D + UINTN AddressStart_HugePage;=0D + UINTN AddressEnd_HugePage;=0D +=0D + Pmd =3D PmdAllocGet (Pud, Address);=0D + if (!Pmd) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + do {=0D + Next =3D PMD_ADDRESS_END (Address, End);=0D + if (((Address & (~PMD_MASK)) =3D=3D 0) &&=0D + ((Next & (~PMD_MASK)) =3D=3D 0) &&=0D + (pmd_none (*Pmd)))=0D + {=0D + DEBUG ((DEBUG_VERBOSE,=0D + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p MAKE_= HUGE_PTE %p\n",=0D + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Addr= ess), PMD_INDEX (Address),=0D + MAKE_HUGE_PTE (Address, Attributes)));=0D +=0D + SetPmd (Pmd, (PTE *)MAKE_HUGE_PTE (Address, Attributes));=0D + } else {=0D + if ((pmd_none (*Pmd)) ||=0D + ((!pmd_none (*Pmd)) &&=0D + (!IS_HUGE_PAGE (Pmd->PmdVal))))=0D + {=0D + if (MemoryMapPteRange (Pmd, Address, Next, Attributes)) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D + } else {=0D + SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte));=0D + AddressStart_HugePage =3D Address & PMD_MASK;=0D + AddressEnd_HugePage =3D AddressStart_HugePage + HUGE_PAGE_SIZE;=0D + if (MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_Hug= ePage, Attributes)) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D + Pte =3D GetPteAddress (AddressStart_HugePage);=0D + if (Pte =3D=3D NULL) {=0D + continue ;=0D + }=0D + UpdateTlb (AddressStart_HugePage, Pte);=0D + if (AddressEnd_HugePage > End) {=0D + Next =3D End;=0D + }=0D + }=0D + }=0D + } while (Pmd++, Address =3D Next, Address !=3D End);=0D +=0D + return 0;=0D +}=0D +/**=0D + Establishes a page upper directory based on the specified memory region.= =0D +=0D + @param Pgd A pointer to the page global directory.=0D + @param Address The memory space start address.=0D + @param End The end address of the memory space.=0D + @param Attributes Memory space Attributes.=0D +=0D + @retval EFI_SUCCESS The page upper directory was created successfu= lly.=0D + @retval EFI_OUT_OF_RESOURCES Page upper directory establishment fai= led due to resource exhaustion.=0D +**/=0D +EFI_STATUS=0D +MemoryMapPudRange (=0D + IN PGD *Pgd,=0D + IN UINTN Address,=0D + IN UINTN End,=0D + IN UINTN Attributes=0D + )=0D +{=0D + PUD *Pud;=0D + UINTN Next;=0D +=0D + Pud =3D PudAllocGet (Pgd, Address);=0D + if (!Pud) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + do {=0D + Next =3D PUD_ADDRESS_END (Address, End);=0D + if (MemoryMapPmdRange (Pud, Address, Next, Attributes)) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D + } while (Pud++, Address =3D Next, Address !=3D End);=0D + return EFI_SUCCESS;=0D +}=0D +/**=0D + Establishes a page global directory based on the specified memory region= .=0D +=0D + @param Start The memory space start address.=0D + @param End The end address of the memory space.=0D + @param Attributes Memory space Attributes.=0D +=0D + @retval EFI_SUCCESS The page global directory was created successf= ully.=0D + @retval EFI_OUT_OF_RESOURCES Page global directory establishment fa= iled due to resource exhaustion.=0D +**/=0D +EFI_STATUS=0D +MemoryMapPageRange (=0D + IN UINTN Start,=0D + IN UINTN End,=0D + IN UINTN Attributes=0D + )=0D +{=0D + PGD *Pgd;=0D + UINTN Next;=0D + UINTN Address =3D Start;=0D + EFI_STATUS Err;=0D +=0D + Pgd =3D PgdOffset (Address);=0D + do {=0D + Next =3D PGD_ADDRESS_END (Address, End);=0D + Err =3D MemoryMapPudRange (Pgd, Address, Next, Attributes);=0D + if (Err) {=0D + return Err;=0D + }=0D + } while (Pgd++, Address =3D Next, Address !=3D End);=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Page tables are established from memory-mapped tables.=0D +=0D + @param MemoryRegion A pointer to a memory-mapped table entry.=0D +=0D + @retval EFI_SUCCESS The page table was created successfully.=0D + @retval EFI_OUT_OF_RESOURCES Page table establishment failed due t= o resource exhaustion.=0D +**/=0D +EFI_STATUS=0D +FillTranslationTable (=0D + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion=0D + )=0D +{=0D + return MemoryMapPageRange (MemoryRegion->VirtualBase,=0D + (MemoryRegion->Length + MemoryRegion->VirtualBase),=0D + MemoryRegion->Attributes);=0D +}=0D +=0D +/**=0D + write operation is performed Count times from the first element of Buffe= r.=0D +Convert EFI Attributes to Loongarch Attributes.=0D + @param[in] EfiAttributes Efi Attributes.=0D +=0D + @retval LoongArch Attributes.=0D +**/=0D +UINTN=0D +EfiAttributeToLoongArchAttribute (=0D + IN UINTN EfiAttributes=0D + )=0D +{=0D + UINTN LoongArchAttributes =3D PAGE_VALID | PAGE_DIRTY | CACHE_CC | PAGE= _USER;=0D + switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {=0D + case EFI_MEMORY_UC:=0D + LoongArchAttributes |=3D CACHE_SUC;=0D + break;=0D + case EFI_MEMORY_WC:=0D + case EFI_MEMORY_WT:=0D + case EFI_MEMORY_WB:=0D + LoongArchAttributes |=3D CACHE_CC;=0D + break;=0D + default :=0D + LoongArchAttributes |=3D CACHE_CC;=0D + break;=0D + }=0D +=0D + // Write protection attributes=0D + if ((EfiAttributes & EFI_MEMORY_RO) !=3D 0) {=0D + LoongArchAttributes &=3D ~PAGE_DIRTY;=0D + }=0D +=0D + //eXecute protection attribute=0D + if ((EfiAttributes & EFI_MEMORY_XP) !=3D 0) {=0D + LoongArchAttributes |=3D PAGE_NO_EXEC;=0D + }=0D +=0D + return LoongArchAttributes;=0D +}=0D +=0D +/**=0D + Finds the length and memory properties of the memory region correspondin= g to the specified base address.=0D +=0D + @param[in] BaseAddress To find the base address of the memory region= .=0D + @param[in] EndAddress To find the end address of the memory region.= =0D + @param[out] RegionLength The length of the memory region found.=0D + @param[out] RegionAttributes Properties of the memory region found.= =0D +=0D + @retval EFI_SUCCESS The corresponding memory area was successfully f= ound=0D + EFI_NOT_FOUND No memory area found=0D +**/=0D +EFI_STATUS=0D +GetLoongArchMemoryRegion (=0D + IN UINTN BaseAddress,=0D + IN UINTN EndAddress,=0D + OUT UINTN *RegionLength,=0D + OUT UINTN *RegionAttributes=0D + )=0D +{=0D + PTE *Pte;=0D + UINTN Attributes;=0D + UINTN AttributesTmp;=0D + UINTN MaxAddress;=0D + MaxAddress =3D LShiftU64 (1ULL, MAX_VA_BITS) - 1;=0D + Pte =3D GetPteAddress (BaseAddress);=0D +=0D + if (!MmuIsInit ()) {=0D + return EFI_SUCCESS;=0D + }=0D + if (Pte =3D=3D NULL) {=0D + return EFI_NOT_FOUND;=0D + }=0D + Attributes =3D GET_PAGE_ATTRIBUTES (*Pte);=0D + if (IS_HUGE_PAGE (Pte->PteVal)) {=0D + *RegionAttributes =3D Attributes & (~(PAGE_HUGE));=0D + *RegionLength +=3D HUGE_PAGE_SIZE;=0D + } else {=0D + *RegionLength +=3D EFI_PAGE_SIZE;=0D + *RegionAttributes =3D Attributes;=0D + }=0D +=0D + while (BaseAddress <=3D MaxAddress) {=0D + Pte =3D GetPteAddress (BaseAddress);=0D + if (Pte =3D=3D NULL) {=0D + return EFI_SUCCESS;=0D + }=0D + AttributesTmp =3D GET_PAGE_ATTRIBUTES (*Pte);=0D + if (IS_HUGE_PAGE (Pte->PteVal)) {=0D + if (AttributesTmp =3D=3D Attributes) {=0D + *RegionLength +=3D HUGE_PAGE_SIZE;=0D + }=0D + BaseAddress +=3D HUGE_PAGE_SIZE;=0D + } else {=0D + if (AttributesTmp =3D=3D Attributes) {=0D + *RegionLength +=3D EFI_PAGE_SIZE;=0D + }=0D + BaseAddress +=3D EFI_PAGE_SIZE;=0D + }=0D +=0D + if (BaseAddress > EndAddress) {=0D + break;=0D + }=0D + }=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Sets the Attributes of the specified memory region=0D +=0D + @param[in] BaseAddress The base address of the memory region to set th= e Attributes.=0D + @param[in] Length The length of the memory region to set the Attr= ibutes.=0D + @param[in] Attributes The Attributes to be set.=0D +=0D + @retval EFI_SUCCESS The Attributes was set successfully=0D +=0D +**/=0D +EFI_STATUS=0D +LoongArchSetMemoryAttributes (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINTN Length,=0D + IN UINTN Attributes=0D + )=0D +{=0D +=0D + if (!MmuIsInit ()) {=0D + return EFI_SUCCESS;=0D + }=0D + Attributes =3D EfiAttributeToLoongArchAttribute (Attributes);=0D + DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddr= ess , Length, Attributes));=0D + MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes);=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Sets the non-executable Attributes for the specified memory region=0D +=0D + @param[in] BaseAddress The base address of the memory region to set th= e Attributes.=0D + @param[in] Length The length of the memory region to set the Attr= ibutes.=0D +=0D + @retval EFI_SUCCESS The Attributes was set successfully=0D +**/=0D +EFI_STATUS=0D +LoongArchSetMemoryRegionNoExec (=0D + IN EFI_PHYSICAL_ADDRESS BaseAddress,=0D + IN UINTN Length=0D + )=0D +{=0D + if (MmuIsInit ()) {=0D + Length =3D EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Length));=0D + LoongArchSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP);=0D + }=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Check to see if mmu successfully initializes and saves the result.=0D +=0D + @param VOID.=0D +=0D + @retval EFI_SUCCESS Initialization succeeded.=0D +**/=0D +EFI_STATUS=0D +MmuInitialize (VOID)=0D +{=0D + if (PcdGet64 (PcdSwapPageDir) !=3D 0) {=0D + mMmuInited =3D TRUE;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h= b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h new file mode 100644 index 0000000000..e9f294b356 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h @@ -0,0 +1,39 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Dir - Directory=0D +**/=0D +#ifndef MMU_LIB_CORE_H_=0D +#define MMU_LIB_CORE_H_=0D +/**=0D + Iterates through the page directory to initialize it.=0D +=0D + @param Dst A pointer to the directory of the page to initialize.=0D + @param Num The number of page directories to initialize.=0D + @param Src A pointer to the data used to initialize the page directory= .=0D +=0D + @retval VOID.=0D +**/=0D +VOID=0D +PageDirInit (=0D + IN VOID *dest,=0D + IN UINTN Count,=0D + IN VOID *src=0D + );=0D +/**=0D + Page tables are established from memory-mapped tables.=0D +=0D + @param MemoryRegion A pointer to a memory-mapped table entry.=0D +=0D + @retval EFI_SUCCESS The page table was created successfully.=0D + @retval EFI_OUT_OF_RESOURCES Page table establishment failed due t= o resource exhaustion.=0D +**/=0D +EFI_STATUS=0D +FillTranslationTable (=0D + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion=0D + );=0D +#endif=0D 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..899f40fd94 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.c @@ -0,0 +1,236 @@ +/** @file=0D + Platform PEI driver=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - FwCfg - Firmeware Config=0D + - Tlb - Translation Lookaside Buffer=0D +**/=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "Library/Cpu.h"=0D +#include "pte.h"=0D +#include "page.h"=0D +#include "mmu.h"=0D +#include =0D +#include "MmuLibCore.h"=0D +=0D +/**=0D + Return the Virtual Memory Map of your platform=0D +=0D + This Virtual Memory Map is used by MemoryInitPei Module to initialize th= e MMU=0D + on your platform.=0D +=0D + @param[out] VirtualMemoryMap Array of MEMORY_REGION_DESCRIPTOR=0D + describing a Physical-to-Virtual Memor= y=0D + mapping. This array must be ended by a= =0D + zero-filled entry. The allocated memor= y=0D + will not be freed.=0D +=0D +**/=0D +VOID=0D +GetMemoryMapFromFwCfg (=0D + OUT MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap=0D + )=0D +{=0D +=0D + EFI_STATUS Status;=0D + FIRMWARE_CONFIG_ITEM FwCfgItem;=0D + UINTN FwCfgSize;=0D + LOONGARCH_MEMMAP_ENTRY MemoryMapEntry;=0D + LOONGARCH_MEMMAP_ENTRY *StartEntry;=0D + LOONGARCH_MEMMAP_ENTRY *pEntry;=0D + UINTN Processed;=0D + MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;=0D + UINTN Index =3D 0;=0D + ASSERT (VirtualMemoryMap !=3D NULL);=0D +=0D + VirtualMemoryTable =3D AllocatePool (=0D + sizeof (MEMORY_REGION_DESCRIPTOR) *=0D + MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS=0D + );=0D + VirtualMemoryTable[Index].PhysicalBase =3D 0x10000000;=0D + VirtualMemoryTable[Index].VirtualBase =3D VirtualMemoryTable[Index].Phy= sicalBase;=0D + VirtualMemoryTable[Index].Length =3D 0x80000000;=0D + VirtualMemoryTable[Index].Attributes =3D PAGE_VALID | PAGE_USER | CAC= HE_CC | PAGE_DIRTY;=0D + ++Index;=0D +=0D + Status =3D QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __fun= c__, __LINE__, Status));=0D + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR)= );=0D + *VirtualMemoryMap =3D VirtualMemoryTable;=0D + return ;=0D + }=0D + if (FwCfgSize % sizeof MemoryMapEntry !=3D 0) {=0D + DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize));= =0D + }=0D +=0D + QemuFwCfgSelectItem (FwCfgItem);=0D + StartEntry =3D AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize));=0D + QemuFwCfgReadBytes (FwCfgSize, StartEntry);=0D + for (Processed =3D 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); P= rocessed++) {=0D + pEntry =3D StartEntry + Processed;=0D + if (pEntry->Length =3D=3D 0) {=0D + continue;=0D + }=0D +=0D + DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry= ->BaseAddr, pEntry->Length, pEntry->Type));=0D + VirtualMemoryTable[Index].PhysicalBase =3D pEntry->BaseAddr;=0D + VirtualMemoryTable[Index].VirtualBase =3D VirtualMemoryTable[Index].P= hysicalBase;=0D + VirtualMemoryTable[Index].Length =3D pEntry->Length;=0D + VirtualMemoryTable[Index].Attributes =3D PAGE_VALID | PAGE_USER | C= ACHE_CC | PAGE_DIRTY;=0D + ++Index;=0D + }=0D +=0D + FreePages (StartEntry, EFI_SIZE_TO_PAGES (FwCfgSize));=0D + // End of Table=0D + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR));= =0D + *VirtualMemoryMap =3D VirtualMemoryTable;=0D + return ;=0D +}=0D +=0D +/**=0D + Create a page table and initialize the MMU.=0D +=0D + @param[] VOID=0D +=0D + @retval VOID=0D +**/=0D +EFIAPI=0D +VOID=0D +ConfigureMmu (VOID)=0D +{=0D + PGD *SwapperPageDir =3D NULL;=0D + PGD *InvalidPgd =3D NULL;=0D + PUD *InvalidPudTable =3D NULL;=0D + PMD *InvalidPmdTable =3D NULL;=0D + PTE *InvalidPteTable =3D NULL;=0D + MEMORY_REGION_DESCRIPTOR *MemoryTable =3D NULL;=0D + RETURN_STATUS PcdStatus;=0D + UINTN PgdShift =3D PGD_SHIFT;=0D + UINTN PgdWide =3D PGD_WIDE;=0D + UINTN PudShift =3D PUD_SHIFT;=0D + UINTN PudWide =3D PUD_WIDE;=0D + UINTN PmdShift =3D PMD_SHIFT;=0D + UINTN PmdWide =3D PMD_WIDE;=0D + UINTN PteShift =3D PTE_SHIFT;=0D + UINTN PteWide =3D PTE_WIDE;=0D + UINTN PageEnable =3D 1 << 4;=0D + VOID *TlbReEntry;=0D + UINTN PageSize;=0D +=0D + SwapperPageDir =3D AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));=0D + InvalidPgd =3D AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));=0D + InvalidPudTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE));= =0D + InvalidPmdTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE));= =0D + InvalidPteTable =3D AllocatePages (EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE));= =0D + ZeroMem (InvalidPteTable, PTE_TABLE_SIZE);=0D +=0D + if ((!InvalidPgd) ||=0D + (!InvalidPudTable) ||=0D + (!InvalidPmdTable) ||=0D + (!InvalidPteTable))=0D + {=0D + goto FreeTranslationTable;=0D + }=0D +=0D + /*pgd init*/=0D + PageDirInit (SwapperPageDir , ENTRYS_PER_PGD, InvalidPudTable);=0D + /*pgd init*/=0D + PageDirInit (InvalidPgd, ENTRYS_PER_PGD, InvalidPudTable);=0D + /*pud init*/=0D + PageDirInit (InvalidPudTable, ENTRYS_PER_PUD, InvalidPmdTable);=0D + /*pmd init*/=0D + PageDirInit (InvalidPmdTable, ENTRYS_PER_PMD, InvalidPteTable);=0D + GetMemoryMapFromFwCfg (&MemoryTable);=0D +=0D + PcdStatus |=3D PcdSet64S (PcdSwapPageDir, (UINTN)SwapperPageDir);=0D + PcdStatus |=3D PcdSet64S (PcdInvalidPgd, (UINTN)InvalidPgd);=0D + PcdStatus |=3D PcdSet64S (PcdInvalidPud, (UINTN)InvalidPudTable);=0D + PcdStatus |=3D PcdSet64S (PcdInvalidPmd, (UINTN)InvalidPmdTable);=0D + PcdStatus |=3D PcdSet64S (PcdInvalidPte, (UINTN)InvalidPteTable);=0D + ASSERT_RETURN_ERROR (PcdStatus);=0D +=0D + while (MemoryTable->Length !=3D 0) {=0D + DEBUG ((DEBUG_VERBOSE, "%a %d VirtualBase %p VirtualEnd %p Attributes = %p .\n", __func__, __LINE__,=0D + MemoryTable->VirtualBase,=0D + (MemoryTable->Length + MemoryTable->VirtualBase),=0D + MemoryTable->Attributes));=0D +=0D + PcdStatus =3D FillTranslationTable (MemoryTable);=0D + if (EFI_ERROR (PcdStatus)) {=0D + goto FreeTranslationTable;=0D + }=0D + MemoryTable++;=0D + }=0D +=0D + /*set page size*/=0D + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE);=0D + WRITE_CSR_STLB_PAGE_SIZE (DEFAULT_PAGE_SIZE);=0D + WRITE_CSR_TLBREFILL_PAGE_SIZE (DEFAULT_PAGE_SIZE);=0D + READ_CSR_PAGE_SIZE (PageSize);=0D + if (PageSize !=3D DEFAULT_PAGE_SIZE) {=0D + goto FreeTranslationTable;=0D + }=0D +=0D + TlbReEntry =3D AllocatePages (1);=0D + if (TlbReEntry =3D=3D NULL) {=0D + goto FreeTranslationTable;=0D + }=0D + CopyMem ((char *)TlbReEntry, HandleTlbRefill, (HandleTlbRefillEnd - Hand= leTlbRefill));=0D + SET_REFILL_TLBBASE ((UINTN)HandleTlbRefill);=0D +=0D + DEBUG ((DEBUG_VERBOSE,=0D + "%a %d PteShift %d PteWide %d PmdShift %d PmdWide %d PudShift %d PudW= ide %d PgdShift %d PgdWide %d.\n",=0D + __func__, __LINE__,=0D + PteShift, PteWide, PmdShift, PmdWide,PudShift, PudWide, PgdShift, PgdW= ide));=0D +=0D + LOONGARCH_CSR_WRITEQ (PteShift | PteWide << 5 | PmdShift << 10 | PmdWide= << 15 | PudShift << 20 | PudWide << 25,=0D + LOONGARCH_CSR_PWCTL0);=0D + LOONGARCH_CSR_WRITEQ (PgdShift | PgdWide << 6, LOONGARCH_CSR_PWCTL1);=0D + LOONGARCH_CSR_WRITEQ ((UINTN)SwapperPageDir, LOONGARCH_CSR_PGDL);=0D + LOONGARCH_CSR_WRITEQ ((UINTN)InvalidPgd, LOONGARCH_CSR_PGDH);=0D +=0D + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu Start PageBassAddress %p.\n", __fu= nc__, __LINE__, SwapperPageDir));=0D + LOONGARCH_CSR_XCHGQ ( PageEnable, 1 << 4, LOONGARCH_CSR_CRMD);=0D + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu End.\n", __func__, __LINE__));=0D +=0D + return ;=0D +=0D +FreeTranslationTable:=0D + if (SwapperPageDir) {=0D + FreePages (SwapperPageDir, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));=0D + }=0D +=0D + if (InvalidPgd) {=0D + FreePages (InvalidPgd, EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));=0D + }=0D +=0D + if (InvalidPudTable) {=0D + FreePages (InvalidPudTable, EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE));=0D + }=0D +=0D + if (InvalidPmdTable) {=0D + FreePages (InvalidPmdTable, EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE));=0D + }=0D +=0D + if (InvalidPteTable) {=0D + FreePages (InvalidPteTable, EFI_SIZE_TO_PAGES (PTE_TABLE_SIZE));=0D + }=0D +=0D + PcdSet64S (PcdSwapPageDir, (UINTN)0);=0D + PcdSet64S (PcdInvalidPgd, (UINTN)0);=0D + PcdSet64S (PcdInvalidPud, (UINTN)0);=0D + PcdSet64S (PcdInvalidPmd, (UINTN)0);=0D + PcdSet64S (PcdInvalidPte, (UINTN)0);=0D +=0D + return ;=0D +}=0D +=0D 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..50b785bb6e --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/mmu.h @@ -0,0 +1,104 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Tlb or TLB - Translation Lookaside Buffer=0D + - CSR - Cpu State Register=0D + - PGDL - Page Global Directory Low=0D + - PGDH - Page Global Directory High=0D + - TLBIDX - TLB Index=0D + - TLBREHI - TLB Refill Entry High=0D + - PWCTL - Page Walk Control=0D + - STLB - Singular Page Size TLB=0D + - PS - Page Size=0D +**/=0D +#ifndef MMU_H_=0D +#define MMU_H_=0D +/*page size 4k*/=0D +#define DEFAULT_PAGE_SIZE 0x0c=0D +#define LOONGARCH_CSR_PGDL 0x19 /* Page table base address when VA[= 47] =3D 0 */=0D +#define LOONGARCH_CSR_PGDH 0x1a /* Page table base address when VA[= 47] =3D 1 */=0D +#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP *= /=0D +#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */=0D +#define LOONGARCH_CSR_TLBELO0 0x12 /* TLB EntryLo0 */=0D +#define LOONGARCH_CSR_TLBELO1 0x13 /* TLB EntryLo1 */=0D +#define LOONGARCH_CSR_TLBREHI 0x8e /* TLB refill entryhi */=0D +#define LOONGARCH_CSR_PWCTL0 0x1c /* PWCtl0 */=0D +#define LOONGARCH_CSR_PWCTL1 0x1d /* PWCtl1 */=0D +#define LOONGARCH_CSR_STLBPGSIZE 0x1e=0D +#define CSR_TLBIDX_SIZE_MASK 0x3f000000=0D +#define CSR_TLBIDX_PS_SHIFT 24=0D +#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT=0D +=0D +/*=0D + Set Cpu Status Register STLB Page Size.=0D +=0D + @param val Page Size.=0D +=0D + @retval VOID=0D + */=0D +#define WRITE_CSR_STLB_PAGE_SIZE(val) LOONGARCH_CSR_WRITEQ((val), LOONGAR= CH_CSR_STLBPGSIZE)=0D +/*=0D + Set Cpu Status Register Page Size.=0D +=0D + @param size Page Size.=0D +=0D + @retval VOID=0D + */=0D +#define WRITE_CSR_PAGE_SIZE(size) LOONGARCH_CSR_XCHGQ((size) << CSR_TLBID= X_SIZE, CSR_TLBIDX_SIZE_MASK, LOONGARCH_CSR_TLBIDX)=0D +/*=0D + Set Cpu Status Register TLBREFILL Page Size.=0D +=0D + @param size Page Size.=0D +=0D + @retval VOID=0D + */=0D +#define WRITE_CSR_TLBREFILL_PAGE_SIZE(size) LOONGARCH_CSR_XCHGQ((size) <<= CSR_TLBREHI_PS_SHIFT, CSR_TLBREHI_PS, LOONGARCH_CSR_TLBREHI)=0D +/*=0D + Set Cpu Status Register TLBREFILL Base Address.=0D +=0D + @param BaseAddress the code base address of TLB refills .=0D +=0D + @retval VOID=0D + */=0D +#define SET_REFILL_TLBBASE(BaseAddress) LOONGARCH_CSR_WRITEQ((BaseAddress)= , LOONGARCH_CSR_TLBREBASE);=0D +/*=0D + Get Cpu Status Register Page Size.=0D +=0D + @param val Gets the page size.=0D +=0D + @retval VOID=0D + */=0D +#define READ_CSR_PAGE_SIZE(val) \=0D +{ \=0D + LOONGARCH_CSR_READQ ((val), LOONGARCH_CSR_TLBIDX); \=0D + (val) =3D ((val) & CSR_TLBIDX_SIZE_MASK) >> CSR_TLBIDX_SIZE; \=0D +}=0D +=0D +=0D +#define CSR_TLBREHI_PS_SHIFT 0=0D +#define CSR_TLBREHI_PS ((UINTN)(0x3f) << CSR_TLBREHI_PS_SHIFT)=0D +=0D +#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \=0D + EFI_MEMORY_WC | \=0D + EFI_MEMORY_WT | \=0D + EFI_MEMORY_WB | \=0D + EFI_MEMORY_UCE \=0D + )=0D +=0D +=0D +typedef struct {=0D + EFI_PHYSICAL_ADDRESS PhysicalBase;=0D + EFI_VIRTUAL_ADDRESS VirtualBase;=0D + UINTN Length;=0D + UINTN Attributes;=0D +} MEMORY_REGION_DESCRIPTOR;=0D +=0D +// The total number of descriptors, including the final "end-of-table" des= criptor.=0D +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS (128)=0D +=0D +extern CHAR8 HandleTlbRefill[], HandleTlbRefillEnd[];=0D +#endif=0D 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..3b3b0b72c3 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h @@ -0,0 +1,267 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Pgd or Pgd or PGD - Page Global Directory=0D + - Pud or Pud or PUD - Page Upper Directory=0D + - Pmd or Pmd or PMD - Page Middle Directory=0D + - Pte or pte or PTE - Page Table Entry=0D + - Val or VAL or val - Value=0D + - Dir - Directory=0D +**/=0D +#ifndef PAGE_H_=0D +#define PAGE_H_=0D +=0D +#define MAX_VA_BITS 47=0D +#define PGD_WIDE (8)=0D +#define PUD_WIDE (9)=0D +#define PMD_WIDE (9)=0D +#define PTE_WIDE (9)=0D +=0D +#define ENTRYS_PER_PGD (1 << PGD_WIDE)=0D +#define ENTRYS_PER_PUD (1 << PUD_WIDE)=0D +#define ENTRYS_PER_PMD (1 << PMD_WIDE)=0D +#define ENTRYS_PER_PTE (1 << PTE_WIDE)=0D +=0D +#define PGD_SHIFT (PUD_SHIFT + PUD_WIDE)=0D +#define PUD_SHIFT (PMD_SHIFT + PMD_WIDE)=0D +#define PMD_SHIFT (EFI_PAGE_SHIFT + PTE_WIDE)=0D +#define PTE_SHIFT (EFI_PAGE_SHIFT)=0D +=0D +#define PGD_SIZE (1UL << PGD_SHIFT)=0D +#define PUD_SIZE (1UL << PUD_SHIFT)=0D +#define PMD_SIZE (1UL << PMD_SHIFT)=0D +=0D +#define PGD_MASK (~(PGD_SIZE-1))=0D +#define PUD_MASK (~(PUD_SIZE-1))=0D +#define PMD_MASK (~(PMD_SIZE-1))=0D +#define PAGE_MASK (~(EFI_PAGE_SIZE - 1))=0D +#define PFN_MASK (~(((UINTN)(1) << (EFI_PAGE_SH= IFT)) - 1) & \=0D + (((UINTN)(1) << (PAGE_PFN_END= _SHIFT)) - 1))=0D +=0D +typedef struct { UINTN PgdVal; } PGD;=0D +typedef struct { UINTN PudVal; } PUD;=0D +typedef struct { UINTN PmdVal; } PMD;=0D +typedef struct { UINTN PteVal; } PTE;=0D +/**=0D + Gets the value of the page global directory table entry.=0D +=0D + @param x Page global directory struct variables.=0D +=0D + @retval the value of the page global directory table entry.=0D + **/=0D +#define PGD_VAL(x) ((x).PgdVal)=0D +/**=0D + Gets the value of the page upper directory table entry.=0D +=0D + @param x Page upper directory struct variables.=0D +=0D + @retval the value of the page upper directory table entry.=0D + **/=0D +#define PUD_VAL(x) ((x).PudVal)=0D +/**=0D + Gets the value of the page middle directory table entry.=0D +=0D + @param x Page middle directory struct variables.=0D +=0D + @retval the value of the page middle directory table entry.=0D + **/=0D +#define PMD_VAL(x) ((x).PmdVal)=0D +/**=0D + Gets the value of the page table entry.=0D +=0D + @param x Page table entry struct variables.=0D +=0D + @retval the value of the page table entry.=0D + **/=0D +#define PTE_VAL(x) ((x).PteVal)=0D +=0D +=0D +#define PGD_TABLE_SIZE (ENTRYS_PER_PGD * sizeof(PGD))= =0D +#define PUD_TABLE_SIZE (ENTRYS_PER_PUD * sizeof(PUD))= =0D +#define PMD_TABLE_SIZE (ENTRYS_PER_PMD * sizeof(PMD))= =0D +#define PTE_TABLE_SIZE (ENTRYS_PER_PTE * sizeof(PTE))= =0D +/**=0D + Gets the physical address of the record in the page table entry.=0D +=0D + @param x Page table entry struct variables.=0D +=0D + @retval the value of the physical address.=0D + **/=0D +#define GET_PAGE_ATTRIBUTES(x) (UINTN) {(PTE_VAL(x) & ~PFN_MA= SK)}=0D +/**=0D + Gets the virtual address of the next block of the specified virtual addr= ess=0D + that is aligned with the size of the global page directory mapping.=0D +=0D + @param Address Specifies the virtual address.=0D + @param End The end address of the memory region.=0D +=0D + @retval the specified virtual address of the next block.=0D + **/=0D +#define PGD_ADDRESS_END(Address, End) \=0D +({ UINTN Boundary =3D ((Address) + PGD_SIZE) & PGD_MASK; \=0D + (Boundary - 1 < (End) - 1)? Boundary: (End); \=0D +})=0D +/**=0D + Gets the virtual address of the next block of the specified virtual addr= ess=0D + that is aligned with the size of the page upper directory mapping.=0D +=0D + @param Address Specifies the virtual address.=0D + @param End The end address of the memory region.=0D +=0D + @retval the specified virtual address of the next block.=0D + **/=0D +#define PUD_ADDRESS_END(Address, End) \=0D +({ UINTN Boundary =3D ((Address) + PUD_SIZE) & PUD_MASK; \=0D + (Boundary - 1 < (End) - 1)? Boundary: (End); \=0D +})=0D +/**=0D + Gets the virtual address of the next block of the specified virtual addr= ess=0D + that is aligned with the size of the page middle directory mapping.=0D +=0D + @param Address Specifies the virtual address.=0D + @param End The end address of the memory region.=0D +=0D + @retval the specified virtual address of the next block.=0D + **/=0D +#define PMD_ADDRESS_END(Address, End) \=0D +({ UINTN Boundary =3D ((Address) + PMD_SIZE) & PMD_MASK; \=0D + (Boundary - 1 < (End) - 1)? Boundary: (End); \=0D +})=0D +/**=0D + Get Specifies the virtual address corresponding to the index of the page= global directory table entry.=0D +=0D + @param Address Specifies the virtual address.=0D +=0D + @retval the index of the page global directory table entry.=0D + **/=0D +#define PGD_INDEX(Address) (((Address) >> PGD_SHIFT) & (E= NTRYS_PER_PGD-1))=0D +/**=0D + Get Specifies the virtual address corresponding to the index of the page= upper directory table entry.=0D +=0D + @param Address Specifies the virtual address.=0D + @param End The end address of the memory region.=0D +=0D + @retval the index of the page upper directory table entry.=0D + **/=0D +#define PUD_INDEX(Address) (((Address) >> PUD_SHIFT) & (E= NTRYS_PER_PUD - 1))=0D +/**=0D + Get Specifies the virtual address corresponding to the index of the page= middle directory table entry.=0D +=0D + @param Address Specifies the virtual address.=0D +=0D + @retval the index of the page middle directory table entry.=0D + **/=0D +#define PMD_INDEX(Address) (((Address) >> PMD_SHIFT) & (E= NTRYS_PER_PMD - 1))=0D +/**=0D + Get Specifies the virtual address corresponding to the index of the page= table entry.=0D +=0D + @param Address Specifies the virtual address.=0D +=0D + @retval the index of the page table entry.=0D + **/=0D +#define PTE_INDEX(Address) (((Address) >> EFI_PAGE_SHIFT)= & (ENTRYS_PER_PTE - 1))=0D +=0D +/**=0D + Calculates the value of the page table entry based on the specified virt= ual address and properties.=0D +=0D + @param Address Specifies the virtual address.=0D + @param Attributes Specifies the Attributes.=0D +=0D + @retval the value of the page table entry.=0D + **/=0D +#define MAKE_PTE(Address, Attributes) (PTE){((((Address) >> EFI_PAGE= _SHIFT) << 12) | (Attributes))}=0D +/**=0D + Calculates the value of the Huge page table entry based on the specified= virtual address and properties.=0D +=0D + @param Address Specifies the virtual address.=0D + @param Attributes Specifies the Attributes.=0D +=0D + @retval the value of the HUGE page table entry.=0D + **/=0D +#define MAKE_HUGE_PTE(Address, Attributes) (((((Address) >> PMD_SHIFT) <<= PMD_SHIFT) | ((Attributes) | PAGE_HUGE)))=0D + /**=0D + Check whether the large page table entry is.=0D +=0D + @param Val The value of the page table entry.=0D +=0D + @retval 1 Is huge page table entry.=0D + @retval 0 Isn't huge page table entry.=0D + **/=0D +#define IS_HUGE_PAGE(Val) (((Val) & PAGE_HUGE) =3D=3D PA= GE_HUGE)=0D +#define HUGE_PAGE_SIZE (PMD_SIZE)=0D +=0D + /**=0D + Check that the global page directory table entry is empty.=0D +=0D + @param pgd the global page directory struct variables.=0D +=0D + @retval 1 Is huge page table entry.=0D + @retval 0 Isn't huge page table entry.=0D + **/=0D +STATIC=0D +inline=0D +UINTN=0D +pgd_none (=0D + IN PGD pgd=0D + )=0D +{=0D + return (PGD_VAL(pgd) =3D=3D (UINTN)PcdGet64(PcdInvalidPud));=0D +}=0D +=0D + /**=0D + Check that the page upper directory table entry is empty.=0D +=0D + @param pud Page upper directory struct variables.=0D +=0D + @retval 1 Is huge page table entry.=0D + @retval 0 Isn't huge page table entry.=0D + **/=0D +STATIC=0D +inline=0D +UINTN=0D +pud_none (=0D + IN PUD pud=0D + )=0D +{=0D + return (PUD_VAL(pud) =3D=3D (UINTN)PcdGet64 (PcdInvalidPmd));=0D +}=0D +=0D + /**=0D + Check that the page middle directory table entry is empty.=0D +=0D + @param pmd Page middle directory struct variables.=0D +=0D + @retval 1 Is huge page table entry.=0D + @retval 0 Isn't huge page table entry.=0D + **/=0D +STATIC=0D +inline=0D +UINTN=0D +pmd_none (=0D + IN PMD pmd=0D + )=0D +{=0D + return (PMD_VAL(pmd) =3D=3D (UINTN)PcdGet64(PcdInvalidPte));=0D +}=0D + /**=0D + Check that the page table entry is empty.=0D +=0D + @param pmd Page table entry struct variables.=0D +=0D + @retval 1 Is huge page table entry.=0D + @retval 0 Isn't huge page table entry.=0D + **/=0D +STATIC=0D +inline=0D +UINTN=0D +pte_none (=0D + IN PTE pte=0D + )=0D +{=0D + return (!(PTE_VAL(pte) & (~PAGE_GLOBAL)));=0D +}=0D +#endif=0D 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..d6ac74f9c9 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h @@ -0,0 +1,57 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Tlb or TLB - Translation Lookaside Buffer=0D + - HGLOBAL - Huge Global=0D + - PFN - Page Frame number=0D + - EXEC - Execute=0D + - PLV - Privilege Level=0D + - RPLV - Restricted Privilege Level=0D + - SUC - Strong-ordered UnCached=0D + - CC - Coherent Cached=0D + - WUC - Weak-ordered UnCached=0D +**/=0D +#ifndef PTE_H_=0D +#define PTE_H_=0D +/*Page table property definitions */=0D +#define PAGE_VALID_SHIFT 0=0D +#define PAGE_DIRTY_SHIFT 1=0D +#define PAGE_PLV_SHIFT 2 /* 2~3, two bits */=0D +#define CACHE_SHIFT 4 /* 4~5, two bits */=0D +#define PAGE_GLOBAL_SHIFT 6=0D +#define PAGE_HUGE_SHIFT 6 /* HUGE is a PMD bit */=0D +=0D +#define PAGE_HGLOBAL_SHIFT 12 /* HGlobal is a PMD bit */=0D +#define PAGE_PFN_SHIFT 12=0D +#define PAGE_PFN_END_SHIFT 48=0D +#define PAGE_NO_READ_SHIFT 61=0D +#define PAGE_NO_EXEC_SHIFT 62=0D +#define PAGE_RPLV_SHIFT 63=0D +=0D +/* Used by TLB hardware (placed in EntryLo*) */=0D +#define PAGE_VALID ((UINTN)(1) << PAGE_VALID_SHIFT)=0D +#define PAGE_DIRTY ((UINTN)(1) << PAGE_DIRTY_SHIFT)=0D +#define PAGE_PLV ((UINTN)(3) << PAGE_PLV_SHIFT)=0D +#define PAGE_GLOBAL ((UINTN)(1) << PAGE_GLOBAL_SHIFT)=0D +#define PAGE_HUGE ((UINTN)(1) << PAGE_HUGE_SHIFT)=0D +#define PAGE_HGLOBAL ((UINTN)(1) << PAGE_HGLOBAL_SHIFT)=0D +#define PAGE_NO_READ ((UINTN)(1) << PAGE_NO_READ_SHIFT)=0D +#define PAGE_NO_EXEC ((UINTN)(1) << PAGE_NO_EXEC_SHIFT)=0D +#define PAGE_RPLV ((UINTN)(1) << PAGE_RPLV_SHIFT)=0D +#define CACHE_MASK ((UINTN)(3) << CACHE_SHIFT)=0D +#define PFN_SHIFT (EFI_PAGE_SHIFT - 12 + PAGE_PFN_SHIFT)=0D +=0D +#define PLV_KERNEL 0=0D +#define PLV_USER 3=0D +=0D +#define PAGE_USER (PLV_USER << PAGE_PLV_SHIFT)=0D +#define PAGE_KERNEL (PLV_KERN << PAGE_PLV_SHIFT)=0D +=0D +#define CACHE_SUC (0 << CACHE_SHIFT) /* Strong-ordered UnCached= */=0D +#define CACHE_CC (1 << CACHE_SHIFT) /* Coherent Cached */=0D +#define CACHE_WUC (2 << CACHE_SHIFT) /* Weak-ordered UnCached *= /=0D +#endif=0D --=20 2.31.1