On 7 September 2015 at 11:16, Heyi Guo <heyi....@linaro.org> wrote: > > > On 09/06/2015 09:42 PM, Ard Biesheuvel wrote: >> >> On 6 September 2015 at 10:15, Heyi Guo <heyi....@linaro.org> wrote: >>> >>> 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....@linaro.org> >>> Cc: Leif Lindholm <leif.lindh...@linaro.org> >>> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org> >> >> I am not very familiar with this code, and I am struggling a bit to >> understand it. >> Since you identify at least 2 issues with this code, could you perhaps >> split it up into 2 (or more) patches? >> >> Thanks, >> Ard. > > Hi Ard, > > There are several issues with the original code, but all can be fixed by > updating PageLevel and getting OUT parameters with the final PageLevel, > which I supposed to be one complete modification. > > So I've no good idea on how to split the patch yet. > > Below change can be split but I think it is just a minor change. Please let > me know if you think it is better to split it. > > And LastBlockEntry is only an OUT parameter. >
OK. Let me grab another cup of coffee and I will go through the patch again. -- Ard. >> >>> --- >>> ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c | 45 >>> ++++++++++-------------------- >>> 1 file changed, 15 insertions(+), 30 deletions(-) >>> >>> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c >>> b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c >>> index b039ae1..f7351cd 100644 >>> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c >>> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c >>> @@ -244,7 +244,7 @@ GetBlockEntryListFromAddress ( >>> IN UINT64 RegionStart, >>> OUT UINTN *TableLevel, >>> IN OUT UINT64 *BlockEntrySize, >>> - IN OUT UINT64 **LastBlockEntry >>> + OUT UINT64 **LastBlockEntry >>> ) >>> { >>> UINTN RootTableLevel; >>> @@ -282,14 +282,9 @@ GetBlockEntryListFromAddress ( >>> return NULL; >>> } >>> >>> - // >>> - // Calculate LastBlockEntry from T0SZ - this is the last block entry >>> of the root Translation table >>> - // >>> T0SZ = ArmGetTCR () & TCR_T0SZ_MASK; >>> // Get the Table info from T0SZ >>> 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 (RegionStart == 0) { >>> @@ -321,12 +316,6 @@ GetBlockEntryListFromAddress ( >>> 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 >>> // >>> @@ -339,13 +328,10 @@ GetBlockEntryListFromAddress ( >>> // Go to the next 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) { >>> - // 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); >>> + // Enter the next level >>> + PageLevel++; >>> } >>> } 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 >>> @@ -394,11 +380,6 @@ GetBlockEntryListFromAddress ( >>> >>> // Fill the BlockEntry with the new TranslationTable >>> *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 { >>> if (IndexLevel != PageLevel) { >>> @@ -417,17 +398,21 @@ GetBlockEntryListFromAddress ( >>> >>> // Fill the new BlockEntry with the TranslationTable >>> *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; >>> } >>> >>> -- >>> 2.5.0 >>> > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel