Optimize the process of converting huge pages
to page table entries.
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Chao Li <lichao@loongson.cn>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
---
.../Library/MmuLib/MmuLibCore.c | 109 +++++++++++++-----
.../LoongArchQemuPkg/Library/MmuLib/page.h | 3 +
2 files changed, 82 insertions(+), 30 deletions(-)
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
index 9e2bd3344a..dac38c63f2 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
@@ -449,6 +449,29 @@ GetPteAddress (
return PteOffset (Pmd, Address);
}
+/**
+ Gets the Attributes of Huge Page.
+
+ @param Pmd A pointer to the page middle directory.
+
+ @retval Value of Attributes.
+**/
+UINTN
+GetHugePageAttributes (
+ IN PMD *Pmd
+ )
+{
+ UINTN Attributes;
+ UINTN GlobalFlag;
+ UINTN HugeVal = PMD_VAL(*Pmd);
+
+ Attributes = HugeVal & (~HUGEP_PAGE_MASK);
+ GlobalFlag = ((Attributes & (1 << PAGE_HGLOBAL_SHIFT)) >> PAGE_HGLOBAL_SHIFT) << PAGE_GLOBAL_SHIFT;
+ Attributes &= ~(1 << PAGE_HGLOBAL_SHIFT);
+ Attributes |= GlobalFlag;
+ return Attributes;
+}
+
/**
Establishes a page table entry based on the specified memory region.
@@ -477,13 +500,13 @@ MemoryMapPteRange (
return EFI_OUT_OF_RESOURCES;
}
+ DEBUG ((DEBUG_VERBOSE,
+ "%a %d Address %p End %p Attributes %llx\n",
+ __func__, __LINE__, Address, End, Attributes));
+
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)))
@@ -500,6 +523,55 @@ MemoryMapPteRange (
return EFI_SUCCESS;
}
+/**
+ Convert Huge Page to Page.
+
+ @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
+ConvertHugePageToPage (
+ IN PMD *Pmd,
+ IN UINTN Address,
+ IN UINTN End,
+ IN UINTN Attributes
+ )
+{
+ UINTN OldAttributes;
+ UINTN HugePageEnd;
+ UINTN HugePageStart;
+ EFI_STATUS Status;
+
+ if ((pmd_none (*Pmd)) ||
+ (!IS_HUGE_PAGE (Pmd->PmdVal)))
+ {
+ Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
+ } else {
+ OldAttributes = GetHugePageAttributes(Pmd);
+ SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte));
+ HugePageStart = Address & PMD_MASK;
+ HugePageEnd = HugePageStart + HUGE_PAGE_SIZE;
+ ASSERT (HugePageEnd >= End);
+
+ if (Address > HugePageStart) {
+ Status |= MemoryMapPteRange (Pmd, HugePageStart, Address, OldAttributes);
+ }
+
+ Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
+
+ if (End < HugePageEnd) {
+ Status |= MemoryMapPteRange (Pmd, End, HugePageEnd, OldAttributes);
+ }
+ }
+
+ return Status;
+}
+
/**
Establishes a page middle directory based on the specified memory region.
@@ -520,10 +592,7 @@ MemoryMapPmdRange (
)
{
PMD *Pmd;
- PTE *Pte;
UINTN Next;
- UINTN AddressStart_HugePage;
- UINTN AddressEnd_HugePage;
Pmd = PmdAllocGet (Pud, Address);
if (!Pmd) {
@@ -534,7 +603,7 @@ MemoryMapPmdRange (
Next = PMD_ADDRESS_END (Address, End);
if (((Address & (~PMD_MASK)) == 0) &&
((Next & (~PMD_MASK)) == 0) &&
- (pmd_none (*Pmd)))
+ (pmd_none (*Pmd) || IS_HUGE_PAGE (Pmd->PmdVal)))
{
DEBUG ((DEBUG_VERBOSE,
"%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p MAKE_HUGE_PTE %p\n",
@@ -543,28 +612,7 @@ MemoryMapPmdRange (
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 ;
- }
- if (AddressEnd_HugePage > End) {
- Next = End;
- }
- }
+ ConvertHugePageToPage (Pmd, Address, Next, Attributes);
}
} while (Pmd++, Address = Next, Address != End);
@@ -788,6 +836,7 @@ LoongArchSetMemoryAttributes (
Attributes = EfiAttributeToLoongArchAttribute (Attributes);
DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddress , Length, Attributes));
MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes);
+ DEBUG ((DEBUG_VERBOSE, "%a %d end.\n", __func__, __LINE__));
return EFI_SUCCESS;
}
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
index 84c7c13919..927aeb018d 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
@@ -42,6 +42,9 @@
#define PFN_MASK (~(((UINTN)(1) << (EFI_PAGE_SHIFT)) - 1) & \
(((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1))
+#define HUGEP_PAGE_MASK (~(((UINTN)(1) << (PMD_SHIFT)) - 1) & \
+ (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1))
+
typedef struct { UINTN PgdVal; } PGD;
typedef struct { UINTN PudVal; } PUD;
typedef struct { UINTN PmdVal; } PMD;
--
2.31.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98432): https://edk2.groups.io/g/devel/message/98432
Mute This Topic: https://groups.io/mt/96239134/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Reviewed-by: Chao Li <lichao@loongson.cn>
Thanks,
Chao
在 2023/1/13 11:17, xianglai 写道:
> Optimize the process of converting huge pages
> to page table entries.
>
> Cc: Ard Biesheuvel<ardb+tianocore@kernel.org>
> Cc: Bibo Mao<maobibo@loongson.cn>
> Cc: Chao Li<lichao@loongson.cn>
> Cc: Leif Lindholm<quic_llindhol@quicinc.com>
> Cc: Liming Gao<gaoliming@byosoft.com.cn>
> Cc: Michael D Kinney<michael.d.kinney@intel.com>
> Signed-off-by: xianglai li<lixianglai@loongson.cn>
> ---
> .../Library/MmuLib/MmuLibCore.c | 109 +++++++++++++-----
> .../LoongArchQemuPkg/Library/MmuLib/page.h | 3 +
> 2 files changed, 82 insertions(+), 30 deletions(-)
>
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
> index 9e2bd3344a..dac38c63f2 100644
> --- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuLibCore.c
> @@ -449,6 +449,29 @@ GetPteAddress (
> return PteOffset (Pmd, Address);
> }
>
> +/**
> + Gets the Attributes of Huge Page.
> +
> + @param Pmd A pointer to the page middle directory.
> +
> + @retval Value of Attributes.
> +**/
> +UINTN
> +GetHugePageAttributes (
> + IN PMD *Pmd
> + )
> +{
> + UINTN Attributes;
> + UINTN GlobalFlag;
> + UINTN HugeVal = PMD_VAL(*Pmd);
> +
> + Attributes = HugeVal & (~HUGEP_PAGE_MASK);
> + GlobalFlag = ((Attributes & (1 << PAGE_HGLOBAL_SHIFT)) >> PAGE_HGLOBAL_SHIFT) << PAGE_GLOBAL_SHIFT;
> + Attributes &= ~(1 << PAGE_HGLOBAL_SHIFT);
> + Attributes |= GlobalFlag;
> + return Attributes;
> +}
> +
> /**
> Establishes a page table entry based on the specified memory region.
>
> @@ -477,13 +500,13 @@ MemoryMapPteRange (
> return EFI_OUT_OF_RESOURCES;
> }
>
> + DEBUG ((DEBUG_VERBOSE,
> + "%a %d Address %p End %p Attributes %llx\n",
> + __func__, __LINE__, Address, End, Attributes));
> +
> 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)))
> @@ -500,6 +523,55 @@ MemoryMapPteRange (
> return EFI_SUCCESS;
> }
>
> +/**
> + Convert Huge Page to Page.
> +
> + @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
> +ConvertHugePageToPage (
> + IN PMD *Pmd,
> + IN UINTN Address,
> + IN UINTN End,
> + IN UINTN Attributes
> + )
> +{
> + UINTN OldAttributes;
> + UINTN HugePageEnd;
> + UINTN HugePageStart;
> + EFI_STATUS Status;
> +
> + if ((pmd_none (*Pmd)) ||
> + (!IS_HUGE_PAGE (Pmd->PmdVal)))
> + {
> + Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
> + } else {
> + OldAttributes = GetHugePageAttributes(Pmd);
> + SetPmd (Pmd, (PTE *)PcdGet64 (PcdInvalidPte));
> + HugePageStart = Address & PMD_MASK;
> + HugePageEnd = HugePageStart + HUGE_PAGE_SIZE;
> + ASSERT (HugePageEnd >= End);
> +
> + if (Address > HugePageStart) {
> + Status |= MemoryMapPteRange (Pmd, HugePageStart, Address, OldAttributes);
> + }
> +
> + Status |= MemoryMapPteRange (Pmd, Address, End, Attributes);
> +
> + if (End < HugePageEnd) {
> + Status |= MemoryMapPteRange (Pmd, End, HugePageEnd, OldAttributes);
> + }
> + }
> +
> + return Status;
> +}
> +
> /**
> Establishes a page middle directory based on the specified memory region.
>
> @@ -520,10 +592,7 @@ MemoryMapPmdRange (
> )
> {
> PMD *Pmd;
> - PTE *Pte;
> UINTN Next;
> - UINTN AddressStart_HugePage;
> - UINTN AddressEnd_HugePage;
>
> Pmd = PmdAllocGet (Pud, Address);
> if (!Pmd) {
> @@ -534,7 +603,7 @@ MemoryMapPmdRange (
> Next = PMD_ADDRESS_END (Address, End);
> if (((Address & (~PMD_MASK)) == 0) &&
> ((Next & (~PMD_MASK)) == 0) &&
> - (pmd_none (*Pmd)))
> + (pmd_none (*Pmd) || IS_HUGE_PAGE (Pmd->PmdVal)))
> {
> DEBUG ((DEBUG_VERBOSE,
> "%a %d Address %p PGD_INDEX %p PUD_INDEX %p PMD_INDEX %p MAKE_HUGE_PTE %p\n",
> @@ -543,28 +612,7 @@ MemoryMapPmdRange (
>
> 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 ;
> - }
> - if (AddressEnd_HugePage > End) {
> - Next = End;
> - }
> - }
> + ConvertHugePageToPage (Pmd, Address, Next, Attributes);
> }
> } while (Pmd++, Address = Next, Address != End);
>
> @@ -788,6 +836,7 @@ LoongArchSetMemoryAttributes (
> Attributes = EfiAttributeToLoongArchAttribute (Attributes);
> DEBUG ((DEBUG_VERBOSE, "%a %d %p %p %p.\n", __func__, __LINE__, BaseAddress , Length, Attributes));
> MemoryMapPageRange (BaseAddress, BaseAddress + Length, Attributes);
> + DEBUG ((DEBUG_VERBOSE, "%a %d end.\n", __func__, __LINE__));
>
> return EFI_SUCCESS;
> }
> diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
> index 84c7c13919..927aeb018d 100644
> --- a/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
> +++ b/Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/page.h
> @@ -42,6 +42,9 @@
> #define PFN_MASK (~(((UINTN)(1) << (EFI_PAGE_SHIFT)) - 1) & \
> (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1))
>
> +#define HUGEP_PAGE_MASK (~(((UINTN)(1) << (PMD_SHIFT)) - 1) & \
> + (((UINTN)(1) << (PAGE_PFN_END_SHIFT)) - 1))
> +
> typedef struct { UINTN PgdVal; } PGD;
> typedef struct { UINTN PudVal; } PUD;
> typedef struct { UINTN PmdVal; } PMD;
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98542): https://edk2.groups.io/g/devel/message/98542
Mute This Topic: https://groups.io/mt/96239134/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.