From patchwork Thu May 14 12:38:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Walle X-Patchwork-Id: 245817 List-Id: U-Boot discussion From: michael at walle.cc (Michael Walle) Date: Thu, 14 May 2020 14:38:28 +0200 Subject: [PATCH 1/4] efi_loader: aarch64: align runtime section to 64kb In-Reply-To: <20200514123831.30157-1-michael@walle.cc> References: <20200514123831.30157-1-michael@walle.cc> Message-ID: <20200514123831.30157-2-michael@walle.cc> 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. Align the actual runtime code to 64kb instead. Fixes: 7a82c3051c8f ("efi_loader: Align runtime section to 64kb") Signed-off-by: Michael Walle --- 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 needs to come before *(.text*) + */ + + . = ALIGN(65536); .efi_runtime : { __efi_runtime_start = .; *(.text.efi_runtime*) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 97d90f069a..fd79178da9 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -12,7 +12,6 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -734,7 +733,6 @@ __weak void efi_add_known_memory(void) static void add_u_boot_and_runtime(void) { unsigned long runtime_start, runtime_end, runtime_pages; - unsigned long runtime_mask = EFI_PAGE_MASK; unsigned long uboot_start, uboot_pages; unsigned long uboot_stack_size = 16 * 1024 * 1024; @@ -745,22 +743,13 @@ static void add_u_boot_and_runtime(void) uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false); -#if defined(__aarch64__) - /* - * Runtime Services must be 64KiB aligned according to the - * "AArch64 Platforms" section in the UEFI spec (2.7+). - */ - - runtime_mask = SZ_64K - 1; -#endif - /* * Add Runtime Services. We mark surrounding boottime code as runtime as * well to fulfill the runtime alignment constraints but avoid padding. */ - runtime_start = (ulong)&__efi_runtime_start & ~runtime_mask; + runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK; runtime_end = (ulong)&__efi_runtime_stop; - runtime_end = (runtime_end + runtime_mask) & ~runtime_mask; + runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; efi_add_memory_map(runtime_start, runtime_pages, EFI_RUNTIME_SERVICES_CODE, false); From patchwork Thu May 14 12:38:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Walle X-Patchwork-Id: 245816 List-Id: U-Boot discussion From: michael at walle.cc (Michael Walle) Date: Thu, 14 May 2020 14:38:29 +0200 Subject: [PATCH 2/4] efi_loader: check alignment in efi_add_memory_map() In-Reply-To: <20200514123831.30157-1-michael@walle.cc> References: <20200514123831.30157-1-michael@walle.cc> Message-ID: <20200514123831.30157-3-michael@walle.cc> The first argument has to be aligned with EFI_PAGE_SIZE. This alignment is already checked for external callers but it is not checked for internal callers. Unfortunately, most of the time the return value is not checked, so scream loud and clear. Signed-off-by: Michael Walle --- lib/efi_loader/efi_memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index fd79178da9..b56e19cb30 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -248,6 +248,9 @@ efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__, start, pages, memory_type, overlap_only_ram ? "yes" : "no"); + if (start & EFI_PAGE_MASK) + panic("%s: start not aligned\n", __func__); + if (memory_type >= EFI_MAX_MEMORY_TYPE) return EFI_INVALID_PARAMETER; From patchwork Thu May 14 12:38:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Walle X-Patchwork-Id: 245815 List-Id: U-Boot discussion From: michael at walle.cc (Michael Walle) Date: Thu, 14 May 2020 14:38:30 +0200 Subject: [PATCH 3/4] fsl-layerscape: align first parameter of efi_add_memory_map() In-Reply-To: <20200514123831.30157-1-michael@walle.cc> References: <20200514123831.30157-1-michael@walle.cc> Message-ID: <20200514123831.30157-4-michael@walle.cc> The start parameter must be aligned to EFI_PAGE_SIZE. Fixes: 5a37a2f0140c ("armv8: ls2080a: Declare spin tables as reserved for efi loader") Signed-off-by: Michael Walle --- arch/arm/cpu/armv8/fsl-layerscape/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c index 3bbad827cb..fc65ad6c1e 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c @@ -146,7 +146,7 @@ remove_psci_node: fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, *boot_code_size); #if CONFIG_IS_ENABLED(EFI_LOADER) - efi_add_memory_map((uintptr_t)&secondary_boot_code, + efi_add_memory_map(ALIGN_DOWN((uintptr_t)&secondary_boot_code, EFI_PAGE_SIZE), ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT, EFI_RESERVED_MEMORY_TYPE, false); #endif From patchwork Thu May 14 12:38:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Walle X-Patchwork-Id: 245818 List-Id: U-Boot discussion From: michael at walle.cc (Michael Walle) Date: Thu, 14 May 2020 14:38:31 +0200 Subject: [PATCH 4/4] efi_loader: call smp_kick_all_cpus() In-Reply-To: <20200514123831.30157-1-michael@walle.cc> References: <20200514123831.30157-1-michael@walle.cc> Message-ID: <20200514123831.30157-5-michael@walle.cc> On some architectures, specifically the layerscape, the secondary cores wait for an interrupt before entering the spin-tables. This applies only to boards which doesn't have PSCI provided by TF-a and u-boot does the secondary cores handling. bootm/booti already call that function for ARM architecture; also add it to bootelf before switching to EL2. Additionally, provide a weak noop function so we don't have to have "#ifdef CONFIG_ARM64" guards. Signed-off-by: Michael Walle --- common/bootm.c | 9 +++++++++ lib/efi_loader/efi_setup.c | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/common/bootm.c b/common/bootm.c index db4362a643..65adf29329 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -816,6 +816,15 @@ void __weak switch_to_non_secure_mode(void) { } +/** + * smp_kick_all_cpus() - kick all CPUs + * + * This routine is overridden by architectures requiring this feature. + */ +void __weak smp_kick_all_cpus(void) +{ +} + #else /* USE_HOSTCC */ #if defined(CONFIG_FIT_SIGNATURE) diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 26a7423203..7e5364adc5 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -132,6 +132,12 @@ efi_status_t efi_init_obj_list(void) /* Allow unaligned memory access */ allow_unaligned(); + /* + * Some architectures need to kick secondary cores to enter their + * spin table. + */ + smp_kick_all_cpus(); + /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */ switch_to_non_secure_mode();