From: "maobibo" <maobibo@loongson.cn>
To: xianglai li <lixianglai@loongson.cn>, devel@edk2.groups.io
Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, ardb@kernel.org
Subject: Re: [edk2-platforms][PATCH V4 05/14] Platform/Loongson: Add MmuLib.
Date: Sat, 29 Oct 2022 14:45:23 +0800 [thread overview]
Message-ID: <eed21b78-113f-543f-d512-be4cbcdd981e@loongson.cn> (raw)
In-Reply-To: <1d54b72b110ab8a6aa5c0f3f029fd4cc43b85c0c.1666335216.git.lixianglai@loongson.cn>
在 2022/10/21 15:11, xianglai li 写道:
> 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=4054
>
> Signed-off-by: xianglai li <lixianglai@loongson.cn>
> ---
> .../LoongArchQemuPkg/Include/Library/MmuLib.h | 85 ++
> .../LoongArchQemuPkg/Library/MmuLib/Mmu.S | 35 +
> .../Library/MmuLib/MmuBaseLib.inf | 35 +
> .../Library/MmuLib/MmuBaseLibPei.inf | 42 +
> .../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, 1808 insertions(+)
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/MmuLib.h
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h
> create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.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
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + 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 Buffer.
> +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 corresponding 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 found
> + 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 the Attributes.
> + @param[in] Length The length of the memory region to set the Attributes.
> + @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 the Attributes.
> + @param[in] Length The length of the memory region to set the Attributes.
> +
> + @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
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/Mmu.S b/Platform/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 @@
> +#------------------------------------------------------------------------------
> +#
> +# LoongArch for LoongArch
> +#
> +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#-----------------------------------------------------------------------------
> +
> +#ifndef _KERNEL
> +#define _KERNEL
> +#endif
> +
> +#include "Library/Cpu.h"
> +#include "LoongArchAsmMacro.h"
> +
> +# Query the page table.
> +#
> +# @param VOID
> +#
> +# @retval VOID
> +ASM_FUNC(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
> +.globl HandleTlbRefillEnd
> +HandleTlbRefillEnd:
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLib.inf 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
> +#
> +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = MmuBaseLib
> + FILE_GUID = da8f0232-fb14-42f0-922c-63104d2c70be
> + MODULE_TYPE = BASE
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = MmuLib
> +
> + CONSTRUCTOR = MmuInitialize
> +[Sources.common]
> + MmuLibCore.c
> +
> +[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/MmuBaseLibPei.inf b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf
> new file mode 100644
> index 0000000000..f6a3cab45f
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf
> @@ -0,0 +1,42 @@
> +## @file
> +#
> +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = MmuPeiLib
> + FILE_GUID = da8f0232-fb14-42f0-922c-63104d2c70bd
> + MODULE_TYPE = BASE
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = MmuLib | SEC PEIM
> +
> +[Sources.common]
> + 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
> + 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..d737759ad2
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
> @@ -0,0 +1,908 @@
> +/** @file
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + 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 <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include "Library/Cpu.h"
> +#include "pte.h"
> +#include "page.h"
> +#include "mmu.h"
> +
> +BOOLEAN mMmuInited = 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 == TRUE) ||
> + (PcdGet64 (PcdSwapPageDir) != 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 = (UINTN)Src;
> + Ptr = (UINTN *)Dst;
> + End = Ptr + Num;
> +
> + for ( ;Ptr < End; Ptr++) {
> + *Ptr = Entry;
> + }
> +
> + return ;
> +}
> +/**
> + Gets the virtual address corresponding to the page global directory table 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 = (UINTN)PGD_VAL (*Pgd);
> + return (PUD *)PgdVal + PUD_INDEX (Address);
> +}
> +/**
> + Gets the virtual address corresponding to the page middle directory table 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 = 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 = (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 = 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 = (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 = (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 = (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 to memory.
> +**/
> +INTN
> +PudAlloc (
> + IN PGD *Pgd
> + )
> +{
> + PUD *Pud = (PUD *) AllocatePages (1);
> + if (!Pud) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + PageDirInit ((VOID *)Pud, ENTRYS_PER_PUD, (VOID *)PcdGet64 (PcdInvalidPmd));
> +
> + 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 to memory.
> +**/
> +EFI_STATUS
> +PmdAlloc (
> + IN PUD *Pud
> + )
> +{
> + PMD *Pmd;
> +
> + Pmd = (PMD *) AllocatePages (1);
> + if (!Pmd) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + PageDirInit ((VOID *)Pmd, ENTRYS_PER_PMD, (VOID *)PcdGet64 (PcdInvalidPte));
> +
> + 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 to memory.
> +**/
> +INTN
> +PteAlloc (
> + IN PMD *Pmd
> + )
> +{
> + PTE *Pte;
> +
> + Pte = (PTE *) AllocatePages (1);
> + if (!Pte) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Pte = 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 address
> +
> + @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 address
> +
> + @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 = (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);
> +}
> + /**
> + Convert page middle directory table entry to tlb entry.
> +
> + @param PmdVal page middle directory table entry value.
> +
> + @retval tlb entry value.
> + **/
> +UINTN
> +PmdToTlbEntry (
> + UINTN PmdVal
> + )
> +{
> + UINTN Value;
> +
> + Value = PmdVal ^ PAGE_HUGE;
> + Value |= ((Value & PAGE_HGLOBAL) >>
> + (PAGE_HGLOBAL_SHIFT - PAGE_GLOBAL_SHIFT));
> +
> + return Value;
> +}
> +
> + /**
> + Update huge tlb.
> +
> + @param address The address corresponding to tlb.
> + @param Pte A pointer to the page table entry.
> +
> + @retval VOID.
> + **/
> +VOID
> +UpdateHugeTlb (
> + IN UINTN address,
> + PTE *Pte)
> +{
> + INTN Idx;
> + UINTN TlbEntry;
> + address &= (PAGE_MASK << 1);
> + LOONGARCH_CSR_WRITEQ (address, LOONGARCH_CSR_TLBEHI);
> + LOONGARCH_TLB_SRCH();
> + LOONGARCH_CSR_READQ (Idx, LOONGARCH_CSR_TLBIDX);
> +
> + if (Idx < 0) {
> + return ;
> + }
> + WRITE_CSR_PAGE_SIZE (HUGE_PAGE_SIZE);
> + TlbEntry = PmdToTlbEntry(PTE_VAL (*Pte));
> + LOONGARCH_CSR_WRITEQ(TlbEntry, LOONGARCH_CSR_TLBELO0);
> + LOONGARCH_CSR_WRITEQ(TlbEntry + (HUGE_PAGE_SIZE >> 1), LOONGARCH_CSR_TLBELO1);
> + LOONGARCH_TLB_WR ();
> +
> + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE);
> +
> + return ;
> +}
> + /**
> + Update tlb.
> +
> + @param address The address corresponding to tlb.
> + @param Pte A pointer to the page table entry.
> +
> + @retval VOID.
> + **/
> +VOID
> +UpdateTlb (
> + IN UINTN address,
> + PTE *Pte)
> +{
> + INTN Idx;
> + if (IS_HUGE_PAGE (Pte->PteVal)) {
> + return UpdateHugeTlb(address, Pte);
> + }
> +
> + address &= (PAGE_MASK << 1);
> + LOONGARCH_CSR_WRITEQ (address, LOONGARCH_CSR_TLBEHI);
> + LOONGARCH_TLB_SRCH();
> + LOONGARCH_CSR_READQ (Idx, LOONGARCH_CSR_TLBIDX);
> +
> + if (Idx < 0) {
> + return ;
> + }
> +
> + if ((UINTN)Pte & sizeof(PTE)) {
> + Pte--;
> + }
> +
> + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE);
> + LOONGARCH_CSR_WRITEQ(PTE_VAL (*Pte), LOONGARCH_CSR_TLBELO0);
> + Pte++;
> + LOONGARCH_CSR_WRITEQ(PTE_VAL (*Pte), LOONGARCH_CSR_TLBELO1);
> + LOONGARCH_TLB_WR ();
> +
> + return ;
> +}
> +
> +/**
> + Gets the physical address of the page table entry corresponding to the specified virtual address.
> +
> + @param Address the corresponding virtual address of the page table entry.
> +
> + @retval A pointer to the page table entry.
> + @retval NULL
> +**/
> +PTE *
> +GetPteAddress (
> + IN UINTN Address
> + )
> +{
> + PGD *Pgd;
> + PUD *Pud;
> + PMD *Pmd;
> +
> + Pgd = PgdOffset (Address);
> +
> + if (pgd_none (*Pgd)) {
> + return NULL;
> + }
> +
> + Pud = PudOffset (Pgd, Address);
> +
> + if (pud_none (*Pud)) {
> + return NULL;
> + }
> +
> + Pmd = 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 = PteAllocGet (Pmd, Address);
> + if (!Pte) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + do {
> + UpDate = FALSE;
> + PteVal = MAKE_PTE (Address, Attributes);
> + DEBUG ((DEBUG_VERBOSE,
> + "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p PTE_INDEX %p MAKE_PTE %p\n",
> + __func__, __LINE__, Address, PGD_INDEX (Address), PUD_INDEX (Address), PMD_INDEX (Address),
> + PTE_INDEX (Address), PteVal));
> +
> + if ((!pte_none (*Pte)) &&
> + (PTE_VAL(*Pte) != PTE_VAL(PteVal)))
> + {
> + UpDate = TRUE;
> + }
> +
> + SetPte (Pte, PteVal);
> + if (UpDate) {
> + UpdateTlb (Address, Pte);
> + }
> + } while (Pte++, Address += EFI_PAGE_SIZE, Address != 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 successfully.
> + @retval EFI_OUT_OF_RESOURCES Page middle directory establishment failed 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 = PmdAllocGet (Pud, Address);
> + if (!Pmd) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + do {
> + Next = PMD_ADDRESS_END (Address, End);
> + if (((Address & (~PMD_MASK)) == 0) &&
> + ((Next & (~PMD_MASK)) == 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 (Address), 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 = Address & PMD_MASK;
> + AddressEnd_HugePage = AddressStart_HugePage + HUGE_PAGE_SIZE;
> + if (MemoryMapPteRange (Pmd, AddressStart_HugePage, AddressEnd_HugePage, Attributes)) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + Pte = GetPteAddress (AddressStart_HugePage);
> + if (Pte == NULL) {
> + continue ;
> + }
> + UpdateTlb (AddressStart_HugePage, Pte);
> + if (AddressEnd_HugePage > End) {
> + Next = End;
> + }
> + }
> + }
> + } while (Pmd++, Address = Next, Address != 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 successfully.
> + @retval EFI_OUT_OF_RESOURCES Page upper directory establishment failed due to resource exhaustion.
> +**/
> +EFI_STATUS
> +MemoryMapPudRange (
> + IN PGD *Pgd,
> + IN UINTN Address,
> + IN UINTN End,
> + IN UINTN Attributes
> + )
> +{
> + PUD *Pud;
> + UINTN Next;
> +
> + Pud = PudAllocGet (Pgd, Address);
> + if (!Pud) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + do {
> + Next = PUD_ADDRESS_END (Address, End);
> + if (MemoryMapPmdRange (Pud, Address, Next, Attributes)) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> + } while (Pud++, Address = Next, Address != 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 successfully.
> + @retval EFI_OUT_OF_RESOURCES Page global directory establishment failed due to resource exhaustion.
> +**/
> +EFI_STATUS
> +MemoryMapPageRange (
> + IN UINTN Start,
> + IN UINTN End,
> + IN UINTN Attributes
> + )
> +{
> + PGD *Pgd;
> + UINTN Next;
> + UINTN Address = Start;
> + EFI_STATUS Err;
> +
> + Pgd = PgdOffset (Address);
> + do {
> + Next = PGD_ADDRESS_END (Address, End);
> + Err = MemoryMapPudRange (Pgd, Address, Next, Attributes);
> + if (Err) {
> + return Err;
> + }
> + } while (Pgd++, Address = Next, Address != 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 to 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 Buffer.
> +Convert EFI Attributes to Loongarch Attributes.
> + @param[in] EfiAttributes Efi Attributes.
> +
> + @retval LoongArch Attributes.
> +**/
> +UINTN
> +EfiAttributeToLoongArchAttribute (
> + IN UINTN EfiAttributes
> + )
> +{
> + UINTN LoongArchAttributes = PAGE_VALID | PAGE_DIRTY | CACHE_CC | PAGE_USER;
I just think that PAGE_KERNEL need be used here rather than PAGE_USER,
it can only be accessed with kernel priviledge.
> + switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
> + case EFI_MEMORY_UC:
> + LoongArchAttributes |= CACHE_SUC;
> + break;
> + case EFI_MEMORY_WC:
> + case EFI_MEMORY_WT:
> + case EFI_MEMORY_WB:
> + LoongArchAttributes |= CACHE_CC;
> + break;
> + default :
> + LoongArchAttributes |= CACHE_CC;
> + break;
> + }
> +
> + // Write protection attributes
> + if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
> + LoongArchAttributes &= ~PAGE_DIRTY;
> + }
> +
> + //eXecute protection attribute
> + if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
> + LoongArchAttributes |= PAGE_NO_EXEC;
> + }
> +
> + return LoongArchAttributes;
> +}
> +
> +/**
> + Finds the length and memory properties of the memory region corresponding 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 found
> + 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 = LShiftU64 (1ULL, MAX_VA_BITS) - 1;
> + Pte = GetPteAddress (BaseAddress);
> +
> + if (!MmuIsInit ()) {
> + return EFI_SUCCESS;
> + }
> + if (Pte == NULL) {
> + return EFI_NOT_FOUND;
> + }
> + Attributes = GET_PAGE_ATTRIBUTES (*Pte);
> + if (IS_HUGE_PAGE (Pte->PteVal)) {
> + *RegionAttributes = Attributes & (~(PAGE_HUGE));
> + *RegionLength += HUGE_PAGE_SIZE;
> + } else {
> + *RegionLength += EFI_PAGE_SIZE;
> + *RegionAttributes = Attributes;
> + }
> +
> + while (BaseAddress <= MaxAddress) {
> + Pte = GetPteAddress (BaseAddress);
> + if (Pte == NULL) {
> + return EFI_SUCCESS;
> + }
> + AttributesTmp = GET_PAGE_ATTRIBUTES (*Pte);
> + if (IS_HUGE_PAGE (Pte->PteVal)) {
> + if (AttributesTmp == Attributes) {
> + *RegionLength += HUGE_PAGE_SIZE;
> + }
> + BaseAddress += HUGE_PAGE_SIZE;
> + } else {
> + if (AttributesTmp == Attributes) {
> + *RegionLength += EFI_PAGE_SIZE;
> + }
> + BaseAddress += 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 the Attributes.
> + @param[in] Length The length of the memory region to set the Attributes.
> + @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 = EfiAttributeToLoongArchAttribute (Attributes);
> + DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddress , 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 the Attributes.
> + @param[in] Length The length of the memory region to set the Attributes.
> +
> + @retval EFI_SUCCESS The Attributes was set successfully
> +**/
> +EFI_STATUS
> +LoongArchSetMemoryRegionNoExec (
> + IN EFI_PHYSICAL_ADDRESS BaseAddress,
> + IN UINTN Length
> + )
> +{
> + if (MmuIsInit ()) {
> + Length = 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) != 0) {
> + mMmuInited = 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..e9f294b356
> --- /dev/null
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.h
> @@ -0,0 +1,39 @@
> +/** @file
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + 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 to resource exhaustion.
> +**/
> +EFI_STATUS
> +FillTranslationTable (
> + IN MEMORY_REGION_DESCRIPTOR *MemoryRegion
> + );
> +#endif
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCorePei.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
> + Platform PEI driver
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> + @par Glossary:
> + - FwCfg - Firmeware Config
> + - Tlb - Translation Lookaside Buffer
> +**/
> +#include <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include "Library/Cpu.h"
> +#include "pte.h"
> +#include "page.h"
> +#include "mmu.h"
> +#include <Library/QemuFwCfgLib.h>
> +#include "MmuLibCore.h"
> +
> +/**
> + Return the Virtual Memory Map of your platform
> +
> + This Virtual Memory Map is used by MemoryInitPei Module to initialize the 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 = 0;
> + ASSERT (VirtualMemoryMap != NULL);
> +
> + VirtualMemoryTable = AllocatePool (
> + sizeof (MEMORY_REGION_DESCRIPTOR) *
> + MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
> + );
> + VirtualMemoryTable[Index].PhysicalBase = 0x10000000;
> + VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
> + VirtualMemoryTable[Index].Length = 0x80000000;
> + VirtualMemoryTable[Index].Attributes = PAGE_VALID | PAGE_USER | CACHE_CC | PAGE_DIRTY;
PAGE_KERNEL need be used here rather than PAGE_USER.
And the memory space from 0x10000000 -- 0x80000000 is mmio space, it should be uncachable. CACHE_SUC should be used here.
> + ++Index;
> +
> + Status = QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __func__, __LINE__, Status));
> + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR));
> + *VirtualMemoryMap = VirtualMemoryTable;
> + return ;
> + }
> + if (FwCfgSize % sizeof MemoryMapEntry != 0) {
> + DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize));
> + }
> +
> + QemuFwCfgSelectItem (FwCfgItem);
> + StartEntry = AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize));
> + QemuFwCfgReadBytes (FwCfgSize, StartEntry);
> + for (Processed = 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); Processed++) {
> + pEntry = StartEntry + Processed;
> + if (pEntry->Length == 0) {
> + continue;
> + }
> +
> + DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry->BaseAddr, pEntry->Length, pEntry->Type));
> + VirtualMemoryTable[Index].PhysicalBase = pEntry->BaseAddr;
> + VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase;
> + VirtualMemoryTable[Index].Length = pEntry->Length;
> + VirtualMemoryTable[Index].Attributes = PAGE_VALID | PAGE_USER | CACHE_CC | PAGE_DIRTY;
> + ++Index;
> + }
> +
> + FreePages (StartEntry, EFI_SIZE_TO_PAGES (FwCfgSize));
> + // End of Table
> + ZeroMem (&VirtualMemoryTable[Index], sizeof (MEMORY_REGION_DESCRIPTOR));
> + *VirtualMemoryMap = VirtualMemoryTable;
> + return ;
> +}
> +
> +/**
> + Create a page table and initialize the MMU.
> +
> + @param[] VOID
> +
> + @retval VOID
> +**/
> +EFIAPI
> +VOID
> +ConfigureMmu (VOID)
> +{
> + PGD *SwapperPageDir = NULL;
> + PGD *InvalidPgd = NULL;
> + PUD *InvalidPudTable = NULL;
> + PMD *InvalidPmdTable = NULL;
> + PTE *InvalidPteTable = NULL;
> + MEMORY_REGION_DESCRIPTOR *MemoryTable = NULL;
> + RETURN_STATUS PcdStatus;
> + UINTN PgdShift = PGD_SHIFT;
> + UINTN PgdWide = PGD_WIDE;
> + UINTN PudShift = PUD_SHIFT;
> + UINTN PudWide = PUD_WIDE;
> + UINTN PmdShift = PMD_SHIFT;
> + UINTN PmdWide = PMD_WIDE;
> + UINTN PteShift = PTE_SHIFT;
> + UINTN PteWide = PTE_WIDE;
> + UINTN PageEnable = 1 << 4;
> + VOID *TlbReEntry;
> + UINTN PageSize;
> +
> + SwapperPageDir = AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));
> + InvalidPgd = AllocatePages (EFI_SIZE_TO_PAGES (PGD_TABLE_SIZE));
> + InvalidPudTable = AllocatePages (EFI_SIZE_TO_PAGES (PUD_TABLE_SIZE));
> + InvalidPmdTable = AllocatePages (EFI_SIZE_TO_PAGES (PMD_TABLE_SIZE));
> + InvalidPteTable = 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 |= PcdSet64S (PcdSwapPageDir, (UINTN)SwapperPageDir);
> + PcdStatus |= PcdSet64S (PcdInvalidPgd, (UINTN)InvalidPgd);
> + PcdStatus |= PcdSet64S (PcdInvalidPud, (UINTN)InvalidPudTable);
> + PcdStatus |= PcdSet64S (PcdInvalidPmd, (UINTN)InvalidPmdTable);
> + PcdStatus |= PcdSet64S (PcdInvalidPte, (UINTN)InvalidPteTable);
> + ASSERT_RETURN_ERROR (PcdStatus);
> +
> + while (MemoryTable->Length != 0) {
> + DEBUG ((DEBUG_VERBOSE, "%a %d VirtualBase %p VirtualEnd %p Attributes %p .\n", __func__, __LINE__,
> + MemoryTable->VirtualBase,
> + (MemoryTable->Length + MemoryTable->VirtualBase),
> + MemoryTable->Attributes));
> +
> + PcdStatus = FillTranslationTable (MemoryTable);
> + if (EFI_ERROR (PcdStatus)) {
> + goto FreeTranslationTable;
> + }
> + MemoryTable++;
> + }
> +
> + /*set page size*/
> + WRITE_CSR_PAGE_SIZE (DEFAULT_PAGE_SIZE);
> + WRITE_CSR_STLB_PAGE_SIZE (DEFAULT_PAGE_SIZE);
> + WRITE_CSR_TLBREFILL_PAGE_SIZE (DEFAULT_PAGE_SIZE);
> + READ_CSR_PAGE_SIZE (PageSize);
> + if (PageSize != DEFAULT_PAGE_SIZE) {
> + goto FreeTranslationTable;
> + }
> +
> + TlbReEntry = AllocatePages (1);
> + if (TlbReEntry == NULL) {
> + goto FreeTranslationTable;
> + }
> + CopyMem ((char *)TlbReEntry, HandleTlbRefill, (HandleTlbRefillEnd - HandleTlbRefill));
> + SET_REFILL_TLBBASE ((UINTN)HandleTlbRefill);
> +
> + DEBUG ((DEBUG_VERBOSE,
> + "%a %d PteShift %d PteWide %d PmdShift %d PmdWide %d PudShift %d PudWide %d PgdShift %d PgdWide %d.\n",
> + __func__, __LINE__,
> + PteShift, PteWide, PmdShift, PmdWide,PudShift, PudWide, PgdShift, PgdWide));
> +
> + LOONGARCH_CSR_WRITEQ (PteShift | PteWide << 5 | PmdShift << 10 | PmdWide << 15 | PudShift << 20 | PudWide << 25,
> + LOONGARCH_CSR_PWCTL0);
> + LOONGARCH_CSR_WRITEQ (PgdShift | PgdWide << 6, LOONGARCH_CSR_PWCTL1);
> + LOONGARCH_CSR_WRITEQ ((UINTN)SwapperPageDir, LOONGARCH_CSR_PGDL);
> + LOONGARCH_CSR_WRITEQ ((UINTN)InvalidPgd, LOONGARCH_CSR_PGDH);
> +
> + DEBUG ((DEBUG_INFO, "%a %d Enable Mmu Start PageBassAddress %p.\n", __func__, __LINE__, SwapperPageDir));
> + LOONGARCH_CSR_XCHGQ ( PageEnable, 1 << 4, LOONGARCH_CSR_CRMD);
> + 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/Platform/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
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + 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] = 0 */
> +#define LOONGARCH_CSR_PGDH 0x1a /* Page table base address when VA[47] = 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
> +
> +/*
> + Set Cpu Status Register STLB Page Size.
> +
> + @param val Page Size.
> +
> + @retval VOID
> + */
> +#define WRITE_CSR_STLB_PAGE_SIZE(val) LOONGARCH_CSR_WRITEQ((val), LOONGARCH_CSR_STLBPGSIZE)
> +/*
> + Set Cpu Status Register Page Size.
> +
> + @param size Page Size.
> +
> + @retval VOID
> + */
> +#define WRITE_CSR_PAGE_SIZE(size) LOONGARCH_CSR_XCHGQ((size) << CSR_TLBIDX_SIZE, CSR_TLBIDX_SIZE_MASK, LOONGARCH_CSR_TLBIDX)
> +/*
> + Set Cpu Status Register TLBREFILL Page Size.
> +
> + @param size Page Size.
> +
> + @retval VOID
> + */
> +#define WRITE_CSR_TLBREFILL_PAGE_SIZE(size) LOONGARCH_CSR_XCHGQ((size) << CSR_TLBREHI_PS_SHIFT, CSR_TLBREHI_PS, LOONGARCH_CSR_TLBREHI)
> +/*
> + Set Cpu Status Register TLBREFILL Base Address.
> +
> + @param BaseAddress the code base address of TLB refills .
> +
> + @retval VOID
> + */
> +#define SET_REFILL_TLBBASE(BaseAddress) LOONGARCH_CSR_WRITEQ((BaseAddress), LOONGARCH_CSR_TLBREBASE);
> +/*
> + Get Cpu Status Register Page Size.
> +
> + @param val Gets the page size.
> +
> + @retval VOID
> + */
> +#define READ_CSR_PAGE_SIZE(val) \
> +{ \
> + LOONGARCH_CSR_READQ ((val), LOONGARCH_CSR_TLBIDX); \
> + (val) = ((val) & CSR_TLBIDX_SIZE_MASK) >> CSR_TLBIDX_SIZE; \
> +}
> +
> +
> +#define CSR_TLBREHI_PS_SHIFT 0
> +#define CSR_TLBREHI_PS ((UINTN)(0x3f) << CSR_TLBREHI_PS_SHIFT)
> +
> +#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" descriptor.
> +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS (128)
> +
> +extern CHAR8 HandleTlbRefill[], HandleTlbRefillEnd[];
> +#endif
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Platform/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
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + 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_SHIFT)) - 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_MASK)}
> +/**
> + Gets the virtual address of the next block of the specified virtual address
> + 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 = ((Address) + PGD_SIZE) & PGD_MASK; \
> + (Boundary - 1 < (End) - 1)? Boundary: (End); \
> +})
> +/**
> + Gets the virtual address of the next block of the specified virtual address
> + 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 = ((Address) + PUD_SIZE) & PUD_MASK; \
> + (Boundary - 1 < (End) - 1)? Boundary: (End); \
> +})
> +/**
> + Gets the virtual address of the next block of the specified virtual address
> + 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 = ((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) & (ENTRYS_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) & (ENTRYS_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) & (ENTRYS_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 virtual 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))}
> +/**
> + 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) | 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) == PAGE_HUGE)
> +#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) == (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) == (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) == (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)));
PAGE_VALID represents the tlb is valid, PAGE_GLOBAL represents tlb entry is valid for all asid processes.
how about using PAGE_VALID bit rather than PAGE_GLOBAL:
return (!(PTE_VAL(pte) & PAGE_VALID));
> +}
> +#endif
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/pte.h b/Platform/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
> +
> + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
> +
> + 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
next prev parent reply other threads:[~2022-10-29 6:45 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-21 7:11 [edk2-platforms][PATCH V4 00/14] Platform: Add Loongson support xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 07/14] Platform/Loongson: Support PEI phase xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 08/14] Platform/Loongson: Add CPU DXE driver xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 09/14] Platform/Loongson: Add PciCpuIoDxe driver xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 10/14] Platform/Loongson: Add timer Dxe driver xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 11/14] Platform/Loongson: Add RealTime Clock lib xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 12/14] Platform/Loongson: Add Platform Boot Manager Lib xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 13/14] Platform/Loongson: Add Reset System Lib xianglai
2022-10-21 7:11 ` [edk2-platforms][PATCH V4 14/14] Platform/Loongson: Support Dxe xianglai
2022-10-24 9:25 ` [edk2-platforms][PATCH V4 01/14] Platform/Loongson: Add Serial Port library xianglai
2022-10-29 3:01 ` maobibo
2022-10-24 9:25 ` [edk2-platforms][PATCH V4 02/14] Platform/Loongson: Support SEC And Add Readme.md xianglai
2022-10-24 9:25 ` [edk2-platforms][PATCH V4 03/14] Platform/Loongson: Add PeiServicesTablePointerLib xianglai
2022-10-24 9:25 ` [edk2-platforms][PATCH V4 04/14] Platform/Loongson: Add QemuFwCfgLib xianglai
2022-10-24 9:25 ` [edk2-platforms][PATCH V4 05/14] Platform/Loongson: Add MmuLib xianglai
2022-10-29 6:45 ` maobibo [this message]
2022-10-24 9:25 ` [edk2-platforms][PATCH V4 06/14] Platform/Loongson: Add StableTimerLib xianglai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=eed21b78-113f-543f-d512-be4cbcdd981e@loongson.cn \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox