Skip to content

Commit

Permalink
OvmfPkg/LoongArchVirt: Add CpuMmuInit library
Browse files Browse the repository at this point in the history
Added a new library for LoongArch, it use for initialization the CPU
MMU, it consumed the CpuMmuLib.

Cc: Ard Biesheuvel <[email protected]>
Cc: Jiewen Yao <[email protected]>
Cc: Gerd Hoffmann <[email protected]>
Signed-off-by: Chao Li <[email protected]>
Co-authored-by: Baoqi Zhang <[email protected]>
Co-authored-by: Dongyan Qian <[email protected]>
Co-authored-by: Xianglai Li <[email protected]>
Co-authored-by: Bibo Mao <[email protected]>
  • Loading branch information
5 people authored and mergify[bot] committed Jun 18, 2024
1 parent e3e27f2 commit ace279c
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 0 deletions.
26 changes: 26 additions & 0 deletions OvmfPkg/Include/Library/CpuMmuInitLib.h
Original file line number Diff line number Diff line change
@@ -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
);
200 changes: 200 additions & 0 deletions OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInit.c
Original file line number Diff line number Diff line change
@@ -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;
}
35 changes: 35 additions & 0 deletions OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.inf
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions OvmfPkg/LoongArchVirt/Library/CpuMmuInitLib/CpuMmuInitLib.uni
Original file line number Diff line number Diff line change
@@ -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."
4 changes: 4 additions & 0 deletions OvmfPkg/OvmfPkg.dec
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down

0 comments on commit ace279c

Please sign in to comment.