From patchwork Mon Nov 12 09:46:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Fan X-Patchwork-Id: 10678377 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0E14F14BA for ; Mon, 12 Nov 2018 09:48:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E737B29699 for ; Mon, 12 Nov 2018 09:48:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DA9C7297C6; Mon, 12 Nov 2018 09:48:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3745429699 for ; Mon, 12 Nov 2018 09:48:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726190AbeKLTk1 (ORCPT ); Mon, 12 Nov 2018 14:40:27 -0500 Received: from mail.cn.fujitsu.com ([183.91.158.132]:63830 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725873AbeKLTk1 (ORCPT ); Mon, 12 Nov 2018 14:40:27 -0500 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="47945961" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 12 Nov 2018 17:47:55 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id 153F74B6ED4F; Mon, 12 Nov 2018 17:47:52 +0800 (CST) Received: from localhost.local (10.167.225.56) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 12 Nov 2018 17:47:57 +0800 From: Chao Fan To: , , , , , , , , , , CC: , , Subject: [PATCH v11 1/5] x86/boot: Add efi_get_rsdp_addr() to dig out RSDP from EFI table Date: Mon, 12 Nov 2018 17:46:41 +0800 Message-ID: <20181112094645.4879-2-fanc.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> References: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.225.56] X-yoursite-MailScanner-ID: 153F74B6ED4F.ADFFB X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: fanc.fnst@cn.fujitsu.com Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In order to parse SRAT table and get memory information, RSDP pointer should be found. In kernel, there are three methods to get RSDP: EFI condition, BIOS condition and KEXEC condition. The first works for EFI condition. Imitate ACPI code and EFI code to dig RSDP pointer from EFI tables. Process: boot_param->systab->efi_config_table->RSDP. Based on efi_init(), efi_config_init(), efi_config_parse_tables(). Signed-off-by: Chao Fan --- arch/x86/boot/compressed/acpitb.c | 96 +++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 arch/x86/boot/compressed/acpitb.c diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c new file mode 100644 index 000000000000..56b54b0e0889 --- /dev/null +++ b/arch/x86/boot/compressed/acpitb.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +#define BOOT_CTYPE_H +#include "misc.h" +#include "error.h" + +#include +#include +#include +#include + +/* Search EFI table for RSDP table. */ +static void efi_get_rsdp_addr(acpi_physical_address *rsdp_addr) +{ +#ifdef CONFIG_EFI + efi_system_table_t *systab; + bool efi_64 = false; + void *config_tables; + struct efi_info *e; + char *sig; + int size; + int i; + + e = &boot_params->efi_info; + sig = (char *)&e->efi_loader_signature; + + if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) + efi_64 = true; + else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4)) + efi_64 = false; + else { + debug_putstr("Wrong EFI loader signature.\n"); + return; + } + + /* Get systab from boot params. Based on efi_init(). */ +#ifdef CONFIG_X86_64 + systab = (efi_system_table_t *)( + e->efi_systab | ((__u64)e->efi_systab_hi<<32)); +#else + if (e->efi_systab_hi || e->efi_memmap_hi) { + debug_putstr("Table located above 4GB. EFI should be disabled.\n"); + return; + } + systab = (efi_system_table_t *)e->efi_systab; +#endif + + if (!systab) + return; + + /* + * Get EFI tables from systab. Based on efi_config_init() and + * efi_config_parse_tables(). Only dig out the config_table. + */ + size = efi_64 ? sizeof(efi_config_table_64_t) : + sizeof(efi_config_table_32_t); + + for (i = 0; i < systab->nr_tables; i++) { + efi_guid_t guid; + unsigned long table; + + config_tables = (void *)(systab->tables + size * i); + if (efi_64) { + efi_config_table_64_t *tmp_table; + + tmp_table = (efi_config_table_64_t *)config_tables; + guid = tmp_table->guid; + table = tmp_table->table; +#ifndef CONFIG_64BIT + if (table >> 32) { + debug_putstr("Table located above 4G. EFI should be disabled.\n"); + return; + } +#endif + } else { + efi_config_table_32_t *tmp_table; + + tmp_table = (efi_config_table_32_t *)config_tables; + guid = tmp_table->guid; + table = tmp_table->table; + } + + /* + * Get RSDP from EFI tables. + * If ACPI20 table found, use it. + * If ACPI20 table not found, but ACPI table found, + * use the ACPI table. + */ + if (!(efi_guidcmp(guid, ACPI_TABLE_GUID))) { + *rsdp_addr = (acpi_physical_address)table; + } else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID))) { + *rsdp_addr = (acpi_physical_address)table; + return; + } + } +#endif +} From patchwork Mon Nov 12 09:46:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Fan X-Patchwork-Id: 10678389 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B524214DB for ; Mon, 12 Nov 2018 09:48:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A4E7629CFE for ; Mon, 12 Nov 2018 09:48:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 985D729D4B; Mon, 12 Nov 2018 09:48:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2336329CFE for ; Mon, 12 Nov 2018 09:48:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727297AbeKLTka (ORCPT ); Mon, 12 Nov 2018 14:40:30 -0500 Received: from mail.cn.fujitsu.com ([183.91.158.132]:28580 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726161AbeKLTk2 (ORCPT ); Mon, 12 Nov 2018 14:40:28 -0500 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="47945959" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 12 Nov 2018 17:47:55 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id 057D14B71EA6; Mon, 12 Nov 2018 17:47:54 +0800 (CST) Received: from localhost.local (10.167.225.56) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 12 Nov 2018 17:47:59 +0800 From: Chao Fan To: , , , , , , , , , , CC: , , Subject: [PATCH v11 2/5] x86/boot: Add bios_get_rsdp_addr() to search RSDP in memory Date: Mon, 12 Nov 2018 17:46:42 +0800 Message-ID: <20181112094645.4879-3-fanc.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> References: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.225.56] X-yoursite-MailScanner-ID: 057D14B71EA6.AB53B X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: fanc.fnst@cn.fujitsu.com Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Imitate ACPI code to search RSDP pointer from memory. Walk memory and check the signature until get the RSDP signature. Based on acpi_tb_scan_memory_for_rsdp() and acpi_find_root_pointer(). If didn't get RSDP from EFI table, will run this function. Used for later patch to dig out SRAT table and get the memory information. And figure out the immovable memory regions to avoid KASLR extracts kernel on movable memory, slove the conflict between KASLR and movable_node feature. Signed-off-by: Chao Fan --- arch/x86/boot/compressed/acpitb.c | 106 ++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c index 56b54b0e0889..50fa65cf824d 100644 --- a/arch/x86/boot/compressed/acpitb.c +++ b/arch/x86/boot/compressed/acpitb.c @@ -94,3 +94,109 @@ static void efi_get_rsdp_addr(acpi_physical_address *rsdp_addr) } #endif } + +static u8 compute_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) + sum = (u8)(sum + *(buffer++)); + + return sum; +} + +/* + * Used to search a block of memory for the RSDP signature. + * Return Pointer to the RSDP if found, otherwise NULL. + * Based on acpi_tb_scan_memory_for_rsdp(). + */ +static u8 *scan_mem_for_rsdp(u8 *start, u32 length) +{ + struct acpi_table_rsdp *rsdp; + u8 *end; + u8 *rover; + + end = start + length; + + /* Search from given start address for the requested length */ + for (rover = start; rover < end; rover += ACPI_RSDP_SCAN_STEP) { + /* + * The RSDP signature and checksum must both be correct + * Note: Sometimes there exists more than one RSDP in memory; + * the valid RSDP has a valid checksum, all others have an + * invalid checksum. + */ + rsdp = (struct acpi_table_rsdp *)rover; + + /* Nope, BAD Signature */ + if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) + continue; + + /* Check the standard checksum */ + if (compute_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH)) + continue; + + /* Check extended checksum if table version >= 2 */ + if ((rsdp->revision >= 2) && + (compute_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH))) + continue; + + /* Sig and checksum valid, we have found a real RSDP */ + return rover; + } + return NULL; +} + +/* + * Used to search RSDP physical address. + * Based on acpi_find_root_pointer(). Since only use physical address + * in this period, so there is no need to do the memory map jobs. + */ +static void bios_get_rsdp_addr(acpi_physical_address *rsdp_addr) +{ + struct acpi_table_rsdp *rsdp; + u8 *table_ptr; + u8 *mem_rover; + u32 address; + + /* + * Get the location of the Extended BIOS Data Area (EBDA) + * Since we use physical address directely, so + * acpi_os_map_memory() and acpi_os_unmap_memory() are + * not needed here. + */ + table_ptr = (u8 *)ACPI_EBDA_PTR_LOCATION; + *(u32 *)(void *)&address = *(u16 *)(void *)table_ptr; + address <<= 4; + table_ptr = (u8 *)address; + + /* + * Search EBDA paragraphs (EBDA is required to be a minimum of + * 1K length) + */ + if (address > 0x400) { + mem_rover = scan_mem_for_rsdp(table_ptr, ACPI_EBDA_WINDOW_SIZE); + + if (mem_rover) { + address += (u32)ACPI_PTR_DIFF(mem_rover, table_ptr); + *rsdp_addr = (acpi_physical_address)address; + return; + } + } + + table_ptr = (u8 *)ACPI_HI_RSDP_WINDOW_BASE; + mem_rover = scan_mem_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); + + /* + * Search upper memory: 16-byte boundaries in E0000h-FFFFFh + * Since we use physical address directely, so + * acpi_os_map_memory() and acpi_os_unmap_memory() are + * not needed here. + */ + if (mem_rover) { + address = (u32)(ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); + *rsdp_addr = (acpi_physical_address)address; + } +} From patchwork Mon Nov 12 09:46:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Fan X-Patchwork-Id: 10678385 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F367914BA for ; Mon, 12 Nov 2018 09:48:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DAAF9298CD for ; Mon, 12 Nov 2018 09:48:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C78C829703; Mon, 12 Nov 2018 09:48:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 56C6B28E72 for ; Mon, 12 Nov 2018 09:48:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728619AbeKLTkw (ORCPT ); Mon, 12 Nov 2018 14:40:52 -0500 Received: from mail.cn.fujitsu.com ([183.91.158.132]:26720 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1725873AbeKLTka (ORCPT ); Mon, 12 Nov 2018 14:40:30 -0500 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="47945968" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 12 Nov 2018 17:48:01 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id C14E24B7348C; Mon, 12 Nov 2018 17:47:55 +0800 (CST) Received: from localhost.local (10.167.225.56) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 12 Nov 2018 17:48:01 +0800 From: Chao Fan To: , , , , , , , , , , CC: , , Subject: [PATCH v11 3/5] x86/boot: Add get_acpi_rsdp() to parse RSDP in cmdlien from kexec Date: Mon, 12 Nov 2018 17:46:43 +0800 Message-ID: <20181112094645.4879-4-fanc.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> References: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.225.56] X-yoursite-MailScanner-ID: C14E24B7348C.A81AF X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: fanc.fnst@cn.fujitsu.com Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Imitate setup_acpi_rsdp() for the early_param of 'acpi_rsdp'. KEXEC writes the RSDP pointer to cmdline for EFI booting. So if 'acpi_rsdp' found in cmdline, use it directely. Since function kstrtoull() is needed, include it in arch/x86/boot/string.h. To solve the definition conflict problem, set BOOT_STRING tag to expose only kstrtoull() and functions used by it. Other functions in lib/kstrtox.c will be covered. Signed-off-by: Chao Fan --- arch/x86/boot/compressed/acpitb.c | 26 ++++++++++++++++++++++++++ arch/x86/boot/string.h | 4 ++++ lib/kstrtox.c | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c index 50fa65cf824d..5cfb4efa5a19 100644 --- a/arch/x86/boot/compressed/acpitb.c +++ b/arch/x86/boot/compressed/acpitb.c @@ -8,6 +8,12 @@ #include #include +#define STATIC +#include + +#define BOOT_STRING +#include "../string.h" + /* Search EFI table for RSDP table. */ static void efi_get_rsdp_addr(acpi_physical_address *rsdp_addr) { @@ -200,3 +206,23 @@ static void bios_get_rsdp_addr(acpi_physical_address *rsdp_addr) *rsdp_addr = (acpi_physical_address)address; } } + +static void get_acpi_rsdp(acpi_physical_address *rsdp_addr) +{ +#ifdef CONFIG_KEXEC + unsigned long long res; + int len = 0; + char *val; + + val = malloc(19); + len = cmdline_find_option("acpi_rsdp", val, 19); + + if (len == -1) + return; + + if (len > 0) { + val[len] = 0; + *rsdp_addr = (acpi_physical_address)kstrtoull(val, 16, &res); + } +#endif +} diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h index 3d78e27077f4..0ff3edb888e4 100644 --- a/arch/x86/boot/string.h +++ b/arch/x86/boot/string.h @@ -30,3 +30,7 @@ extern unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); #endif /* BOOT_STRING_H */ + +#ifdef BOOT_STRING +#include "../../../lib/kstrtox.c" +#endif diff --git a/lib/kstrtox.c b/lib/kstrtox.c index 1006bf70bf74..3804db9eed56 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -126,6 +126,8 @@ int kstrtoull(const char *s, unsigned int base, unsigned long long *res) } EXPORT_SYMBOL(kstrtoull); +#ifndef BOOT_STRING + /** * kstrtoll - convert a string to a long long * @s: The start of the string. The string must be null-terminated, and may also @@ -408,3 +410,5 @@ kstrto_from_user(kstrtou16_from_user, kstrtou16, u16); kstrto_from_user(kstrtos16_from_user, kstrtos16, s16); kstrto_from_user(kstrtou8_from_user, kstrtou8, u8); kstrto_from_user(kstrtos8_from_user, kstrtos8, s8); + +#endif From patchwork Mon Nov 12 09:46:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Fan X-Patchwork-Id: 10678381 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3F03414BD for ; Mon, 12 Nov 2018 09:48:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2CB0329699 for ; Mon, 12 Nov 2018 09:48:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 20B54297C8; Mon, 12 Nov 2018 09:48:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7C509296FB for ; Mon, 12 Nov 2018 09:48:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727133AbeKLTkj (ORCPT ); Mon, 12 Nov 2018 14:40:39 -0500 Received: from mail.cn.fujitsu.com ([183.91.158.132]:63830 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727156AbeKLTka (ORCPT ); Mon, 12 Nov 2018 14:40:30 -0500 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="47945969" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 12 Nov 2018 17:48:01 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id 217794B73496; Mon, 12 Nov 2018 17:47:58 +0800 (CST) Received: from localhost.local (10.167.225.56) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 12 Nov 2018 17:48:03 +0800 From: Chao Fan To: , , , , , , , , , , CC: , , Subject: [PATCH v11 4/5] x86/boot: Dig out SRAT table from RSDP and find immovable memory Date: Mon, 12 Nov 2018 17:46:44 +0800 Message-ID: <20181112094645.4879-5-fanc.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> References: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.225.56] X-yoursite-MailScanner-ID: 217794B73496.A4FCC X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: fanc.fnst@cn.fujitsu.com Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP To avoid KASLR extracting kernel on movable memory, slove the conflict between KASLR and movable_node feature, dig the SRAT tables from RSDP pointer. Walk the SRAT tables and store the immovable memory regions in immovable_mem[]. There are three methods to get RSDP pointer: KEXEC condition, EFI confition, BIOS condition. If KEXEC add 'acpi_rsdp' to cmdline, use it. Otherwise, parse EFI table for RSDP. Then, search memory for RSDP. Imitate from ACPI code, based on acpi_os_get_root_pointer(). Process: RSDP->RSDT/XSDT->ACPI root table->SRAT. Signed-off-by: Chao Fan --- arch/x86/boot/compressed/Makefile | 4 + arch/x86/boot/compressed/acpitb.c | 139 ++++++++++++++++++++++++++++++ arch/x86/boot/compressed/kaslr.c | 4 - arch/x86/boot/compressed/misc.h | 15 ++++ 4 files changed, 158 insertions(+), 4 deletions(-) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 466f66c8a7f8..b51f7629b8ef 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -84,6 +84,10 @@ ifdef CONFIG_X86_64 vmlinux-objs-y += $(obj)/pgtable_64.o endif +#if (defined CONFIG_MEMORY_HOTREMOVE) && (defined CONFIG_RANDOMIZE_BASE) +vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/acpitb.o +#endif + $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \ diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c index 5cfb4efa5a19..161f21a7fb3b 100644 --- a/arch/x86/boot/compressed/acpitb.c +++ b/arch/x86/boot/compressed/acpitb.c @@ -14,6 +14,11 @@ #define BOOT_STRING #include "../string.h" +#ifdef CONFIG_MEMORY_HOTREMOVE +/* Store the immovable memory regions */ +struct mem_vector immovable_mem[MAX_NUMNODES*2]; +#endif + /* Search EFI table for RSDP table. */ static void efi_get_rsdp_addr(acpi_physical_address *rsdp_addr) { @@ -226,3 +231,137 @@ static void get_acpi_rsdp(acpi_physical_address *rsdp_addr) } #endif } + +/* + * Used to dig RSDP table from EFI table or BIOS. + * If RSDP table found in EFI table, use it. Or search BIOS. + * Based on acpi_os_get_root_pointer(). + */ +static acpi_physical_address get_rsdp_addr(void) +{ + acpi_physical_address pa = 0; + + get_acpi_rsdp(&pa); + + if (!pa) + efi_get_rsdp_addr(&pa); + + if (!pa) + bios_get_rsdp_addr(&pa); + + return pa; +} + +static struct acpi_table_header *get_acpi_srat_table(void) +{ + acpi_physical_address acpi_table; + acpi_physical_address root_table; + struct acpi_table_header *header; + struct acpi_table_rsdp *rsdp; + bool acpi_use_rsdt = false; + char *signature; + char arg[10]; + u8 *entry; + u32 count; + u32 size; + int i, j; + int ret; + u32 len; + + rsdp = (struct acpi_table_rsdp *)get_rsdp_addr(); + if (!rsdp) + return NULL; + + ret = cmdline_find_option("acpi", arg, sizeof(arg)); + if (ret == 4 && !strncmp(arg, "rsdt", 4)) + acpi_use_rsdt = true; + + /* Get RSDT or XSDT from RSDP. */ + if (!acpi_use_rsdt && + rsdp->xsdt_physical_address && rsdp->revision > 1) { + root_table = rsdp->xsdt_physical_address; + size = ACPI_XSDT_ENTRY_SIZE; + } else { + root_table = rsdp->rsdt_physical_address; + size = ACPI_RSDT_ENTRY_SIZE; + } + + /* Get ACPI root table from RSDT or XSDT.*/ + header = (struct acpi_table_header *)root_table; + len = header->length; + count = (u32)((len - sizeof(struct acpi_table_header)) / size); + entry = ACPI_ADD_PTR(u8, header, sizeof(struct acpi_table_header)); + + for (i = 0; i < count; i++) { + u64 address64; + + if (size == ACPI_RSDT_ENTRY_SIZE) + acpi_table = ((acpi_physical_address) + (*ACPI_CAST_PTR(u32, entry))); + else { + *(u64 *)(void *)&address64 = *(u64 *)(void *)entry; + acpi_table = (acpi_physical_address) address64; + } + + if (acpi_table) { + header = (struct acpi_table_header *)acpi_table; + signature = header->signature; + + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_SRAT)) + return header; + } + entry += size; + } + return NULL; +} + +/* + * According to ACPI table, filter the immvoable memory regions + * and store them in immovable_mem[]. + */ +void get_immovable_mem(void) +{ + struct acpi_table_header *table_header; + struct acpi_subtable_header *table; + struct acpi_srat_mem_affinity *ma; + unsigned long table_end; + char arg[10]; + int i = 0; + int ret; + + ret = cmdline_find_option("acpi", arg, sizeof(arg)); + if (ret == 3 && !strncmp(arg, "off", 3)) + return; + + if (!cmdline_find_option_bool("movable_node")) + return; + + table_header = get_acpi_srat_table(); + if (!table_header) + return; + + table_end = (unsigned long)table_header + table_header->length; + + table = (struct acpi_subtable_header *) + ((unsigned long)table_header + sizeof(struct acpi_table_srat)); + + while (((unsigned long)table) + + sizeof(struct acpi_subtable_header) < table_end) { + if (table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) { + ma = (struct acpi_srat_mem_affinity *)table; + if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) { + immovable_mem[i].start = ma->base_address; + immovable_mem[i].size = ma->length; + i++; + } + + if (i >= MAX_NUMNODES*2) { + debug_putstr("Too many immovable memory regions, aborted.\n"); + break; + } + } + table = (struct acpi_subtable_header *) + ((unsigned long)table + table->length); + } + num_immovable_mem = i; +} diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 9ed9709d9947..b251572e77af 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -87,10 +87,6 @@ static unsigned long get_boot_seed(void) #define KASLR_COMPRESSED_BOOT #include "../../lib/kaslr.c" -struct mem_vector { - unsigned long long start; - unsigned long long size; -}; /* Only supporting at most 4 unusable memmap regions with kaslr */ #define MAX_MEMMAP_REGIONS 4 diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index a1d5918765f3..4a3645fda0ed 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -77,6 +77,11 @@ void choose_random_location(unsigned long input, unsigned long *output, unsigned long output_size, unsigned long *virt_addr); +struct mem_vector { + unsigned long long start; + unsigned long long size; +}; + /* cpuflags.c */ bool has_cpuflag(int flag); #else @@ -116,3 +121,13 @@ static inline void console_init(void) void set_sev_encryption_mask(void); #endif + +/* acpitb.c */ +#ifdef CONFIG_RANDOMIZE_BASE +int num_immovable_mem; +#ifdef CONFIG_MEMORY_HOTREMOVE +/* Store the amount of immovable memory regions */ +#define ACPI_MAX_TABLES 128 +void get_immovable_mem(void); +#endif +#endif From patchwork Mon Nov 12 09:46:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Fan X-Patchwork-Id: 10678379 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6EE2C14BA for ; Mon, 12 Nov 2018 09:48:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C08D296FB for ; Mon, 12 Nov 2018 09:48:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4EFD8297C6; Mon, 12 Nov 2018 09:48:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C766129699 for ; Mon, 12 Nov 2018 09:48:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726161AbeKLTkd (ORCPT ); Mon, 12 Nov 2018 14:40:33 -0500 Received: from mail.cn.fujitsu.com ([183.91.158.132]:28580 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727133AbeKLTka (ORCPT ); Mon, 12 Nov 2018 14:40:30 -0500 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="47945970" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 12 Nov 2018 17:48:01 +0800 Received: from G08CNEXCHPEKD01.g08.fujitsu.local (unknown [10.167.33.80]) by cn.fujitsu.com (Postfix) with ESMTP id 5062B4B73497; Mon, 12 Nov 2018 17:48:00 +0800 (CST) Received: from localhost.local (10.167.225.56) by G08CNEXCHPEKD01.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 12 Nov 2018 17:48:05 +0800 From: Chao Fan To: , , , , , , , , , , CC: , , Subject: [PATCH v11 5/5] x86/boot/KASLR: Walk srat tables to filter immovable memory Date: Mon, 12 Nov 2018 17:46:45 +0800 Message-ID: <20181112094645.4879-6-fanc.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> References: <20181112094645.4879-1-fanc.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.225.56] X-yoursite-MailScanner-ID: 5062B4B73497.A5C8A X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: fanc.fnst@cn.fujitsu.com Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP KASLR may randomly chooses some positions which are located in movable memory regions. This will break memory hotplug feature and make the movable memory chosen by KASLR can't be removed. The solution is limite KASLR to choose memory regions in immovable node according to SRAT tables. If CONFIG_MEMORY_HOTREMOVE enabled, walk through the SRAT memory tables and store those immovable memory regions so that KASLR can get where to choose for randomization. If the amount of immovable memory regions is not zero, which means the immovable memory regions existing. Calculate the intersection between memory regions from e820/efi memory table and immovable memory regions. Signed-off-by: Chao Fan --- arch/x86/boot/compressed/kaslr.c | 77 +++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index b251572e77af..174d2114045e 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -97,6 +97,11 @@ static bool memmap_too_large; /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */ static unsigned long long mem_limit = ULLONG_MAX; +#ifdef CONFIG_MEMORY_HOTREMOVE +/* Store the immovable memory regions */ +extern struct mem_vector immovable_mem[MAX_NUMNODES*2]; +#endif + enum mem_avoid_index { MEM_AVOID_ZO_RANGE = 0, @@ -413,6 +418,11 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, /* Mark the memmap regions we need to avoid */ handle_mem_options(); +#ifdef CONFIG_MEMORY_HOTREMOVE + /* Mark the immovable regions we need to choose */ + get_immovable_mem(); +#endif + #ifdef CONFIG_X86_VERBOSE_BOOTUP /* Make sure video RAM can be used. */ add_identity_map(0, PMD_SIZE); @@ -568,9 +578,9 @@ static unsigned long slots_fetch_random(void) return 0; } -static void process_mem_region(struct mem_vector *entry, - unsigned long minimum, - unsigned long image_size) +static void slots_count(struct mem_vector *entry, + unsigned long minimum, + unsigned long image_size) { struct mem_vector region, overlap; unsigned long start_orig, end; @@ -646,6 +656,57 @@ static void process_mem_region(struct mem_vector *entry, } } +static bool process_mem_region(struct mem_vector *region, + unsigned long long minimum, + unsigned long long image_size) +{ + int i; + /* + * If no immovable memory found, or MEMORY_HOTREMOVE disabled, + * walk all the regions, so use region directely. + */ + if (num_immovable_mem == 0) { + slots_count(region, minimum, image_size); + + if (slot_area_index == MAX_SLOT_AREA) { + debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n"); + return 1; + } + return 0; + } + +#ifdef CONFIG_MEMORY_HOTREMOVE + /* + * If immovable memory found, filter the intersection between + * immovable memory and region to slots_count. + * Otherwise, go on old code. + */ + for (i = 0; i < num_immovable_mem; i++) { + struct mem_vector entry; + unsigned long long start, end, entry_end, region_end; + + if (!mem_overlaps(region, &immovable_mem[i])) + continue; + + start = immovable_mem[i].start; + end = start + immovable_mem[i].size; + region_end = region->start + region->size; + + entry.start = clamp(region->start, start, end); + entry_end = clamp(region_end, start, end); + entry.size = entry_end - entry.start; + + slots_count(&entry, minimum, image_size); + + if (slot_area_index == MAX_SLOT_AREA) { + debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n"); + return 1; + } + } + return 0; +#endif +} + #ifdef CONFIG_EFI /* * Returns true if mirror region found (and must have been processed @@ -711,11 +772,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size) region.start = md->phys_addr; region.size = md->num_pages << EFI_PAGE_SHIFT; - process_mem_region(®ion, minimum, image_size); - if (slot_area_index == MAX_SLOT_AREA) { - debug_putstr("Aborted EFI scan (slot_areas full)!\n"); + if (process_mem_region(®ion, minimum, image_size)) break; - } } return true; } @@ -742,11 +800,8 @@ static void process_e820_entries(unsigned long minimum, continue; region.start = entry->addr; region.size = entry->size; - process_mem_region(®ion, minimum, image_size); - if (slot_area_index == MAX_SLOT_AREA) { - debug_putstr("Aborted e820 scan (slot_areas full)!\n"); + if (process_mem_region(®ion, minimum, image_size)) break; - } } }