[PATCH] arm64: efi: Fix stub cache maintenance

Roy Franz roy.franz at linaro.org
Wed Nov 12 08:44:57 PST 2014


On Wed, Nov 12, 2014 at 11:39 AM, Mark Rutland <mark.rutland at arm.com> wrote:
> While efi-entry.S mentions that efi_entry() will have relocated the
> kernel image, it actually means that efi_entry will have placed a copy
> of the kernel in the appropriate location, and until this is branched to
> at the end of efi_entry.S, all instructions are executed from the
> original image.
>
> Thus while the flush in efi_entry.S does ensure that the copy is visible
> to noncacheable accesses, it does not guarantee that this is true for
> the image instructions are being executed from. This could have
> disasterous effects when the MMU and caches are disabled if the image
> has not been naturally evicted to the PoC.
>
> Additionally, due to a missing dsb following the ic ialluis, the new
> kernel image is not necessarily clean in the I-cache when it is branched
> to, with similar potentially disasterous effects.
>
> This patch adds additional flushing to ensure that the currently
> executing stub text is flushed to the PoC and is thus visible to
> noncacheable accesses. As it is placed after the instructions cache
> maintenance for the new image and __flush_dcache_area already contains a
> dsb, we do not need to add a separate barrier to ensure completion of
> the icache maintenance.
>
> Comments are updated to clarify the situation with regard to the two
> images and the maintenance required for both.

Looks good.
Reviewed-by: Roy Franz <roy.franz at linaro.org>

>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Ian Campbell <ijc at hellion.org.uk>
> Cc: Joel Schopp <joel.schopp at amd.com>
> Cc: Leif Lindholm <leif.lindholm at linaro.org>
> Cc: Mark Salter <msalter at redhat.com>
> Cc: Roy Franz <roy.franz at linaro.org>
> Cc: Will Deacon <will.deacon at arm.com>
> ---
>  arch/arm64/kernel/efi-entry.S | 27 +++++++++++++++++++++------
>  1 file changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
> index 619b1dd..d18a449 100644
> --- a/arch/arm64/kernel/efi-entry.S
> +++ b/arch/arm64/kernel/efi-entry.S
> @@ -54,18 +54,17 @@ ENTRY(efi_stub_entry)
>         b.eq    efi_load_fail
>
>         /*
> -        * efi_entry() will have relocated the kernel image if necessary
> -        * and we return here with device tree address in x0 and the kernel
> -        * entry point stored at *image_addr. Save those values in registers
> -        * which are callee preserved.
> +        * efi_entry() will have copied the kernel image if necessary and we
> +        * return here with device tree address in x0 and the kernel entry
> +        * point stored at *image_addr. Save those values in registers which
> +        * are callee preserved.
>          */
>         mov     x20, x0         // DTB address
>         ldr     x0, [sp, #16]   // relocated _text address
>         mov     x21, x0
>
>         /*
> -        * Flush dcache covering current runtime addresses
> -        * of kernel text/data. Then flush all of icache.
> +        * Calculate size of the kernel Image (same for original and copy).
>          */
>         adrp    x1, _text
>         add     x1, x1, #:lo12:_text
> @@ -73,9 +72,24 @@ ENTRY(efi_stub_entry)
>         add     x2, x2, #:lo12:_edata
>         sub     x1, x2, x1
>
> +       /*
> +        * Flush the copied Image to the PoC, and ensure it is not shadowed by
> +        * stale icache entries from before relocation.
> +        */
>         bl      __flush_dcache_area
>         ic      ialluis
>
> +       /*
> +        * Ensure that the rest of this function (in the original Image) is
> +        * visible when the caches are disabled. The I-cache can't have stale
> +        * entries for the VA range of the current image, so no maintenance is
> +        * necessary.
> +        */
> +       adr     x0, efi_stub_entry
> +       adr     x1, efi_stub_entry_end
> +       sub     x1, x1, x0
> +       bl      __flush_dcache_area
> +
>         /* Turn off Dcache and MMU */
>         mrs     x0, CurrentEL
>         cmp     x0, #CurrentEL_EL2
> @@ -105,4 +119,5 @@ efi_load_fail:
>         ldp     x29, x30, [sp], #32
>         ret
>
> +efi_stub_entry_end:
>  ENDPROC(efi_stub_entry)
> --
> 1.9.1
>



More information about the linux-arm-kernel mailing list