[PATCH 1/4] efi_loader: aarch64: align runtime section to 64kb

Michael Walle michael at walle.cc
Fri May 15 13:39:38 CEST 2020


Am 2020-05-15 01:04, schrieb Heinrich Schuchardt:
> On 5/15/20 12:27 AM, Heinrich Schuchardt wrote:
>> On 5/15/20 12:02 AM, Michael Walle wrote:
>>> Am 2020-05-14 23:03, schrieb Heinrich Schuchardt:
>>>> On 5/14/20 9:04 PM, Michael Walle wrote:
>>>>> Am 2020-05-14 20:27, schrieb Heinrich Schuchardt:
>>>>>> On 5/14/20 2:38 PM, Michael Walle wrote:
>>>>>>> Commit 7a82c3051c8f ("efi_loader: Align runtime section to 64kb")
>>>>>>> already aligned the memory region to 64kb, but it does not align 
>>>>>>> the
>>>>>>> actual efi runtime code. Thus it is likely, that 
>>>>>>> efi_add_memory_map()
>>>>>>> actually adds a larger memory region than the efi runtime code 
>>>>>>> really
>>>>>>> is, which is no error I guess. But what actually leads to an 
>>>>>>> error is
>>>>>>> that there might be other efi_add_memory_map() calls with regions
>>>>>>> overlapping with the already registered efi runtime code section.
>>>>>> 
>>>>>> Do you relate to this sentence:
>>>>>> 
>>>>>> "If a 64KiB physical page contains any 4KiB page with any of the
>>>>>> following types listed below, then all 4KiB pages in the 64KiB 
>>>>>> page
>>>>>> must
>>>>>> use identical ARM Memory Page Attributes"?
>>>>> 
>>>>> I don't think this is what I want to fix here.
>>>>> 
>>>>> Commit 7a82c3051c8f ("efi_loader: Align runtime section to 64kb")
>>>>> reserves the memory region for runtime services and align the start
>>>>> (and size) to 64kb boundaries. But the actual runtime services are
>>>>> not 64kb aligned. And at least on my board, another memory region
>>>>> right next to it is reserved as well. But of course as another 
>>>>> type.
>>>>> 
>>>>>>> 
>>>>>>> Align the actual runtime code to 64kb instead.
>>>>>>> 
>>>>>>> Fixes: 7a82c3051c8f ("efi_loader: Align runtime section to 64kb")
>>>>>>> Signed-off-by: Michael Walle <michael at walle.cc>
>>>>>>> ---
>>>>>>>  arch/arm/cpu/armv8/u-boot.lds |  9 ++++++++-
>>>>>>>  lib/efi_loader/efi_memory.c   | 15 ++-------------
>>>>>>>  2 files changed, 10 insertions(+), 14 deletions(-)
>>>>>>> 
>>>>>>> diff --git a/arch/arm/cpu/armv8/u-boot.lds
>>>>>>> b/arch/arm/cpu/armv8/u-boot.lds
>>>>>>> index 2554980595..3bc4675586 100644
>>>>>>> --- a/arch/arm/cpu/armv8/u-boot.lds
>>>>>>> +++ b/arch/arm/cpu/armv8/u-boot.lds
>>>>>>> @@ -27,7 +27,14 @@ SECTIONS
>>>>>>>          CPUDIR/start.o (.text*)
>>>>>>>      }
>>>>>>> 
>>>>>>> -    /* This needs to come before *(.text*) */
>>>>>>> +    /*
>>>>>>> +     * Runtime Services must be 64KiB aligned according to the
>>>>>>> +     * "AArch64 Platforms" section in the UEFI spec (2.7+).
>>>>>> 
>>>>>> This is not the exact requirement of the spec. Please, use a
>>>>>> description
>>>>>> that matches the spec.
>>>>> 
>>>>> well I just moved this exact sentence. I'm not familiar with the 
>>>>> UEFI
>>>>> spec.
>>>>> 
>>>>>> The requirement that 64KiB areas should have the same attributes 
>>>>>> was
>>>>>> already presen in UEFI spec 2.4. Please, drop the version 
>>>>>> reference.
>>>>> 
>>>>> As mentioned above, its about the alignment of the runtime section.
>>>> 
>>>> Please, indicate the exact requirement in the "UEFI 2.8 errata A"
>>>> specification you are refering to. Cf.
>>>> file:///home/zfsdt/Documents/UEFI/UEFI_Spec_2_8_A_Feb14.pdf
>>>> 
>>>> I only found the requirement at the bottom of page 35 of said PDF
>>>> dealing with 64KiB pages.
>>>> 
>>>> Please, further indicate in which respect the current code violates 
>>>> the
>>>> UEFI requirements.
>>> 
>>> I don't try to fix anything regarding the spec. As I said, I don't 
>>> know
>>> what specific section Alex was referring to in his original commit.
>>> 
>>> I guess it is better to give you an example. These are the relevant
>>> outputs on my board using the original code:
>>> 
>>> [..]
>>> __efi_runtime_start=fbd48210
>>> __efi_runtime_end=fbd48b88
>>> efi_add_memory_map: 0xfbd40000 0x10 5 no
>>> [..]
>>> 
>>> Because of the 64k alignment, the whole region from 0xfbd40000 to
>>> 0xfbd50000 is added as EFI_RUNTIME_SERVICES_CODE.
>>> 
>>> Later, another region (that is the spin table) is added. But this
>>> time as EFI_RESERVED_MEMORY_TYPE and the region overlaps the former.
>> 
>> This sounds like a real bug.
>> 
>> Could you, please, indicate which function is adding that spin table 
>> and
>> how the address of the spin table is chosen.
>> 
>> Is this __spin_table in arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S?

yes

>> @Alex:
>> What is that efi_add_memory_map((uintptr_t)&secondary_boot_code,...)
>> call good for? Is that secondary boot code ever invoked *after*
>> ExitBootServices()?
>> See your patch 5a37a2f0140c ("armv8: ls2080a: Declare spin tables as
>> reserved for efi loader").
> 
> In ft_fixup_cpu(), arch/arm/cpu/armv8/fsl-layerscape/fdt.c the address
> of __spin_table is added to the device tree.
> 
> The use of spin tables is described in Documentation/arm64/booting.rst.
> 
> So what is required is that after relocation the runtime code is not in
> the same 64KiB page as __spin_table.

Yes, but I guess its __spin_table as well as secondary_boot_code. But I
still fail to understand how fixing that will eventually fixing the
underlying issue, that is: the reserved runtime code memory region will
be a 64kb page, but the actual runtime code in u-boot will (likely) fit
in one 4k page. Which opens the door for code in u-boot to do
efi_add_memory_map() on 4k pages within the range of the 64kb runtime
code range. I.e. what happened here.

> 
> arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S seems to be inconsistent:
> 
> /* Using 64 bit alignment since the spin table is accessed as data */
>         .align 4
>         .global secondary_boot_code
>         /* Secondary Boot Code starts here */
> secondary_boot_code:
>         .global __spin_table
> __spin_table:
>         .space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE
> 
>         .align 2
> ENTRY(secondary_boot_func)
> 
> .align 4 does not sound like 64bit alignment.
> 
> Function secondary_boot_func() uses __spin_table. But does this memory
> location really have to be the same as the reserved memory area that is
> passed to the kernel in the device tree? Or could this be two different
> memory areas?

