From: "Chao Li" <lichao@loongson.cn>
To: devel@edk2.groups.io
Cc: Ray Ni <ray.ni@intel.com>, Rahul Kumar <rahul1.kumar@intel.com>,
Gerd Hoffmann <kraxel@redhat.com>,
Baoqi Zhang <zhangbaoqi@loongson.cn>,
Dongyan Qian <qiandongyan@loongson.cn>,
Xianglai Li <lixianglai@loongson.cn>,
Bibo Mao <maobibo@loongson.cn>
Subject: [edk2-devel] [PATCH v2 09/13] UefiCpuPkg: Add CpuMmuLib to UefiCpuPkg
Date: Wed, 20 Mar 2024 16:43:31 +0800 [thread overview]
Message-ID: <20240320084331.276727-1-lichao@loongson.cn> (raw)
In-Reply-To: <20240320084152.268323-1-lichao@loongson.cn>
Add a new base library named CpuMmuLib and add a LoongArch64 instance
with in the library.
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4734
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Chao Li <lichao@loongson.cn>
Co-authored-by: Baoqi Zhang <zhangbaoqi@loongson.cn>
Co-authored-by: Dongyan Qian <qiandongyan@loongson.cn>
Co-authored-by: Xianglai Li <lixianglai@loongson.cn>
Co-authored-by: Bibo Mao <maobibo@loongson.cn>
---
UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf | 35 +
UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.uni | 14 +
.../Library/CpuMmuLib/LoongArch64/CpuMmu.c | 638 ++++++++++++++++++
.../Library/CpuMmuLib/LoongArch64/Page.h | 24 +
.../CpuMmuLib/LoongArch64/TlbInvalid.S | 24 +
.../CpuMmuLib/LoongArch64/TlbInvalid.h | 24 +
UefiCpuPkg/UefiCpuPkg.dsc | 3 +
7 files changed, 762 insertions(+)
create mode 100644 UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf
create mode 100644 UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.uni
create mode 100644 UefiCpuPkg/Library/CpuMmuLib/LoongArch64/CpuMmu.c
create mode 100644 UefiCpuPkg/Library/CpuMmuLib/LoongArch64/Page.h
create mode 100644 UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.S
create mode 100644 UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.h
diff --git a/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf b/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf
new file mode 100644
index 0000000000..890a614da2
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf
@@ -0,0 +1,35 @@
+## @file
+# CPU Memory Manager Unit library instance.
+#
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = CpuMmuLib
+ MODULE_UNI_FILE = CpuMmuLib.uni
+ FILE_GUID = DA8F0232-FB14-42F0-922C-63104D2C70BE
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuMmuLib
+
+#
+# VALID_ARCHITECTURES = LOONGARCH64
+#
+
+[Sources.LoongArch64]
+ LoongArch64/TlbInvalid.S | GCC
+ LoongArch64/CpuMmu.c
+ LoongArch64/Page.h
+ LoongArch64/TlbInvalid.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ MemoryAllocationLib
diff --git a/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.uni b/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.uni
new file mode 100644
index 0000000000..2408f2f90b
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.uni
@@ -0,0 +1,14 @@
+// /** @file
+// CPU Memory Manager Unit library instance.
+//
+// CPU Memory Manager Unit library instance.
+//
+// Copyright (c) 2024, Loongson Technology Corporation Limited. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "CPU Memory Manager Unit library instance."
+
+#string STR_MODULE_DESCRIPTION #language en-US "CPU Memory Manager Unit library instance."
diff --git a/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/CpuMmu.c b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/CpuMmu.c
new file mode 100644
index 0000000000..9f57499d3f
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/CpuMmu.c
@@ -0,0 +1,638 @@
+/** @file
+
+ CPU Memory Map Unit Handler Library common functions.
+
+ Copyright (c) 2011-2020, ARM Limited. All rights reserved.
+ Copyright (c) 2016, Linaro Limited. All rights reserved.
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.<BR>
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuMmuLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Register/LoongArch64/Csr.h>
+#include "TlbInvalid.h"
+#include "Page.h"
+
+/**
+ Check to see if mmu successfully initializes.
+
+ @param VOID.
+
+ @retval TRUE Initialization has been completed.
+ FALSE Initialization did not complete.
+**/
+STATIC
+BOOLEAN
+MmuIsInit (
+ VOID
+ )
+{
+ if (CsrRead (LOONGARCH_CSR_PGDL) != 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check to see if mmu is enabled.
+
+ @param VOID.
+
+ @retval TRUE MMU has been enabled.
+ FALSE MMU did not enabled.
+**/
+STATIC
+BOOLEAN
+MmuIsEnabled (
+ VOID
+ )
+{
+ if ((CsrRead (LOONGARCH_CSR_CRMD) & BIT4) != 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Determine if an entry is valid pte.
+
+ @param Entry The entry value.
+
+ @retval TRUE The entry is a valid pte.
+ @retval FALSE The entry is not a valid pte.
+
+**/
+STATIC
+BOOLEAN
+IsValidPte (
+ IN UINTN Entry
+ )
+{
+ if (Entry != INVALID_PAGE) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Determine if an entry is huge page.
+
+ @param Entry The entry value.
+
+ @retval TRUE The entry is a huge page.
+ @retval FALSE The entry is not a valid huge page.
+
+**/
+STATIC
+BOOLEAN
+IsValidHugePage (
+ IN UINTN Entry
+ )
+{
+ if ((Entry & (PAGE_HGLOBAL | PAGE_HUGE)) == (PAGE_HGLOBAL | PAGE_HUGE)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Set an entry to be a valid pte.
+
+ @param Entry The entry value.
+
+ @return The entry value.
+
+**/
+STATIC
+UINTN
+SetValidPte (
+ IN UINTN Entry
+ )
+{
+ /* Set Valid and Global mapping bits */
+ return Entry | PAGE_GLOBAL | PAGE_VALID;
+}
+
+/**
+ Get current max page table level.
+
+ @param VOID.
+
+ @return 5 MAX page level is 5
+ 4 MAX page level is 4
+ 3 MAX page level is 3
+ 0 Invalid
+
+**/
+STATIC
+UINTN
+GetCurrentMaxPageTableLevel (
+ VOID
+ )
+{
+ if (((CsrRead (LOONGARCH_CSR_PWCTL1) >> 18) & 0x3F) != 0x0) {
+ return LEVEL5;
+ } else if (((CsrRead (LOONGARCH_CSR_PWCTL1) >> 6) & 0x3F) != 0x0) {
+ return LEVEL4;
+ } else if (((CsrRead (LOONGARCH_CSR_PWCTL0) >> 25) & 0x3F) != 0x0) {
+ return LEVEL3;
+ }
+
+ return 0;
+}
+
+/**
+ Get current page table bit width.
+
+ @param VOID.
+
+ @return page table bit width
+
+**/
+STATIC
+UINTN
+GetCurrentPageTableBitWidth (
+ VOID
+ )
+{
+ //
+ // PTwidth
+ //
+ return ((CsrRead (LOONGARCH_CSR_PWCTL0) >> 5) & 0x1F);
+}
+
+/**
+ Determine if an entry is a HUGE PTE or 4K PTE.
+
+ @param Entry The entry value.
+ @param Level The current page table level.
+
+ @retval TRUE The entry is a block pte.
+ @retval FALSE The entry is not a block pte.
+
+**/
+STATIC
+BOOLEAN
+IsBlockEntry (
+ IN UINTN Entry,
+ IN UINTN Level
+ )
+{
+ if (Level == (GetCurrentMaxPageTableLevel () - 1)) {
+ return ((Entry & PAGE_VALID) == PAGE_VALID);
+ }
+
+ return IsValidHugePage (Entry);
+}
+
+/**
+ Determine if an entry is a table pte.
+
+ @param Entry The entry value.
+ @param Level The current page table level.
+
+ @retval TRUE The entry is a table pte.
+ @retval FALSE The entry is not a table pte.
+
+**/
+STATIC
+BOOLEAN
+IsTableEntry (
+ IN UINTN Entry,
+ IN UINTN Level
+ )
+{
+ if (Level == (GetCurrentMaxPageTableLevel () - 1)) {
+ //
+ // The last level is PAGE rather than Table.
+ //
+ return FALSE;
+ }
+
+ //
+ // Is DIR4 or DIR3 or DIR2 a Huge Page ?
+ //
+ return (!IsValidHugePage (Entry)) && (IsValidPte (Entry));
+}
+
+/**
+ Replace an existing entry with new value.
+
+ @param Entry The entry pointer.
+ @param Value The new entry value.
+ @param RegionStart The start of region that new value affects.
+ @param IsLiveBlockMapping TRUE if this is live update, FALSE otherwise.
+
+**/
+STATIC
+VOID
+ReplaceTableEntry (
+ IN UINTN *Entry,
+ IN UINTN Value,
+ IN UINTN RegionStart,
+ IN BOOLEAN IsLiveBlockMapping
+ )
+{
+ *Entry = Value;
+
+ if (IsLiveBlockMapping && MmuIsInit ()) {
+ InvalidTlb (RegionStart);
+ }
+}
+
+/**
+ Get an ppn value from an entry.
+
+ @param Entry The entry value.
+
+ @return The ppn value.
+
+**/
+STATIC
+UINTN
+GetPpnfromPte (
+ IN UINTN Entry
+ )
+{
+ return ((Entry & PTE_PPN_MASK) >> PTE_PPN_SHIFT);
+}
+
+/**
+ Set an ppn value to a entry.
+
+ @param Entry The entry value.
+ @param Address The address.
+
+ @return The new entry value.
+
+**/
+STATIC
+UINTN
+SetPpnToPte (
+ UINTN Entry,
+ UINTN Address
+ )
+{
+ UINTN Ppn;
+
+ Ppn = ((Address >> LOONGARCH_MMU_PAGE_SHIFT) << PTE_PPN_SHIFT);
+ ASSERT (~(Ppn & ~PTE_PPN_MASK));
+ Entry &= ~PTE_PPN_MASK;
+ return Entry | Ppn;
+}
+
+/**
+ Free resources of translation table recursively.
+
+ @param TranslationTable The pointer of table.
+ @param Level The current level.
+
+**/
+STATIC
+VOID
+FreePageTablesRecursive (
+ IN UINTN *TranslationTable,
+ IN UINTN Level
+ )
+{
+ UINTN Index;
+ UINTN TableEntryNum;
+
+ TableEntryNum = (1 << GetCurrentPageTableBitWidth ());
+
+ if (Level < (GetCurrentMaxPageTableLevel () - 1)) {
+ for (Index = 0; Index < TableEntryNum; Index++) {
+ if (IsTableEntry (TranslationTable[Index], Level)) {
+ FreePageTablesRecursive (
+ (UINTN *)(GetPpnfromPte ((TranslationTable[Index])) <<
+ LOONGARCH_MMU_PAGE_SHIFT),
+ Level + 1
+ );
+ }
+ }
+ }
+
+ FreePages (TranslationTable, 1);
+}
+
+/**
+ Update region mapping recursively.
+
+ @param RegionStart The start address of the region.
+ @param RegionEnd The end address of the region.
+ @param AttributeSetMask The attribute mask to be set.
+ @param AttributeClearMask The attribute mask to be clear.
+ @param PageTable The pointer of current page table.
+ @param Level The current level.
+ @param TableIsLive TRUE if this is live update, FALSE otherwise.
+
+ @retval EFI_OUT_OF_RESOURCES Not enough resource.
+ @retval EFI_SUCCESS The operation succesfully.
+
+**/
+STATIC
+EFI_STATUS
+UpdateRegionMappingRecursive (
+ IN UINTN RegionStart,
+ IN UINTN RegionEnd,
+ IN UINTN AttributeSetMask,
+ IN UINTN AttributeClearMask,
+ IN UINTN *PageTable,
+ IN UINTN Level,
+ IN BOOLEAN TableIsLive
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlockShift;
+ UINTN BlockMask;
+ UINTN BlockEnd;
+ UINTN *Entry;
+ UINTN EntryValue;
+ UINTN *TranslationTable;
+ UINTN TableEntryNum;
+ UINTN TableBitWidth;
+ BOOLEAN NextTableIsLive;
+
+ ASSERT (Level < GetCurrentMaxPageTableLevel ());
+ ASSERT (((RegionStart | RegionEnd) & EFI_PAGE_MASK) == 0);
+
+ TableBitWidth = GetCurrentPageTableBitWidth ();
+ BlockShift = (GetCurrentMaxPageTableLevel () - Level - 1) * TableBitWidth + LOONGARCH_MMU_PAGE_SHIFT;
+ BlockMask = MAX_ADDRESS >> (64 - BlockShift);
+
+ DEBUG (
+ (
+ DEBUG_VERBOSE,
+ "%a(%d): %llx - %llx set %lx clr %lx\n",
+ __func__,
+ Level,
+ RegionStart,
+ RegionEnd,
+ AttributeSetMask,
+ AttributeClearMask
+ )
+ );
+
+ TableEntryNum = (1 << TableBitWidth);
+ for ( ; RegionStart < RegionEnd; RegionStart = BlockEnd) {
+ BlockEnd = MIN (RegionEnd, (RegionStart | BlockMask) + 1);
+ Entry = &PageTable[(RegionStart >> BlockShift) & (TableEntryNum - 1)];
+
+ //
+ // If RegionStart or BlockEnd is not aligned to the block size at this
+ // level, we will have to create a table mapping in order to map less
+ // than a block, and recurse to create the block or page entries at
+ // the next level. No block mappings are allowed at all at level 2,
+ // so in that case, we have to recurse unconditionally.
+ //
+ if ((Level < 2) ||
+ (((RegionStart | BlockEnd) & BlockMask) != 0) || IsTableEntry (*Entry, Level))
+ {
+ ASSERT (Level < (GetCurrentMaxPageTableLevel () - 1));
+ if (!IsTableEntry (*Entry, Level)) {
+ //
+ // No table entry exists yet, so we need to allocate a page table
+ // for the next level.
+ //
+ TranslationTable = AllocatePages (1);
+ if (TranslationTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (TranslationTable, EFI_PAGE_SIZE);
+
+ if (IsBlockEntry (*Entry, Level)) {
+ //
+ // We are splitting an existing block entry, so we have to populate
+ // the new table with the attributes of the block entry it replaces.
+ //
+ Status = UpdateRegionMappingRecursive (
+ RegionStart & ~BlockMask,
+ (RegionStart | BlockMask) + 1,
+ *Entry & PTE_ATTRIBUTES_MASK,
+ PTE_ATTRIBUTES_MASK,
+ TranslationTable,
+ Level + 1,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // The range we passed to UpdateRegionMappingRecursive () is block
+ // aligned, so it is guaranteed that no further pages were allocated
+ // by it, and so we only have to free the page we allocated here.
+ //
+ FreePages (TranslationTable, 1);
+ return Status;
+ }
+ }
+
+ NextTableIsLive = FALSE;
+ } else {
+ TranslationTable = (UINTN *)(GetPpnfromPte (*Entry) << LOONGARCH_MMU_PAGE_SHIFT);
+ NextTableIsLive = TableIsLive;
+ }
+
+ //
+ // Recurse to the next level
+ //
+ Status = UpdateRegionMappingRecursive (
+ RegionStart,
+ BlockEnd,
+ AttributeSetMask,
+ AttributeClearMask,
+ TranslationTable,
+ Level + 1,
+ NextTableIsLive
+ );
+ if (EFI_ERROR (Status)) {
+ if (!IsTableEntry (*Entry, Level)) {
+ //
+ // We are creating a new table entry, so on failure, we can free all
+ // allocations we made recursively, given that the whole subhierarchy
+ // has not been wired into the live page tables yet. (This is not
+ // possible for existing table entries, since we cannot revert the
+ // modifications we made to the subhierarchy it represents.)
+ //
+ FreePageTablesRecursive (TranslationTable, Level + 1);
+ }
+
+ return Status;
+ }
+
+ if (!IsTableEntry (*Entry, Level)) {
+ EntryValue = SetPpnToPte (0, (UINTN)TranslationTable);
+ ReplaceTableEntry (
+ Entry,
+ EntryValue,
+ RegionStart,
+ TableIsLive
+ );
+ }
+ } else {
+ EntryValue = (*Entry & ~AttributeClearMask) | AttributeSetMask;
+
+ EntryValue = SetPpnToPte (EntryValue, RegionStart);
+ EntryValue = SetValidPte (EntryValue);
+
+ if (Level < (GetCurrentMaxPageTableLevel () - 1)) {
+ EntryValue |= (PAGE_HGLOBAL | PAGE_HUGE | PAGE_VALID);
+ } else {
+ EntryValue |= PAGE_GLOBAL | PAGE_VALID;
+ }
+
+ ReplaceTableEntry (Entry, EntryValue, RegionStart, TableIsLive);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update region mapping at root table.
+
+ @param RegionStart The start address of the region.
+ @param RegionLength The length of the region.
+ @param AttributeSetMask The attribute mask to be set.
+ @param AttributeClearMask The attribute mask to be clear.
+ @param RootTable The pointer of root table.
+ @param TableIsLive TRUE if this is live update, FALSE otherwise.
+
+ @retval EFI_INVALID_PARAMETER The RegionStart or RegionLength was not valid.
+ @retval EFI_OUT_OF_RESOURCES Not enough resource.
+ @retval EFI_SUCCESS The operation succesfully.
+
+**/
+EFI_STATUS
+UpdateRegionMapping (
+ IN UINTN RegionStart,
+ IN UINTN RegionLength,
+ IN UINTN AttributeSetMask,
+ IN UINTN AttributeClearMask,
+ IN UINTN *RootTable,
+ IN BOOLEAN TableIsLive
+ )
+{
+ if (((RegionStart | RegionLength) & EFI_PAGE_MASK) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return UpdateRegionMappingRecursive (
+ RegionStart,
+ RegionStart + RegionLength,
+ AttributeSetMask,
+ AttributeClearMask,
+ RootTable,
+ 0,
+ TableIsLive
+ );
+}
+
+/**
+ Convert EFI Attributes to Loongarch Attributes.
+
+ @param[in] EfiAttributes Efi Attributes.
+
+ @retval Corresponding architecture attributes.
+**/
+UINTN
+EFIAPI
+EfiAttributeConverse (
+ IN UINTN EfiAttributes
+ )
+{
+ UINTN LoongArchAttributes;
+
+ LoongArchAttributes = PAGE_VALID | PAGE_DIRTY | PLV_KERNEL | PAGE_GLOBAL;
+
+ switch (EfiAttributes & EFI_CACHE_ATTRIBUTE_MASK) {
+ case EFI_MEMORY_UC:
+ LoongArchAttributes |= CACHE_SUC;
+ break;
+ case EFI_MEMORY_WC:
+ LoongArchAttributes |= CACHE_WUC;
+ break;
+ case EFI_MEMORY_WT:
+ case EFI_MEMORY_WB:
+ LoongArchAttributes |= CACHE_CC;
+ break;
+ case EFI_MEMORY_WP:
+ LoongArchAttributes &= ~PAGE_DIRTY;
+ break;
+ default:
+ break;
+ }
+
+ // Write protection attributes
+ switch (EfiAttributes & EFI_MEMORY_ACCESS_MASK) {
+ case EFI_MEMORY_RP:
+ LoongArchAttributes |= PAGE_NO_READ;
+ break;
+ case EFI_MEMORY_XP:
+ LoongArchAttributes |= PAGE_NO_EXEC;
+ break;
+ case EFI_MEMORY_RO:
+ LoongArchAttributes &= ~PAGE_DIRTY;
+ break;
+ default:
+ break;
+ }
+
+ return LoongArchAttributes;
+}
+
+/**
+ 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.
+ @param[in] AttributeMask Mask of memory attributes to take into account.
+
+ @retval EFI_SUCCESS The Attributes was set successfully
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryRegionAttributes (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length,
+ IN UINTN Attributes,
+ IN UINT64 AttributeMask
+ )
+{
+ EFI_STATUS Status;
+ UINTN LoongArchAttributes;
+
+ if (!MmuIsInit ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ LoongArchAttributes = EfiAttributeConverse (Attributes);
+
+ //
+ // If MMU is enabled, then page tables must be active.
+ //
+ Status = UpdateRegionMapping (
+ BaseAddress,
+ Length,
+ LoongArchAttributes,
+ PTE_ATTRIBUTES_MASK,
+ (UINTN *)CsrRead (LOONGARCH_CSR_PGDL),
+ MmuIsEnabled ()
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/Page.h b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/Page.h
new file mode 100644
index 0000000000..bd568db967
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/Page.h
@@ -0,0 +1,24 @@
+/** @file
+
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PAGE_H_
+#define PAGE_H_
+
+#define INVALID_PAGE 0
+
+#define LEVEL5 5
+#define LEVEL4 4
+#define LEVEL3 3
+
+#define PTE_ATTRIBUTES_MASK 0x600000000000007EULL
+
+#define PTE_PPN_MASK 0xFFFFFFFFF000ULL
+#define PTE_PPN_SHIFT EFI_PAGE_SHIFT
+#define LOONGARCH_MMU_PAGE_SHIFT EFI_PAGE_SHIFT
+
+#endif // PAGE_H_
diff --git a/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.S b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.S
new file mode 100644
index 0000000000..676aada240
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.S
@@ -0,0 +1,24 @@
+#------------------------------------------------------------------------------
+#
+# Invalid TLB operation function
+#
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#-----------------------------------------------------------------------------
+
+#include <Register/LoongArch64/Csr.h>
+
+ASM_GLOBAL ASM_PFX(InvalidTlb)
+
+#
+# Invalid corresponding TLB entries are based on the address given
+# @param a0 The address corresponding to the invalid page table entry
+# @retval none
+#
+ASM_PFX(InvalidTlb):
+ invtlb INVTLB_ADDR_GTRUE_OR_ASID, $zero, $a0
+ jirl $zero, $ra, 0
+
+ .end
diff --git a/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.h b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.h
new file mode 100644
index 0000000000..5063e6662b
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/TlbInvalid.h
@@ -0,0 +1,24 @@
+/** @file
+
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef INVALID_TLB_H_
+#define INVALID_TLB_H_
+
+/**
+ Invalid corresponding TLB entries are based on the address given
+
+ @param Address The address corresponding to the invalid page table entry
+
+ @retval none
+**/
+VOID
+InvalidTlb (
+ UINTN Address
+ );
+
+#endif // INVALID_TLB_H_
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 2eebd45125..e92ceb6466 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -211,5 +211,8 @@ [Components.RISCV64]
UefiCpuPkg/CpuDxeRiscV64/CpuDxeRiscV64.inf
UefiCpuPkg/CpuMmio2Dxe/CpuMmio2Dxe.inf
+[Components.LOONGARCH64]
+ UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf
+
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
--
2.27.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#116926): https://edk2.groups.io/g/devel/message/116926
Mute This Topic: https://groups.io/mt/105041098/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-03-20 8:43 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-20 8:41 [edk2-devel] [PATCH v2 00/13] Part 2 patch set to add LoongArch support into UefiCpuPkg Chao Li
2024-03-20 8:42 ` [edk2-devel] [PATCH v2 01/13] UefiCpuPkg/CpuTimerLib: Reorder the INF file alphabetically Chao Li
2024-03-22 1:15 ` Ni, Ray
2024-03-20 8:42 ` [edk2-devel] [PATCH v2 02/13] UefiCpuPkg/CpuExceptionHandlerLib: Reorder the INF files alphabetically Chao Li
2024-03-22 1:21 ` Ni, Ray
2024-03-20 8:42 ` [edk2-devel] [PATCH v2 03/13] UefiCpuPkg/MpInitLib: " Chao Li
2024-03-20 8:42 ` [edk2-devel] [PATCH v2 04/13] UefiCpuPkg/CpuDxe: Reorder the INF file alphabetically Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 05/13] UefiCpuPkg: Add LoongArch64 CPU Timer instance Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 06/13] UefiCpuPkg: Add CPU exception library for LoongArch Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 07/13] UefiCpuPkg: Add CpuMmuLib.h to UefiCpuPkg Chao Li
2024-03-25 2:29 ` Ni, Ray
2024-03-25 2:31 ` Ni, Ray
2024-03-25 2:52 ` Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 08/13] UefiCpuPkg: Added a new PCD named PcdCpuExceptionVectorBaseAddress Chao Li
2024-03-20 8:43 ` Chao Li [this message]
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 10/13] UefiCpuPkg: Add CpuMmuInitLib.h to UefiCpuPkg Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 11/13] UefiCpuPkg: Add CpuMmuInitLib " Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 12/13] UefiCpuPkg: Add multiprocessor library for LoongArch64 Chao Li
2024-03-20 8:43 ` [edk2-devel] [PATCH v2 13/13] UefiCpuPkg: Add CpuDxe driver " Chao Li
2024-03-25 2:35 ` Ni, Ray
2024-03-22 12:39 ` [edk2-devel] [PATCH v2 00/13] Part 2 patch set to add LoongArch support into UefiCpuPkg Gerd Hoffmann
2024-03-25 2:46 ` Ni, Ray
2024-03-25 3:10 ` Chao Li
[not found] ` <17BFE34457098413.21233@groups.io>
2024-03-26 1:32 ` Chao Li
[not found] ` <17C02C7EE39BF604.20354@groups.io>
2024-03-29 1:28 ` Chao Li
2024-04-09 2:06 ` Ni, Ray
2024-04-09 4:29 ` Chao Li
2024-04-09 5:27 ` Ni, Ray
2024-04-09 6:21 ` Chao Li
[not found] ` <17C1180424B48FA9.19344@groups.io>
2024-04-03 1:21 ` Chao Li
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=20240320084331.276727-1-lichao@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