On 6/1/20 9:53 PM, Michael Walle wrote:
> On ARM64, a 64kb region is reserved for the runtime services code.
> Unfortunately, this code overlaps with the spin table code, which also
> needs to be reserved. Thus now that the code is relocatable, allocate a
> new page from EFI, copy the spin table code into it, update any pointers
> to the old region and the start the secondary CPUs.
>
> Signed-off-by: Michael Walle <mich...@walle.cc>
> ---
>  arch/arm/cpu/armv8/fsl-layerscape/mp.c | 36 ++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
>
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/mp.c 
> b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
> index d50c5a437b..bd85351705 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/mp.c
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
> @@ -79,6 +79,10 @@ int fsl_layerscape_wake_seconday_cores(void)
>       u32 cores, cpu_up_mask = 1;
>       int i, timeout = 10;
>       u64 *table;
> +#ifdef CONFIG_EFI_LOADER
> +     u64 reloc_addr = U32_MAX;
> +     efi_status_t ret;
> +#endif
>
>  #ifdef COUNTER_FREQUENCY_REAL
>       /* update for secondary cores */
> @@ -87,6 +91,38 @@ int fsl_layerscape_wake_seconday_cores(void)
>                          (unsigned long)&__real_cntfrq + 8);
>  #endif
>
> +#ifdef CONFIG_EFI_LOADER
> +     /*
> +      * EFI will reserve 64kb for its runtime services. This will probably
> +      * overlap with our spin table code, which is why we have to relocate
> +      * it.
> +      * Keep this after the __real_cntfrq update, so we have it when we
> +      * copy the complete section here.
> +      */
> +     ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
> +                              EFI_RESERVED_MEMORY_TYPE,
> +                              efi_size_in_pages(secondary_boot_code_size),
> +                              &reloc_addr);
> +     if (ret == EFI_SUCCESS) {
> +             debug("Relocating spin table from %llx to %llx (size %lx)\n",
> +                   (u64)secondary_boot_code_start, reloc_addr,
> +                   secondary_boot_code_size);
> +             memcpy((void *)reloc_addr, secondary_boot_code_start,
> +                    secondary_boot_code_size);
> +             flush_dcache_range(reloc_addr,
> +                                reloc_addr + secondary_boot_code_size);
> +
> +             /* set new entry point for secondary cores */
> +             secondary_boot_addr += (void *)reloc_addr -
> +                                    secondary_boot_code_start;
> +             flush_dcache_range((unsigned long)&secondary_boot_addr,
> +                                (unsigned long)&secondary_boot_addr + 8);

Wouldn't you want to flush the complete target range of memcpy() and
afterwards call invalidate_icache_all(). At least this is what we do in
other cases after copying instructions. Cf. efi_runtime_relocate().

Best regards

Heinrich

> +
> +             /* this will be used to reserve the memory */
> +             secondary_boot_code_start = (void *)reloc_addr;
> +     }
> +#endif
> +
>       cores = cpu_mask();
>       /* Clear spin table so that secondary processors
>        * observe the correct value after waking up from wfe.
>

Reply via email to