On 9 September 2015 at 11:53, Heyi Guo <heyi....@linaro.org> wrote:
> There is a hidden bug for below code:
>
> (1 << BaseAddressAlignment) & *BlockEntrySize
>
> From disassembly code, we can the literal number 1 will be treated as
> INT32 by compiler by default, and we'll get 0xFFFFFFFF80000000 when
> BaseAddressAlignment is equal to 31. So we will always get 31 when
> alignment is larger than 31.
>
>     if ((1 << BaseAddressAlignment) & *BlockEntrySize) {
> 5224: f9404be0  ldr x0, [sp,#144]
> 5228: 2a0003e1  mov w1, w0
> 522c: 52800020  mov w0, #0x1                    // #1
> 5230: 1ac12000  lsl w0, w0, w1
> 5234: 93407c01  sxtw  x1, w0
>
> The bug can be replayed on QEMU AARCH64; by adding some debug print,
> we can see lots of level 1 tables created (for block of 1GB) even
> when the region is large enough to use 512GB block size.
>
> Use LowBitSet64() in BaseLib instead to fix the bug.
>
> 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>

Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org>

> ---
>  ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c | 16 ++++------------
>  1 file changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c 
> b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
> index d5d20a2..20f1a7b 100644
> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
> @@ -276,8 +276,8 @@ GetBlockEntryListFromAddress (
>      return NULL;
>    }
>
> -  // Ensure the required size is aligned on 4KB boundary
> -  if ((*BlockEntrySize & (SIZE_4KB - 1)) != 0) {
> +  // Ensure the required size is aligned on 4KB boundary and not 0
> +  if ((*BlockEntrySize & (SIZE_4KB - 1)) != 0 || *BlockEntrySize == 0) {
>      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>      return NULL;
>    }
> @@ -294,18 +294,10 @@ GetBlockEntryListFromAddress (
>    // If the start address is 0x0 then we use the size of the region to 
> identify the alignment
>    if (RegionStart == 0) {
>      // Identify the highest possible alignment for the Region Size
> -    for (BaseAddressAlignment = 0; BaseAddressAlignment < 64; 
> BaseAddressAlignment++) {
> -      if ((1 << BaseAddressAlignment) & *BlockEntrySize) {
> -        break;
> -      }
> -    }
> +    BaseAddressAlignment = LowBitSet64 (*BlockEntrySize);
>    } else {
>      // Identify the highest possible alignment for the Base Address
> -    for (BaseAddressAlignment = 0; BaseAddressAlignment < 64; 
> BaseAddressAlignment++) {
> -      if ((1 << BaseAddressAlignment) & RegionStart) {
> -        break;
> -      }
> -    }
> +    BaseAddressAlignment = LowBitSet64 (RegionStart);
>    }
>
>    // Identify the Page Level the RegionStart must belongs to
> --
> 2.5.0
>
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to