What would be different if they are in two different areas? The 
secondary
cores are spinning in secondary_boot_func and poll the __spin_table,
which means both need to be EFI_RESERVED_MEMORY_TYPE.

-michael

> 
> Best regards
> 
> Heinrich
>>> 
>>> [..]
>>> efi_add_memory_map: 0xfbd49000 0x1 0 no
>>> [..]
>>> 
>>> Which eventually leads to
>>> 
>>> [    0.067055] Remapping and enabling EFI services.
>>> [    0.071719] UEFI virtual mapping missing or invalid -- runtime
>>> services will not be available
>>> 
>>> [on a side note, this is because the sort and merge of the memory
>>>  region will split the EFI_RUNTIME_SERVICES_CODE into two regions,
>>>  because there is now one EFI_RESERVED_MEMORY_TYPE region in between]
>>> 
>>> 
>>>>>>> +     *
>>>>>>> +     * This needs to come before *(.text*)
>>>>>>> +     */
>>>>>>> +
>>>>>>> +    . = ALIGN(65536);
>>>>>> 
>>>>>> Isn't this an alignment before relocation that is irrelevant with
>>>>>> regards to the UEFI spec?
>>> 
>>> Oh right. My intention was to align the relocated efi runtime section
>>> to 64kb. So this doesn't work.
>>> 
>>> But to complete the example above, with my (broken) patch applied:
>>> 
>>> __efi_runtime_start=fbd48000
>>> __efi_runtime_end=fbd48978
>>> efi_add_memory_map: 0xfbd48000 0x1 5 no
>>> 
>>> Which works because it basically reverts the original commit
>>> and just adds one 4k page to the memory map.
>>> 
>>> So if there is indeed no such requirement to align the runtime
>>> services to 64kb reverting Alex commit works too.
>>> 
>> 


More information about the U-Boot mailing list