From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) by mx.groups.io with SMTP id smtpd.web12.15351.1583344261698909444 for ; Wed, 04 Mar 2020 09:51:02 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=OsHiaIxT; spf=pass (domain: linaro.org, ip: 209.85.128.52, mailfrom: ard.biesheuvel@linaro.org) Received: by mail-wm1-f52.google.com with SMTP id a141so2794042wme.2 for ; Wed, 04 Mar 2020 09:51:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=th8aZI29FfULgC5DoA4xniNuDi0c84bBu/6Wwa9T4GE=; b=OsHiaIxTQu90AYZeAuvdoX+Y+d7INYIqpB0HVcVIDuWZ0GkMRf80cdF2P+bZCVL/lA pm02tyDj8swF2USBbU+SyGJ/A2Je5cVsQ5Ysa4Sqe4hzO93TyqEC5QDf0Ak4cVtpbVZI ew6dGHheurgHAFF3XlTtVVORtGZ5GKbyPf6xGTyX6SWFOXokbXpJRFItVlnjiWAWTLDQ f0nBld60muoIVT9gZjLFWZrNtp35zsc4NqvQf/VHOzrONRCvo1VPo7drWrrEd7AzcWuG A3sS8JpXTTJYM4sMKeeztBEZlENF+9M0idOLMRnqdkOEYm1EW/tz+6+NeIl2W/BmthmO oXYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=th8aZI29FfULgC5DoA4xniNuDi0c84bBu/6Wwa9T4GE=; b=UpGvdwAiaIstyGKwjDOBtICmH4iYbDEk4V0tZBe4+zmY3ob6E7CIc9PiTpMh4G/9E1 L3GtFg3CyScecqwl4U2+2PX6p+wXgW04nPXB9sfmd5WrPRITbyZZbKelDFk6GH2BL4XU OuaTbUEluffSorB1DVh63vKS7ybsaGRZrEYNETxIejjzhMoo+t7M36s9ifq+hW2zvV/T UFDHQCZbtpkDtbXNbyiSC7qxn97kIimqb2FtUk45R39uPd4B04lymGZIXTfTFL1+cV0k QT77fJlcNb1GWj+1CMqD6y59RP7JN+sCIbSjN51pryCmo8maUpnPl+xxLWgp1YyOc3aO HVCw== X-Gm-Message-State: ANhLgQ01rj9TdwWUOY04BM5rsnc7Ki4fKuLiL7TVA49d2z1NRQqXl0pq 7jN2Gyko7nwThZgJFP+rUwjmgh9P9qco4w== X-Google-Smtp-Source: ADFU+vuWXiaQL3ZmkOxWiMSIL3VMEd7gBo5jV42mplAGlZbY9rbf4OH7xN6pF7+vIhPr+2KqVQgu4A== X-Received: by 2002:a7b:ce92:: with SMTP id q18mr4750275wmj.147.1583344259837; Wed, 04 Mar 2020 09:50:59 -0800 (PST) Return-Path: Received: from cam-smtp0.cambridge.arm.com ([2a01:cb1d:112:6f00:816e:ff0d:fb69:f613]) by smtp.gmail.com with ESMTPSA id b82sm5411055wmb.16.2020.03.04.09.50.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2020 09:50:59 -0800 (PST) From: "Ard Biesheuvel" To: devel@edk2.groups.io Cc: leif@nuviainc.com, Ard Biesheuvel Subject: [PATCH edk2-platforms v2 1/1] Platform/ARM/ArmShellCmdRunAxf: switch to by-VA cache maintenance Date: Wed, 4 Mar 2020 18:50:56 +0100 Message-Id: <20200304175056.18107-1-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.17.1 Currently, the 'runaxf' shell command that exists only on ARM's own development platforms deals with the caches in an unsafe manner, as it relies on set/way maintenance to ensure that the ELF image it has put into memory, as well as the running image itself is visible in memory after the MMU and caches are disabled. So let's switch to by-VA maintenance for the currently running image, as well as the ELF image, and use a helper in assembly to ensure that we are not relying on the stack between the disabling of the MMU and the invocation of the ELF image. Signed-off-by: Ard Biesheuvel --- v2: - call ArmDisableMmu() directly from the pivot code, instead of via an indirect branch - move ArmDisableDataCache() call into the pivot code as well - perform I-cache invalidation on the loaded ELF image, but leave the I-cache enabled Platform/ARM/Library/ArmShellCmdRunAxf/AArch64/Pivot.S | 41 +++++++++ Platform/ARM/Library/ArmShellCmdRunAxf/Arm/Pivot.S | 41 +++++++++ Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf | 8 ++ Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c | 89 +++++++++----------- 4 files changed, 131 insertions(+), 48 deletions(-) diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/AArch64/Pivot.S b/Platform/ARM/Library/ArmShellCmdRunAxf/AArch64/Pivot.S new file mode 100644 index 000000000000..1ab4b15f127b --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/AArch64/Pivot.S @@ -0,0 +1,41 @@ +// +// Copyright (c) 2020, ARM Limited. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +#include + +// VOID +// RunAxfPivot ( +// IN ELF_ENTRYPOINT ElfEntry +// IN UINTN Arg0, +// IN UINTN Arg1, +// IN UINTN Arg2, +// IN UINTN Arg3 +// ); +ASM_FUNC(RunAxfPivot) + // Preserve ElfEntry() and its arguments + // Since we will not be returning from this function, we can clobber + // callee preserved register instead. + mov x19, x0 + mov x20, x1 + mov x21, x2 + mov x22, x3 + mov x23, x4 + + bl ArmDisableDataCache + bl ArmDisableMmu + + // Load ElfEntry()'s arguments into x0...x3 + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + // Call ElfEntry() + blr x19 + +0:wfi + wfe + b 0b diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/Arm/Pivot.S b/Platform/ARM/Library/ArmShellCmdRunAxf/Arm/Pivot.S new file mode 100644 index 000000000000..50efcfacdfe6 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/Arm/Pivot.S @@ -0,0 +1,41 @@ +// +// Copyright (c) 2020, ARM Limited. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +#include + +// VOID +// RunAxfPivot ( +// IN ELF_ENTRYPOINT ElfEntry +// IN UINTN Arg0, +// IN UINTN Arg1, +// IN UINTN Arg2, +// IN UINTN Arg3 +// ); +ASM_FUNC(RunAxfPivot) + // Preserve ElfEntry() and its arguments without using the stack. + // Since we will not be returning from this function, we can clobber + // callee preserved register instead. + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, r3 + pop {r8} + + bl ArmDisableDataCache + bl ArmDisableMmu + + // Load ElfEntry()'s arguments into x0...x3 + mov r0, r5 + mov r1, r6 + mov r2, r7 + mov r3, r8 + + // Call ElfEntry() + blx r4 + +0:wfi + wfe + b 0b diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf index 74c6a0e84fdf..7c27a765bd5c 100644 --- a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf @@ -27,6 +27,12 @@ [Sources.common] elf64.h elf_common.h +[Sources.AARCH64] + AArch64/Pivot.S + +[Sources.ARM] + Arm/Pivot.S + [Packages] ArmPkg/ArmPkg.dec MdeModulePkg/MdeModulePkg.dec @@ -37,11 +43,13 @@ [Packages] [LibraryClasses] ArmLib BaseLib + CacheMaintenanceLib DebugLib HiiLib ShellLib [Protocols] + gEfiLoadedImageProtocolGuid gEfiShellDynamicCommandProtocolGuid [Guids] diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c b/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c index 153aed2ab6bd..dbad50ae866a 100644 --- a/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c @@ -10,6 +10,7 @@ #include +#include #include #include #include @@ -20,6 +21,8 @@ #include +#include + #include "ArmShellCmdRunAxf.h" #include "ElfLoader.h" #include "BootMonFsLoader.h" @@ -85,37 +88,21 @@ ShutdownUefiBootServices ( return Status; } - -STATIC -EFI_STATUS -PreparePlatformHardware ( - VOID - ) -{ - //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called. - - // Clean before Disable else the Stack gets corrupted with old data. - ArmCleanDataCache (); - ArmDisableDataCache (); - // Invalidate all the entries that might have snuck in. - ArmInvalidateDataCache (); - - // Disable and invalidate the instruction cache - ArmDisableInstructionCache (); - ArmInvalidateInstructionCache (); - - // Turn off MMU - ArmDisableMmu(); - - return EFI_SUCCESS; -} - // Process arguments to pass to AXF? STATIC CONST SHELL_PARAM_ITEM ParamList[] = { {NULL, TypeMax} }; +VOID +RunAxfPivot ( + IN ELF_ENTRYPOINT ElfEntry, + IN UINTN Arg0, + IN UINTN Arg1, + IN UINTN Arg2, + IN UINTN Arg3 + ); + /** This is the shell command handler function pointer callback type. This function handles the command when it is invoked in the shell. @@ -139,23 +126,23 @@ ShellDynCmdRunAxfHandler ( IN EFI_SHELL_PROTOCOL *Shell ) { - LIST_ENTRY *ParamPackage; - EFI_STATUS Status; - SHELL_STATUS ShellStatus; - SHELL_FILE_HANDLE FileHandle; - ELF_ENTRYPOINT StartElf; - CONST CHAR16 *FileName; - EFI_FILE_INFO *Info; - UINTN FileSize; - VOID *FileData; - VOID *Entrypoint; - LIST_ENTRY LoadList; - LIST_ENTRY *Node; - LIST_ENTRY *NextNode; - RUNAXF_LOAD_LIST *LoadNode; - CHAR16 *TmpFileName; - CHAR16 *TmpChar16; - + LIST_ENTRY *ParamPackage; + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + SHELL_FILE_HANDLE FileHandle; + ELF_ENTRYPOINT StartElf; + CONST CHAR16 *FileName; + EFI_FILE_INFO *Info; + UINTN FileSize; + VOID *FileData; + VOID *Entrypoint; + LIST_ENTRY LoadList; + LIST_ENTRY *Node; + LIST_ENTRY *NextNode; + RUNAXF_LOAD_LIST *LoadNode; + CHAR16 *TmpFileName; + CHAR16 *TmpChar16; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; ShellStatus = SHELL_SUCCESS; FileHandle = NULL; @@ -291,6 +278,9 @@ ShellDynCmdRunAxfHandler ( } } + WriteBackDataCacheRange (FileData, FileSize); + InvalidateInstructionCacheRange (FileData, FileSize); + // Program load list created. // Shutdown UEFI, copy and jump to code. if (!IsListEmpty (&LoadList) && !EFI_ERROR (Status)) { @@ -315,14 +305,17 @@ ShellDynCmdRunAxfHandler ( Node = GetNextNode (&LoadList, Node); } - // - // Switch off interrupts, caches, mmu, etc - // - Status = PreparePlatformHardware (); + Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage); ASSERT_EFI_ERROR (Status); - StartElf = (ELF_ENTRYPOINT)Entrypoint; - StartElf (0,0,0,0); + // + // Ensure that the currently running image is clean to the PoC so we can + // safely keep executing it with the MMU and caches off + // + WriteBackDataCacheRange (LoadedImage->ImageBase, LoadedImage->ImageSize); + + RunAxfPivot (StartElf, 0, 0, 0, 0); // We should never get here.. But if we do, spin.. ASSERT (FALSE); -- 2.17.1