mirror of https://github.com/acidanthera/audk.git
ArmPkg/Mmu: Increase PageLevel when table found at the targeted level
Below code has bug since *BlockEntrySize and *TableLevel are not updated accordingly: if (IndexLevel == PageLevel) { // And get the appropriate BlockEntry at the next level BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, \ IndexLevel + 1, RegionStart); // Set the last block for this new table *LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, \ TT_ENTRY_COUNT); } Also it doesn't check recursively to get the last level, e.g. the initial PageLevel is 1 and we already have level 2 and 3 tables at this address. What's more, *LastBlockEntry was not updated when we get a table and IndexLevel != PageLevel. So we reorganize the sequence, only updating TranslationTable, PageLevel and BlockEntry in the loop, and setting the other output parameters with the final PageLevel before returning. And LastBlockEntry is only an OUT parameter. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Heyi Guo <heyi.guo@linaro.org> Cc: Leif Lindholm <leif.lindholm@linaro.org> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18424 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
41f890164b
commit
edff645fe4
|
@ -244,7 +244,7 @@ GetBlockEntryListFromAddress (
|
||||||
IN UINT64 RegionStart,
|
IN UINT64 RegionStart,
|
||||||
OUT UINTN *TableLevel,
|
OUT UINTN *TableLevel,
|
||||||
IN OUT UINT64 *BlockEntrySize,
|
IN OUT UINT64 *BlockEntrySize,
|
||||||
IN OUT UINT64 **LastBlockEntry
|
OUT UINT64 **LastBlockEntry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN RootTableLevel;
|
UINTN RootTableLevel;
|
||||||
|
@ -282,14 +282,9 @@ GetBlockEntryListFromAddress (
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Calculate LastBlockEntry from T0SZ - this is the last block entry of the root Translation table
|
|
||||||
//
|
|
||||||
T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
|
T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
|
||||||
// Get the Table info from T0SZ
|
// Get the Table info from T0SZ
|
||||||
GetRootTranslationTableInfo (T0SZ, &RootTableLevel, &RootTableEntryCount);
|
GetRootTranslationTableInfo (T0SZ, &RootTableLevel, &RootTableEntryCount);
|
||||||
// The last block of the root table depends on the number of entry in this table
|
|
||||||
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(RootTable, RootTableEntryCount);
|
|
||||||
|
|
||||||
// If the start address is 0x0 then we use the size of the region to identify the alignment
|
// If the start address is 0x0 then we use the size of the region to identify the alignment
|
||||||
if (RegionStart == 0) {
|
if (RegionStart == 0) {
|
||||||
|
@ -311,12 +306,6 @@ GetBlockEntryListFromAddress (
|
||||||
PageLevel++;
|
PageLevel++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose the found PageLevel to the caller
|
|
||||||
*TableLevel = PageLevel;
|
|
||||||
|
|
||||||
// Now, we have the Table Level we can get the Block Size associated to this table
|
|
||||||
*BlockEntrySize = TT_BLOCK_ENTRY_SIZE_AT_LEVEL (PageLevel);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the Table Descriptor for the corresponding PageLevel. We need to decompose RegionStart to get appropriate entries
|
// Get the Table Descriptor for the corresponding PageLevel. We need to decompose RegionStart to get appropriate entries
|
||||||
//
|
//
|
||||||
|
@ -329,13 +318,10 @@ GetBlockEntryListFromAddress (
|
||||||
// Go to the next table
|
// Go to the next table
|
||||||
TranslationTable = (UINT64*)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);
|
TranslationTable = (UINT64*)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);
|
||||||
|
|
||||||
// If we are at the last level then update the output
|
// If we are at the last level then update the last level to next level
|
||||||
if (IndexLevel == PageLevel) {
|
if (IndexLevel == PageLevel) {
|
||||||
// And get the appropriate BlockEntry at the next level
|
// Enter the next level
|
||||||
BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, IndexLevel + 1, RegionStart);
|
PageLevel++;
|
||||||
|
|
||||||
// Set the last block for this new table
|
|
||||||
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, TT_ENTRY_COUNT);
|
|
||||||
}
|
}
|
||||||
} else if ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) {
|
} else if ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) {
|
||||||
// If we are not at the last level then we need to split this BlockEntry
|
// If we are not at the last level then we need to split this BlockEntry
|
||||||
|
@ -383,11 +369,6 @@ GetBlockEntryListFromAddress (
|
||||||
|
|
||||||
// Fill the BlockEntry with the new TranslationTable
|
// Fill the BlockEntry with the new TranslationTable
|
||||||
*BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY;
|
*BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TableAttributes | TT_TYPE_TABLE_ENTRY;
|
||||||
// Update the last block entry with the newly created translation table
|
|
||||||
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, TT_ENTRY_COUNT);
|
|
||||||
|
|
||||||
// Block Entry points at the beginning of the Translation Table
|
|
||||||
BlockEntry = TranslationTable;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IndexLevel != PageLevel) {
|
if (IndexLevel != PageLevel) {
|
||||||
|
@ -405,17 +386,21 @@ GetBlockEntryListFromAddress (
|
||||||
|
|
||||||
// Fill the new BlockEntry with the TranslationTable
|
// Fill the new BlockEntry with the TranslationTable
|
||||||
*BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TT_TYPE_TABLE_ENTRY;
|
*BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TT_TYPE_TABLE_ENTRY;
|
||||||
// Update the last block entry with the newly created translation table
|
|
||||||
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, TT_ENTRY_COUNT);
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// Case when the new region is part of an existing page table
|
|
||||||
//
|
|
||||||
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable, TT_ENTRY_COUNT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose the found PageLevel to the caller
|
||||||
|
*TableLevel = PageLevel;
|
||||||
|
|
||||||
|
// Now, we have the Table Level we can get the Block Size associated to this table
|
||||||
|
*BlockEntrySize = TT_BLOCK_ENTRY_SIZE_AT_LEVEL (PageLevel);
|
||||||
|
|
||||||
|
// The last block of the root table depends on the number of entry in this table,
|
||||||
|
// otherwise it is always the (TT_ENTRY_COUNT - 1)th entry in the table.
|
||||||
|
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable,
|
||||||
|
(PageLevel == RootTableLevel) ? RootTableEntryCount : TT_ENTRY_COUNT);
|
||||||
|
|
||||||
return BlockEntry;
|
return BlockEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue