From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id CD5A4941554 for ; Mon, 11 Mar 2024 09:38:33 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=HKKqVbn5G39EaqrLihkpDZmaGivznPYIQbdYKNojxL4=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240206; t=1710149912; v=1; b=IC6cUFZ/wDxyEVpdH/HbwSH0nJzMKT6d3NVLHuLL9nrNvluPSPPZe/Dk1++qWzSkHKMcLiRa r7V2M9BWXscfpMB260dyeOfP5OWLv/+N0yWjYgPfWqTDiLgStTepiKLvPIhEYh0S8mSxKDYaAO1 RXoyPOE2Bcap0k3Nw4dJcWbDOiX3WnL1cSeT4YFAI8iBpDLrhqdhQUpDzGa7I81YxaZIKlwdRE9 rX+eUu3BZWjXJus6QwDsqLnxXQ88kkkvW3vEA8yx2l0iSVJiR1Ye771S/klnVhHHrcFCwWy6BAq 0VNrpatW6rDG3ZVMA631ygzmPT6YVP4MOTNR5VqcM9CGQ== X-Received: by 127.0.0.2 with SMTP id LzmVYY7687511xYa8E6PVxix; Mon, 11 Mar 2024 02:38:32 -0700 X-Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web10.58518.1710149909999869701 for ; Mon, 11 Mar 2024 02:38:31 -0700 X-Received: from loongson.cn (unknown [10.2.9.245]) by gateway (Coremail) with SMTP id _____8DxWPAR0e5ljRoXAA--.56576S3; Mon, 11 Mar 2024 17:38:25 +0800 (CST) X-Received: from code-server.gen (unknown [10.2.9.245]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxXs0P0e5l5SRWAA--.26149S2; Mon, 11 Mar 2024 17:38:23 +0800 (CST) From: "Chao Li" To: devel@edk2.groups.io Cc: Ray Ni , Rahul Kumar , Gerd Hoffmann , Baoqi Zhang , Dongyan Qian , Xianglai Li , Bibo Mao Subject: [edk2-devel] [PATCH v1 10/26] UefiCpuPkg: Add CpuMmuLib to UefiCpuPkg Date: Mon, 11 Mar 2024 02:38:31 -0700 Message-Id: <20240311093822.1253815-1-lichao@loongson.cn> In-Reply-To: <20240311093631.1251466-1-lichao@loongson.cn> References: <20240311093631.1251466-1-lichao@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxXs0P0e5l5SRWAA--.26149S2 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQANCGXuwOYA3wAPs5 X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lichao@loongson.cn List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: 4WRvoXSJgge6UsQZASseXgLmx7686176AA= Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b="IC6cUFZ/"; dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io 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=4584 Cc: Ray Ni Cc: Rahul Kumar Cc: Gerd Hoffmann Signed-off-by: Chao Li Co-authored-by: Baoqi Zhang Co-authored-by: Dongyan Qian Co-authored-by: Xianglai Li Co-authored-by: Bibo Mao --- UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf | 38 ++ UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.uni | 14 + .../Library/CpuMmuLib/LoongArch64/CpuMmu.c | 614 ++++++++++++++++++ .../Library/CpuMmuLib/LoongArch64/Page.h | 24 + .../CpuMmuLib/LoongArch64/TlbInvalid.S | 24 + .../CpuMmuLib/LoongArch64/TlbInvalid.h | 24 + UefiCpuPkg/UefiCpuPkg.dsc | 3 + 7 files changed, 741 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..57675ae6c0 --- /dev/null +++ b/UefiCpuPkg/Library/CpuMmuLib/CpuMmuLib.inf @@ -0,0 +1,38 @@ +## @file +# CPU Memory Manager Unit library instance. +# +# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
+# +# 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 + +[Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdCpuMmuIsEnabled ## CONSUMES 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.
+// +// 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..7dde436c7c --- /dev/null +++ b/UefiCpuPkg/Library/CpuMmuLib/LoongArch64/CpuMmu.c @@ -0,0 +1,614 @@ +/** @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.
+ Copyright (c) 2023, Ventana Micro Systems Inc. All Rights Reserved.
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include +#include +#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; +} + +/** + 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); + + Status = UpdateRegionMapping ( + BaseAddress, + Length, + LoongArchAttributes, + PTE_ATTRIBUTES_MASK, + (UINTN *)CsrRead (LOONGARCH_CSR_PGDL), + PcdGetBool (PcdCpuMmuIsEnabled) + ); + + 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.
+ + 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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#----------------------------------------------------------------------------- + +#include + +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.
+ + 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 (#116593): https://edk2.groups.io/g/devel/message/116593 Mute This Topic: https://groups.io/mt/104859881/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-