On 09/07/15 09:34, Ard Biesheuvel wrote:
> On 6 September 2015 at 14:22, Leif Lindholm <[email protected]> wrote:
>> On 6 September 2015 at 13:05, Ard Biesheuvel <[email protected]> 
>> wrote:
>>> On 6 September 2015 at 14:04, Leif Lindholm <[email protected]> 
>>> wrote:
>>>> On 6 September 2015 at 12:52, Ard Biesheuvel <[email protected]> 
>>>> wrote:
>>>>> On 6 September 2015 at 10:15, Heyi Guo <[email protected]> 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.
>>>>>>
>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>> Signed-off-by: Heyi Guo <[email protected]>
>>>>>> Cc: Leif Lindholm <[email protected]>
>>>>>> Cc: Ard Biesheuvel <[email protected]>
>>>>>> ---
>>>>>>  ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c | 6 ++++--
>>>>>>  1 file changed, 4 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c 
>>>>>> b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
>>>>>> index e7b095c..b039ae1 100644
>>>>>> --- a/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
>>>>>> +++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Mmu.c
>>>>>> @@ -295,14 +295,16 @@ GetBlockEntryListFromAddress (
>>>>>>    if (RegionStart == 0) {
>>>>>>      // Identify the highest possible alignment for the Region Size
>>>>>>      for (BaseAddressAlignment = 0; BaseAddressAlignment < 64; 
>>>>>> BaseAddressAlignment++) {
>>>>>> -      if ((1 << BaseAddressAlignment) & *BlockEntrySize) {
>>>>>> +      // Type casting is needed as literal number will be treated as 
>>>>>> INT32 by
>>>>>> +      // compiler
>>>>>> +      if (((UINT64) 1 << BaseAddressAlignment) & *BlockEntrySize) {
>>>>>
>>>>> Please use '1UL' instead of '(UINT64) 1'
>>>>
>>>> Wouldn't 1ULL be a better choice?
>>>> To still work if someone was to copy code across to a 32-bit arch.
>>>>
>>>
>>> Perhaps yes, although I think it's the 'U' that makes the difference
>>> here, not the number of Ls :-)
>>
>> For this location, certainly.
>> But if the same code was compiled on a 32-bit architecture, it would.
>> UINT64 is the portable way to specify this, but at least ULL means the
>> same on 32- and 64-bit. UL does not.
>>
> 
> Ehm, looking at the surrounding code, we should probably just be using
> LowBitSet64() instead of open coding it.

Also, quite unrelatedly, if you'd like to have a UINT64 left shift that
compiles for 32-bit targets with *all* supported compilers, then you
should call LShiftU64().

Thanks
Laszlo
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to