summaryrefslogtreecommitdiff
path: root/OvmfPkg
diff options
context:
space:
mode:
authorChao Li <lichao@loongson.cn>2024-06-14 17:02:59 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-06-18 15:02:15 +0000
commitace279c036fc15a0317a94dade9ee17f685ec592 (patch)
treec2b2317774b0d34590840b220cd5fa5a47db51fe /OvmfPkg
parente3e27f22d248742f3e25598a75de5ab99ef3335c (diff)
downloadedk2-ace279c036fc15a0317a94dade9ee17f685ec592.zip
edk2-ace279c036fc15a0317a94dade9ee17f685ec592.tar.gz
edk2-ace279c036fc15a0317a94dade9ee17f685ec592.tar.bz2
OvmfPkg/LoongArchVirt: Add CpuMmuInit library
Added a new library for LoongArch, it use for initialization the CPU MMU, it consumed the CpuMmuLib. Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Jiewen Yao <jiewen.yao@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>
Diffstat (limited to 'OvmfPkg')
-rw-r--r--OvmfPkg/Include/Library/CpuMmuInitLib.h26
-rw-r--r--OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInit.c200
-rw-r--r--OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.inf35
-rw-r--r--OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.uni14
-rw-r--r--OvmfPkg/OvmfPkg.dec4
5 files changed, 279 insertions, 0 deletions
diff --git a/OvmfPkg/Include/Library/CpuMmuInitLib.h b/OvmfPkg/Include/Library/CpuMmuInitLib.h
new file mode 100644
index 0000000..44b5664
--- /dev/null
+++ b/OvmfPkg/Include/Library/CpuMmuInitLib.h
@@ -0,0 +1,26 @@
+/** @file
+ CPU Memory Map Unit Initialization library header.
+
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiSpec.h>
+
+/**
+ Create a page table and initialize the memory management unit(MMU).
+
+ @param[in] MemoryTable A pointer to a memory ragion table.
+
+ @retval EFI_SUCCESS Configure MMU successfully.
+ EFI_INVALID_PARAMETER MemoryTable is NULL.
+ EFI_UNSUPPORTED MemoryRegionMap failed or out of memory space or size not aligned
+ or MaxLivel out of bound.
+**/
+EFI_STATUS
+EFIAPI
+ConfigureMemoryManagementUnit (
+ IN EFI_MEMORY_DESCRIPTOR *MemoryTable
+ );
diff --git a/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInit.c b/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInit.c
new file mode 100644
index 0000000..be2d98c
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInit.c
@@ -0,0 +1,200 @@
+/** @file
+ CPU Memory Map Unit Initialization library instance.
+
+ 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/CacheMaintenanceLib.h>
+#include <Library/CpuMmuLib.h>
+#include <Library/DebugLib.h>
+#include <Register/LoongArch64/Csr.h>
+#include <Register/LoongArch64/Cpucfg.h>
+
+//
+// Because the page size in edk2 is 4KB, the lowest level
+// page table is align to 12 bits, and the page table width
+// of other levels is set to 9 bits by default, which will
+// be 3 or 4 or 5 level page tables, and continuous.
+//
+// Correspondence between max virtual memory address width
+// and page table level:
+// 39 bit >= VA > 31 bit, 3 level page tables
+// 48 bit >= VA > 40 bit, 4 level page tables
+// 57 bit >= VA > 49 bit, 5 level page tables
+//
+#define DEFAULT_BIT_WIDTH_PER_LEVEL (EFI_PAGE_SHIFT - 3)
+
+/**
+ Decided page walker width, level.
+
+ @param[in, out] PageWalkCfg Page walker value instance.
+ @param[in] BitWidt The bit width what you want, 0 is means use the default bit width.
+
+ @retval PageTableLevelNum The max page table level.
+**/
+STATIC
+UINT8
+DecidePageWalkConfiguration (
+ IN OUT UINT64 *PageWalkCfg OPTIONAL,
+ IN UINT8 BitWidth
+ )
+{
+ CPUCFG_REG1_INFO_DATA CpucfgReg1Data;
+ UINT8 CpuVirtMemAddressWidth;
+ UINT8 PageTableLevelNum;
+ UINT8 CurrentPageTableLevel;
+ UINT32 Pwcl0Value;
+ UINT32 Pwcl1Value;
+
+ //
+ // If BitWidth is 0, use the default bit width.
+ //
+ if (BitWidth == 0) {
+ BitWidth = DEFAULT_BIT_WIDTH_PER_LEVEL;
+ }
+
+ //
+ // Get the the CPU virtual memory address width.
+ //
+ AsmCpucfg (CPUCFG_REG1_INFO, &CpucfgReg1Data.Uint32);
+
+ CpuVirtMemAddressWidth = (UINT8)(CpucfgReg1Data.Bits.VALEN + 1);
+
+ //
+ // Statisitics the maximum page table level
+ //
+ PageTableLevelNum = 0x0;
+ if (((CpuVirtMemAddressWidth - EFI_PAGE_SHIFT) % BitWidth) > 0) {
+ PageTableLevelNum++;
+ }
+
+ PageTableLevelNum += (CpuVirtMemAddressWidth - EFI_PAGE_SHIFT) / BitWidth;
+
+ //
+ // Set page table level
+ //
+ Pwcl0Value = 0x0;
+ Pwcl1Value = 0x0;
+ for (CurrentPageTableLevel = 0x0; CurrentPageTableLevel < PageTableLevelNum; CurrentPageTableLevel++) {
+ if (CurrentPageTableLevel < 0x3) {
+ // Less then or equal to level 3
+ Pwcl0Value |= ((BitWidth * CurrentPageTableLevel + EFI_PAGE_SHIFT) << 10 * CurrentPageTableLevel) |
+ BitWidth << (10 * CurrentPageTableLevel + 5);
+ } else {
+ // Lager then level 3
+ Pwcl1Value |= ((BitWidth * CurrentPageTableLevel + EFI_PAGE_SHIFT) << 12 * (CurrentPageTableLevel - 3)) |
+ BitWidth << (12 * (CurrentPageTableLevel - 3) + 6);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a %d Level %d DIR shift %d.\n",
+ __func__,
+ __LINE__,
+ (CurrentPageTableLevel + 1),
+ (BitWidth * CurrentPageTableLevel + EFI_PAGE_SHIFT)
+ ));
+ }
+
+ *PageWalkCfg = ((UINT64)Pwcl1Value << 32) | Pwcl0Value;
+
+ return PageTableLevelNum;
+}
+
+/**
+ Create a page table and initialize the memory management unit(MMU).
+
+ @param[in] MemoryTable A pointer to a memory ragion table.
+
+ @retval EFI_SUCCESS Configure MMU successfully.
+ EFI_INVALID_PARAMETER MemoryTable is NULL.
+ EFI_UNSUPPORTED MemoryRegionMap failed or out of memory space or size not aligned
+ or MaxLivel out of bound.
+**/
+EFI_STATUS
+EFIAPI
+ConfigureMemoryManagementUnit (
+ IN EFI_MEMORY_DESCRIPTOR *MemoryTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN PageTable;
+ UINT64 PageWalkCfg;
+ UINT8 MaxLevel;
+
+ if (MemoryTable == NULL) {
+ ASSERT (MemoryTable != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Automatically obtain the current appropriate page walker configuration.
+ //
+ MaxLevel = DecidePageWalkConfiguration (&PageWalkCfg, 0);
+
+ if ((MaxLevel < 0) || (MaxLevel > 5)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PageTable = 0;
+ while (MemoryTable->NumberOfPages != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a %d VirtualBase %p VirtualEnd %p Attributes %p .\n",
+ __func__,
+ __LINE__,
+ MemoryTable->VirtualStart,
+ (EFI_PAGES_TO_SIZE (MemoryTable->NumberOfPages) + MemoryTable->VirtualStart),
+ MemoryTable->Attribute
+ ));
+
+ Status = MemoryRegionMap (
+ &PageTable,
+ PageWalkCfg,
+ MemoryTable->VirtualStart,
+ EFI_PAGES_TO_SIZE (MemoryTable->NumberOfPages),
+ MemoryTable->Attribute,
+ 0x0
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ MemoryTable++;
+ }
+
+ //
+ // Configure page walker.
+ //
+ CsrWrite (LOONGARCH_CSR_PWCTL0, (UINT32)PageWalkCfg);
+ if ((PageWalkCfg >> 32) != 0x0) {
+ CsrWrite (LOONGARCH_CSR_PWCTL1, (UINT32)(PageWalkCfg >> 32));
+ }
+
+ //
+ // Set page size
+ //
+ CsrXChg (LOONGARCH_CSR_TLBIDX, (DEFAULT_PAGE_SIZE << CSR_TLBIDX_SIZE), CSR_TLBIDX_SIZE_MASK);
+ CsrWrite (LOONGARCH_CSR_STLBPGSIZE, DEFAULT_PAGE_SIZE);
+ CsrXChg (LOONGARCH_CSR_TLBREHI, (DEFAULT_PAGE_SIZE << CSR_TLBREHI_PS_SHIFT), CSR_TLBREHI_PS);
+
+ //
+ // Enable MMU
+ //
+ CsrWrite (LOONGARCH_CSR_PGDL, PageTable);
+
+ //
+ // Enable Paging
+ //
+ CsrXChg (LOONGARCH_CSR_CRMD, BIT4, BIT4|BIT3);
+
+ DEBUG ((DEBUG_INFO, "%a %d Enable MMU Start PageBassAddress %p.\n", __func__, __LINE__, PageTable));
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.inf b/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.inf
new file mode 100644
index 0000000..64bd3ce
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.inf
@@ -0,0 +1,35 @@
+## @file
+# CPU Memory Map Unit Initialization 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 = CpuMmuInitLib
+ MODULE_UNI_FILE = CpuMmuInitLib.uni
+ FILE_GUID = F67EB983-AC2A-7550-AB69-3BC51A1C895B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuMmuInitLib
+
+#
+# VALID_ARCHITECTURES = LOONGARCH64
+#
+
+[Sources]
+ CpuMmuInit.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ CacheMaintenanceLib
+ CpuMmuLib
+ DebugLib
diff --git a/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.uni b/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.uni
new file mode 100644
index 0000000..907f024
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.uni
@@ -0,0 +1,14 @@
+// /** @file
+// CPU Memory Map Unit Initialization library instance.
+//
+// CPU Memory Map Unit Initialization 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 for PEI modules."
+
+#string STR_MODULE_DESCRIPTION #language en-US "CPU Memory Manager Unit library instance for PEI modules."
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 51be9a5..ad7c196 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -148,6 +148,10 @@
#
HardwareInfoLib|Include/Library/HardwareInfoLib.h
+ ## @libraryclass CPU MMU Initialization library.
+ #
+ CpuMmuInitLib|Include/Library/CpuMmuInitLib.h
+
[Guids]
gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}