From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on sa.local.altlinux.org X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.1 X-Yandex-Fwd: 2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1653064201; bh=suNp8+KavAXNXNCsgoApghN+0ZwsHQWjyEsWqGh/F6o=; h=Reply-To:In-Reply-To:References:Date:Subject:Cc:To:From: Message-Id; b=pXLn9LerwsGjB38E4GuRfapInak/l6U2r5U6Qh4XFgFtd+yMBZnM1IgJeEqGETWNi kbOMhrAlbjtCWR5MCgvXuEb69aFlZECIv102umTqqiDlp1ZOzUYC/EIrxQdBQ42Iok OKbuvoBTwycZoa6XHq2sXNurwzcQ7IeC85rUPXyg= Authentication-Results: sas2-23d4707a926d.qloud-c.yandex.net; dkim=pass header.i=@yandex.ru From: asheplyakov@yandex.ru To: devel@lists.altlinux.org Date: Fri, 20 May 2022 20:28:36 +0400 Message-Id: <20220520162849.1554351-23-asheplyakov@yandex.ru> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220520162849.1554351-1-asheplyakov@yandex.ru> References: <20220520162849.1554351-1-asheplyakov@yandex.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Cc: Vitaly Chikunov , Igor Chudov , Alexey Sheplyakov , Evgeny Sinelnikov Subject: [devel] [PATCH 22/35] arm64-stub: fixed secondary cores boot on Baikal-M SoC X-BeenThere: devel@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: ALT Linux Team development discussions List-Id: ALT Linux Team development discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 May 2022 16:30:17 -0000 Archived-At: List-Archive: List-Post: From: Alexey Sheplyakov Old versions of Baikal-M firmware (ARM-TF) deny execution attempts outside of the (physical) address ranges [0x80000000, 0x8FFFFFFF] and [0xA0000000, 0xBFFFFFFF] Thus PSCI calls to boot secondary cores fail unless the kernel image resides in one of these address ranges. However UEFI PE/COFF loader puts the kernel image into the forbidden range. Since the alignment is good enough EFI stub does not try to relocate the kernel. As a result secondary CPUs fail to boot. Relocation to a random address is not going to work either. Therefore automatically disable kaslr on "known bad" systems (for now only Baikal-M) and forcibly relocate the kernel to a low(er) address. This patch is necessary only for old firmware (pre SDK-M 5.1) and prevents kalsr from working on Baikal-M systems. X-DONTUPSTREAM X-legacy X-feature-Baikal-M --- drivers/firmware/efi/libstub/arm64-stub.c | 62 ++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index 9cc556013d08..5486a223a59f 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "efistub.h" @@ -34,6 +35,31 @@ efi_status_t check_platform_features(void) return EFI_SUCCESS; } +static const char* machines_need_low_alloc[] = { + "baikal,baikal-m", +}; + +static bool need_low_alloc(void) { + size_t i; + const void *fdt; + const char *match; + + fdt = get_efi_config_table(DEVICE_TREE_GUID); + if (!fdt) { + efi_info("failed to retrive FDT from EFI\n"); + return false; + } + + for (i = 0; i < ARRAY_SIZE(machines_need_low_alloc); i++) { + match = machines_need_low_alloc[i]; + if (fdt_node_check_compatible(fdt, 0, match) == 0) { + efi_info("machine %s: forcing kernel relocation to low address\n", match); + return true; + } + } + return false; +} + /* * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail * to provide space, and fail to zero it). Check for this condition by double @@ -79,6 +105,19 @@ static bool check_image_region(u64 base, u64 size) return ret; } +static inline efi_status_t efi_low_alloc(unsigned long size, unsigned long align, + unsigned long *addr) +{ + /* + * Don't allocate at 0x0. It will confuse code that + * checks pointers against NULL. Skip the first 8 + * bytes so we start at a nice even number. + */ + return efi_low_alloc_above(size, align, addr, 0x8); +} + + + efi_status_t handle_kernel_image(unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr, @@ -99,6 +138,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, */ u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN; + bool force_low_reloc = need_low_alloc(); + if (force_low_reloc) { + if (!efi_nokaslr) { + efi_info("booting on a broken firmware, KASLR will be disabled\n"); + efi_nokaslr = true; + } + } + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { if (!efi_nokaslr) { status = efi_get_random_bytes(sizeof(phys_seed), @@ -112,7 +159,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, efi_nokaslr = true; } } else { - efi_info("KASLR disabled on kernel command line\n"); + if (!force_low_reloc) + efi_info("KASLR disabled on kernel command line\n"); } } @@ -140,6 +188,15 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, status = EFI_OUT_OF_RESOURCES; } + if (force_low_reloc) { + status = efi_low_alloc(*reserve_size, + min_kimg_align, + reserve_addr); + if (status != EFI_SUCCESS) { + efi_err("Failed to relocate kernel, expect secondary CPUs boot failure\n"); + } + } + if (status != EFI_SUCCESS) { if (!check_image_region((u64)_text, kernel_memsize)) { efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n"); @@ -164,6 +221,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, } *image_addr = *reserve_addr; + if (efi_nokaslr) { + efi_info("relocating kernel to 0x%lx\n", *image_addr); + } memcpy((void *)*image_addr, _text, kernel_size); return EFI_SUCCESS; -- 2.32.0