On 6 September 2015 at 10:15, Heyi Guo <[email protected]> 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 <[email protected]>
> Cc: Leif Lindholm <[email protected]>
> Cc: Ard Biesheuvel <[email protected]>

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.

> ---
>  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
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to