Reviewed-by: Chao Li Thanks, Chao 在 2023/1/13 11:17, xianglai 写道: > Optimize the process of converting huge pages > to page table entries. > > Cc: Ard Biesheuvel > Cc: Bibo Mao > Cc: Chao Li > Cc: Leif Lindholm > Cc: Liming Gao > Cc: Michael D Kinney > Signed-off-by: xianglai li > --- > .../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;