linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory.
@ 2018-06-12  8:10 Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 1/4] x86/boot: Add acpitb.h to help parse acpi tables Chao Fan
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Chao Fan @ 2018-06-12  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, hpa, tglx, mingo, bhe, keescook, yasu.isimatu
  Cc: indou.takao, lcapitulino, caoj.fnst, douly.fnst, Chao Fan

***Background:
People reported that kaslr may randomly chooses some positions
which are located in movable memory regions. This will break memory
hotplug feature and make the memory can't be removed.

***Solutions:
There should be a method to limit kaslr to choosing immovable memory
regions, so there are 2 solutions:
1) Add a kernel parameter to specify the memory regions.
2) Get the information of memory hotremove, then kaslr will know the
   right regions.
But in method 2, information about memory hot remove is in ACPI
tables, which will be parsed after 'start_kernel', kaslr can't get
the information.
In method 1, users should know the regions address and specify in
kernel parameter.

In the earliest time, I tried to dig ACPI tabls to solve this problem.
But I didn't splite the code in 'compressed/' and ACPI code, so the patch
is hard to follow so refused by community.
Somebody suggest to add a kernel parameter to specify the
immovable memory so that limit kaslr in these regions. Then I make
a patchset. After several versions, Ingo gave a suggestion:
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1634024.html
Follow Ingo's suggestion, imitate the ACPI code to parse the acpi
tables, so that the kaslr can get necessary memory information in
ACPI tables.
Since I think ACPI code is independent part, so copy the codes
and functions to 'compressed/' directory, so that kaslr won't
influence the initialization of ACPI.

*** Issues need be discussed
There are several issues I am not quite sure, please help review and
give suggestions:

1) In PATCH 1, I copy the structures and functions from ACPI head file,
   so that ACPI head file will never been used here. I am not sure
   whether it's good to include ACPI head file or use the method in
   PATCH 1. If people think we can use ACPI head files directely, I
   will remove the PATCH 1.

***Test results:
 - I did a very simple test, and it can get the memory information in
   bios and efi KVM guest machine, and put it by early printk. But no
   more tests, so it's with RFC tag.

Any comments will be welcome.


Chao Fan (4):
  x86/boot: Add acpitb.h to help parse acpi tables
  x86/boot: Add acpitb.c to parse acpi tables
  x86/boot/KASLR: Walk srat tables to filter immovable memory
  x86/boot/KASLR: Limit kaslr to choosing the immovable memory

 arch/x86/boot/compressed/Makefile |   1 +
 arch/x86/boot/compressed/acpitb.c | 245 ++++++++++++++++++++++++++++++
 arch/x86/boot/compressed/acpitb.h | 175 +++++++++++++++++++++
 arch/x86/boot/compressed/kaslr.c  | 120 +++++++++++++--
 4 files changed, 530 insertions(+), 11 deletions(-)
 create mode 100644 arch/x86/boot/compressed/acpitb.c
 create mode 100644 arch/x86/boot/compressed/acpitb.h

-- 
2.17.0




^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC PATCH 1/4] x86/boot: Add acpitb.h to help parse acpi tables
  2018-06-12  8:10 [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
@ 2018-06-12  8:10 ` Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 2/4] x86/boot: Add acpitb.c to " Chao Fan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Chao Fan @ 2018-06-12  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, hpa, tglx, mingo, bhe, keescook, yasu.isimatu
  Cc: indou.takao, lcapitulino, caoj.fnst, douly.fnst, Chao Fan

In order to parse ACPI tables, some structers and functions of
ACPI code are needed. But ACPI code is an independent part and
has its closed logic. So dig the necessary structures and functions
from ACPI head files.
Can be used to help parse efi/bios tables, ACPI root tables, rsdp
tables, srat tables in 'compressed' directory.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/acpitb.h | 175 ++++++++++++++++++++++++++++++
 1 file changed, 175 insertions(+)
 create mode 100644 arch/x86/boot/compressed/acpitb.h

diff --git a/arch/x86/boot/compressed/acpitb.h b/arch/x86/boot/compressed/acpitb.h
new file mode 100644
index 000000000000..5ac00eb14141
--- /dev/null
+++ b/arch/x86/boot/compressed/acpitb.h
@@ -0,0 +1,175 @@
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include "misc.h"
+
+#define ACPI_NAME_SIZE                  4
+#define ACPI_OEM_ID_SIZE                6
+#define ACPI_OEM_TABLE_ID_SIZE          8
+#define ACPI_SRAT_MEM_HOT_PLUGGABLE (1<<1)        /* 01: Memory region is hot pluggable */
+
+#define ACPI_RSDP_SCAN_STEP             16
+#define ACPI_RSDP_CHECKSUM_LENGTH       20
+#define ACPI_RSDP_XCHECKSUM_LENGTH      36
+
+#define ACPI_CAST_PTR(t, p)	((t *) (void *) (p))
+#define ACPI_SIG_RSDP	"RSD PTR "      /* Root System Description Pointer */
+#define ACPI_VALIDATE_RSDP_SIG(a)	(!strncmp(ACPI_CAST_PTR(char, (a)), ACPI_SIG_RSDP, 8))
+
+#define ACPI_EBDA_PTR_LOCATION          0x0000040E      /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_BASE        0x000E0000      /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_SIZE        0x00020000
+#define ACPI_EBDA_WINDOW_SIZE		1024
+#define ACPI_MAX_TABLES			128
+#define ACPI_PTR_DIFF(a, b)	((acpi_size)(ACPI_CAST_PTR(u8, (a)) - ACPI_CAST_PTR(u8, (b))))
+#define ACPI_XSDT_ENTRY_SIZE	(sizeof(u64))
+#define ACPI_RSDT_ENTRY_SIZE	(sizeof(u32))
+
+#define ACPI_ADD_PTR(t, a, b)	(ACPI_CAST_PTR(t, (ACPI_CAST_PTR(u8, (a)) + (acpi_size)(b))))
+
+#ifdef ACPI_32BIT_PHYSICAL_ADDRESS
+
+/*
+ * OSPMs can define this to shrink the size of the structures for 32-bit
+ * none PAE environment. ASL compiler may always define this to generate
+ * 32-bit OSPM compliant tables.
+ */
+typedef u32 acpi_physical_address;
+
+#else                           /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
+/*
+ * It is reported that, after some calculations, the physical addresses can
+ * wrap over the 32-bit boundary on 32-bit PAE environment.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=87971
+ */
+typedef u64 acpi_physical_address;
+
+#endif                          /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
+typedef u64 acpi_size;
+
+struct acpi_table_rsdp {
+	char signature[8];	/* ACPI signature, contains "RSD PTR " */
+	u8 checksum;		/* ACPI 1.0 checksum */
+	char oem_id[ACPI_OEM_ID_SIZE];	/* OEM identification */
+	u8 revision;		/* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
+	u32 rsdt_physical_address;	/* 32-bit physical address of the RSDT */
+	u32 length;		/* Table length in bytes, including header (ACPI 2.0+) */
+	u64 xsdt_physical_address;	/* 64-bit physical address of the XSDT (ACPI 2.0+) */
+	u8 extended_checksum;	/* Checksum of entire table (ACPI 2.0+) */
+	u8 reserved[3];		/* Reserved, must be zero */
+};
+
+struct acpi_table_header *get_acpi_srat_table(void);
+/*******************************************************************************
+ *
+ * Master ACPI Table Header. This common header is used by all ACPI tables
+ * except the RSDP and FACS.
+ *
+ ******************************************************************************/
+
+struct acpi_table_header {
+	char signature[ACPI_NAME_SIZE];	/* ASCII table signature */
+	u32 length;		/* Length of table in bytes, including this header */
+	u8 revision;		/* ACPI Specification minor version number */
+	u8 checksum;		/* To make sum of entire table == 0 */
+	char oem_id[ACPI_OEM_ID_SIZE];	/* ASCII OEM identification */
+	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];	/* ASCII OEM table identification */
+	u32 oem_revision;	/* OEM revision number */
+	char asl_compiler_id[ACPI_NAME_SIZE];	/* ASCII ASL compiler vendor ID */
+	u32 asl_compiler_revision;	/* ASL compiler version */
+};
+
+/*******************************************************************************
+ *
+ * SRAT - System Resource Affinity Table
+ *        Version 3
+ *
+ ******************************************************************************/
+
+struct acpi_table_srat {
+	struct acpi_table_header header;	/* Common ACPI table header */
+	u32 table_revision;	/* Must be value '1' */
+	u64 reserved;		/* Reserved, must be zero */
+};
+
+/* Generic subtable header (used in MADT, SRAT, etc.) */
+
+struct acpi_subtable_header {
+	u8 type;
+	u8 length;
+};
+
+struct acpi_srat_mem_affinity {
+	struct acpi_subtable_header header;
+	u32 proximity_domain;
+	u16 reserved;		/* Reserved, must be zero */
+	u64 base_address;
+	u64 length;
+	u32 reserved1;
+	u32 flags;
+	u64 reserved2;		/* Reserved, must be zero */
+};
+
+/*
+ * Internal table-related structures
+ */
+union acpi_name_union {
+	u32 integer;
+	char ascii[4];
+};
+
+typedef u8 acpi_owner_id;
+
+/* Internal ACPI Table Descriptor. One per ACPI table. */
+
+struct acpi_table_desc {
+	acpi_physical_address address;
+	struct acpi_table_header *pointer;
+	u32 length;             /* Length fixed at 32 bits (fixed in table header) */
+	union acpi_name_union signature;
+	acpi_owner_id owner_id;
+	u8 flags;
+	u16 validation_count;
+};
+
+#ifdef ACPI_BIG_ENDIAN
+#define ACPI_MOVE_64_TO_64(d, s) \
+{((u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[7]; \
+((u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[6]; \
+((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[5]; \
+((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[4]; \
+((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3]; \
+((u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[2]; \
+((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1]; \
+((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0]; }
+#else
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#define ACPI_MOVE_64_TO_64(d, s) \
+{*(u64 *)(void *)(d) = *(u64 *)(void *)(s); }
+#else
+#define ACPI_MOVE_64_TO_64(d, s) \
+{((u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[0]; \
+((u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[1]; \
+((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[2]; \
+((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[3]; \
+((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[4]; \
+((u8 *)(void *)(d))[5] = ((u8 *)(void *)(s))[5]; \
+((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[6]; \
+((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[7]; }
+#endif
+#endif
+#ifdef ACPI_BIG_ENDIAN
+#define ACPI_MOVE_16_TO_32(d, s) \
+{(*(u32 *)(void *)(d)) = 0; \
+((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1]; \
+((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0]; }
+#else
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#define ACPI_MOVE_16_TO_32(d, s) \
+{*(u32 *)(void *)(d) = *(u16 *)(void *)(s); }
+#else
+#define ACPI_MOVE_16_TO_32(d, s) \
+{(*(u32 *)(void *)(d)) = 0; ACPI_MOVE_16_TO_16(d, s); }
+#endif
+#endif
-- 
2.17.0




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 2/4] x86/boot: Add acpitb.c to parse acpi tables
  2018-06-12  8:10 [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 1/4] x86/boot: Add acpitb.h to help parse acpi tables Chao Fan
@ 2018-06-12  8:10 ` Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 3/4] x86/boot/KASLR: Walk srat tables to filter immovable memory Chao Fan
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Chao Fan @ 2018-06-12  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, hpa, tglx, mingo, bhe, keescook, yasu.isimatu
  Cc: indou.takao, lcapitulino, caoj.fnst, douly.fnst, Chao Fan

To get more information about memory, acpi tables should be parsed.
But can't use ACPI code directely, so imitate the ACPI code to dig
the useful srat tables from ACPI tables.
Only dig the useful tables, and don't influence the initialization
of ACPI.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/Makefile |   1 +
 arch/x86/boot/compressed/acpitb.c | 245 ++++++++++++++++++++++++++++++
 2 files changed, 246 insertions(+)
 create mode 100644 arch/x86/boot/compressed/acpitb.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index fa42f895fdde..e2b7c176a2e8 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -82,6 +82,7 @@ ifdef CONFIG_X86_64
 	vmlinux-objs-y += $(obj)/mem_encrypt.o
 	vmlinux-objs-y += $(obj)/pgtable_64.o
 endif
+vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/acpitb.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
diff --git a/arch/x86/boot/compressed/acpitb.c b/arch/x86/boot/compressed/acpitb.c
new file mode 100644
index 000000000000..9b3433fb755d
--- /dev/null
+++ b/arch/x86/boot/compressed/acpitb.c
@@ -0,0 +1,245 @@
+#include "acpitb.h"
+
+extern unsigned long get_cmd_line_ptr(void);
+
+/* Search rsdp table from efi table. */
+static bool efi_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	efi_system_table_t *systab;
+	bool find_rsdp = false;
+	bool acpi_20 = false;
+	bool efi_64 = false;
+	void *config_tables;
+	struct efi_info *e;
+	char *sig;
+	int size;
+	int i;
+
+#ifndef CONFIG_EFI
+	return false;
+#endif
+
+	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 false;
+	}
+
+	/* Get systab from boot params. */
+#ifdef CONFIG_X86_32
+	if (e->efi_systab_hi || e->efi_memmap_hi) {
+		debug_putstr("Table located above 4GB, disabling EFI.\n");
+		return false;
+	}
+	systab = (efi_system_table_t *)e->efi_systab;
+#else
+	systab = (efi_system_table_t *)(
+			e->efi_systab | ((__u64)e->efi_systab_hi<<32));
+#endif
+
+	/* Get efi tables from systab. */
+	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, disabling EFI.\n");
+				return false;
+			}
+#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 (!(efi_guidcmp(guid, ACPI_TABLE_GUID)) && !acpi_20) {
+			*rsdp_addr = (acpi_physical_address)table;
+			acpi_20 = false;
+			find_rsdp = true;
+		} else if (!(efi_guidcmp(guid, ACPI_20_TABLE_GUID))) {
+			*rsdp_addr = (acpi_physical_address)table;
+			acpi_20 = true;
+			return true;
+		}
+	}
+	return find_rsdp;
+}
+
+static u8 checksum(u8 *buffer, u32 length)
+{
+	u8 sum = 0;
+	u8 *end = buffer + length;
+
+	while (buffer < end)
+		sum = (u8)(sum + *(buffer++));
+
+	return sum;
+}
+
+static u8 *scan_memory_for_rsdp(u8 *start_address, u32 length)
+{
+	struct acpi_table_rsdp *rsdp;
+	u8 *end_address;
+	u8 *mem_rover;
+
+	end_address = start_address + length;
+
+	for (mem_rover = start_address; mem_rover < end_address;
+	     mem_rover += ACPI_RSDP_SCAN_STEP) {
+		rsdp = (struct acpi_table_rsdp *)mem_rover;
+		if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature))
+			continue;
+		if (checksum((u8 *) rsdp,
+		    ACPI_RSDP_CHECKSUM_LENGTH) != 0)
+			continue;
+		if ((rsdp->revision >= 2) && (checksum((u8 *)
+		    rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0))
+			continue;
+		return mem_rover;
+	}
+	return NULL;
+}
+
+static void bios_get_rsdp_addr(acpi_physical_address *rsdp_addr)
+{
+	struct acpi_table_rsdp *rsdp;
+	u32 physical_address;
+	u8 *table_ptr;
+	u8 *mem_rover;
+
+	table_ptr = (u8 *)ACPI_EBDA_PTR_LOCATION;
+	ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
+	physical_address <<= 4;
+	table_ptr = (u8 *)(acpi_physical_address)physical_address;
+
+	if (physical_address > 0x400) {
+		mem_rover = scan_memory_for_rsdp(table_ptr,
+						 ACPI_EBDA_WINDOW_SIZE);
+
+		if (mem_rover) {
+			physical_address += (u32)ACPI_PTR_DIFF(mem_rover,
+							       table_ptr);
+			*rsdp_addr = (acpi_physical_address)physical_address;
+			return;
+		}
+	}
+
+	table_ptr = (u8 *)ACPI_HI_RSDP_WINDOW_BASE;
+	mem_rover = scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
+
+	if (mem_rover) {
+		physical_address = (u32)(ACPI_HI_RSDP_WINDOW_BASE +
+					 ACPI_PTR_DIFF(mem_rover, table_ptr));
+		*rsdp_addr = (acpi_physical_address)physical_address;
+		return;
+	}
+}
+
+/*
+ * Used to dig rsdp table from efi table or bios.
+ * If rsdp table found in efi table, use it. Or search bios.
+ */
+static acpi_physical_address get_rsdp_addr(void)
+{
+	acpi_physical_address pa = 0;
+	bool status = false;
+
+	status = efi_get_rsdp_addr(&pa);
+
+	if (!status || pa == 0)
+		bios_get_rsdp_addr(&pa);
+
+	return pa;
+}
+
+struct acpi_table_header *get_acpi_srat_table(void)
+{
+	struct acpi_table_desc table_descs[ACPI_MAX_TABLES];
+	char *args = (char *)get_cmd_line_ptr();
+	acpi_physical_address acpi_table;
+	acpi_physical_address root_table;
+	struct acpi_table_rsdp *rsdp;
+	struct acpi_table_header *th;
+	bool use_rsdt = false;
+	u32 table_entry_size;
+	u8 *table_entry;
+	u32 table_count;
+	int i, j;
+	u32 len;
+
+	rsdp = (struct acpi_table_rsdp *)get_rsdp_addr();
+	if (!rsdp)
+		return NULL;
+
+	/* Get rsdt or xsdt from rsdp. */
+	if (strstr(args, "acpi=rsdt"))
+		use_rsdt = true;
+
+	if (!(use_rsdt) &&
+	    (rsdp->xsdt_physical_address) && (rsdp->revision > 1)) {
+		root_table = rsdp->xsdt_physical_address;
+		table_entry_size = ACPI_XSDT_ENTRY_SIZE;
+	} else {
+		root_table = rsdp->rsdt_physical_address;
+		table_entry_size = ACPI_RSDT_ENTRY_SIZE;
+	}
+
+	/* Get acpi root table from rsdt or xsdt. */
+	th = (struct acpi_table_header *)root_table;
+	len = th->length;
+	table_count = (u32)((len - sizeof(struct acpi_table_header)) /
+				table_entry_size);
+	table_entry = ACPI_ADD_PTR(u8, th, sizeof(struct acpi_table_header));
+
+	for (i = 0; i < table_count; i++) {
+		u64 address64;
+
+		memset(&table_descs[i], 0, sizeof(struct acpi_table_desc));
+		if (table_entry_size == ACPI_RSDT_ENTRY_SIZE)
+			acpi_table = ((acpi_physical_address)
+					(*ACPI_CAST_PTR(u32, table_entry)));
+		else {
+			ACPI_MOVE_64_TO_64(&address64, table_entry);
+			acpi_table = (acpi_physical_address) address64;
+		}
+
+		if (acpi_table) {
+			table_descs[i].address = acpi_table;
+			table_descs[i].length = sizeof(
+						struct acpi_table_header);
+			table_descs[i].pointer = (struct acpi_table_header *)
+						  acpi_table;
+			for (j = 0; j < 4; j++)
+				table_descs[i].signature.ascii[j] =
+					((struct acpi_table_header *)
+					 acpi_table)->signature[j];
+		}
+
+		if (!strncmp(table_descs[i].signature.ascii, "SRAT", 4))
+			return table_descs[i].pointer;
+
+		table_entry += table_entry_size;
+	}
+	return NULL;
+}
-- 
2.17.0




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 3/4] x86/boot/KASLR: Walk srat tables to filter immovable memory
  2018-06-12  8:10 [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 1/4] x86/boot: Add acpitb.h to help parse acpi tables Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 2/4] x86/boot: Add acpitb.c to " Chao Fan
@ 2018-06-12  8:10 ` Chao Fan
  2018-06-12  8:10 ` [RFC PATCH 4/4] x86/boot/KASLR: Limit kaslr to choosing the " Chao Fan
  2018-07-02 12:18 ` [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in " Baoquan He
  4 siblings, 0 replies; 9+ messages in thread
From: Chao Fan @ 2018-06-12  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, hpa, tglx, mingo, bhe, keescook, yasu.isimatu
  Cc: indou.takao, lcapitulino, caoj.fnst, douly.fnst, Chao Fan

If 'CONFIG_MEMORY_HOTREMOVE' specified, walk the acpi srat memory
tables, store the immovable memory regions, so that kaslr can get
the information abouth where can be selected or not.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/kaslr.c | 55 ++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index b87a7582853d..4edff0501540 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -31,6 +31,7 @@
 
 #include "misc.h"
 #include "error.h"
+#include "acpitb.h"
 #include "../string.h"
 
 #include <generated/compile.h>
@@ -104,6 +105,17 @@ static bool memmap_too_large;
 /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
 unsigned long long mem_limit = ULLONG_MAX;
 
+/* Store the max numbers of acpi tables */
+#define ACPI_MAX_TABLES		128
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/* Store the movable memory */
+struct mem_vector immovable_mem[MAX_NUMNODES*2];
+
+/* Store the num of movable mem regions */
+static int num_immovable_mem;
+#endif
+
 
 enum mem_avoid_index {
 	MEM_AVOID_ZO_RANGE = 0,
@@ -266,6 +278,44 @@ static int handle_mem_memmap(void)
 	return 0;
 }
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+/*
+ * According to ACPI table, filter the immvoable memory regions
+ * and store them in immovable_mem[].
+ */
+static void handle_movable_mem(void)
+{
+	struct acpi_table_header *table_header;
+	struct acpi_subtable_header *asth;
+	struct acpi_srat_mem_affinity *ma;
+	unsigned long table_size;
+	unsigned long table_end;
+	int i = 0;
+
+	table_header = get_acpi_srat_table();
+
+	table_size = sizeof(struct acpi_table_srat);
+	table_end = (unsigned long)table_header + table_header->length;
+	asth = (struct acpi_subtable_header *)
+		((unsigned long)table_header + table_size);
+
+	while (((unsigned long)asth) +
+			sizeof(struct acpi_subtable_header) < table_end) {
+		if (asth->type == 1) {
+			ma = (struct acpi_srat_mem_affinity *)asth;
+			if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)) {
+				immovable_mem[i].start = ma->base_address;
+				immovable_mem[i].size = ma->length;
+				i++;
+			}
+		}
+		asth = (struct acpi_subtable_header *)
+			((unsigned long)asth + asth->length);
+	}
+	num_immovable_mem = i;
+}
+#endif
+
 /*
  * In theory, KASLR can put the kernel anywhere in the range of [16M, 64T).
  * The mem_avoid array is used to store the ranges that need to be avoided
@@ -389,6 +439,11 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
 	/* Mark the memmap regions we need to avoid */
 	handle_mem_memmap();
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+	/* Mark the hotplug SB regions we need choose */
+	handle_movable_mem();
+#endif
+
 #ifdef CONFIG_X86_VERBOSE_BOOTUP
 	/* Make sure video RAM can be used. */
 	add_identity_map(0, PMD_SIZE);
-- 
2.17.0




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 4/4] x86/boot/KASLR: Limit kaslr to choosing the immovable memory
  2018-06-12  8:10 [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
                   ` (2 preceding siblings ...)
  2018-06-12  8:10 ` [RFC PATCH 3/4] x86/boot/KASLR: Walk srat tables to filter immovable memory Chao Fan
@ 2018-06-12  8:10 ` Chao Fan
  2018-07-02 12:18 ` [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in " Baoquan He
  4 siblings, 0 replies; 9+ messages in thread
From: Chao Fan @ 2018-06-12  8:10 UTC (permalink / raw)
  To: linux-kernel, x86, hpa, tglx, mingo, bhe, keescook, yasu.isimatu
  Cc: indou.takao, lcapitulino, caoj.fnst, douly.fnst, Chao Fan

If 'CONFIG_MEMORY_HOTREMOVE' specified and the account of immovable
memory regions is not zero. Calculate the intersection between memory
regions from e820/efi memory table and immovable memory regions.

Rename process_mem_region to slots_count to match slots_fetch_random,
and name new function as process_mem_region.

Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
---
 arch/x86/boot/compressed/kaslr.c | 65 ++++++++++++++++++++++++++------
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 4edff0501540..a0a07e549ef8 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -545,9 +545,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;
 	struct slot_area slot_area;
@@ -624,6 +624,55 @@ 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)
+{
+#ifdef CONFIG_MEMORY_HOTREMOVE
+	/*
+	 * If hotplug memory found, filter the intersection between
+	 * immovable memory and region to slots_count.
+	 */
+	if (num_immovable_mem > 0) {
+		int i;
+
+		for (i = 0; i < num_immovable_mem; i++) {
+			struct mem_vector entry;
+			unsigned long long start, end, entry_end, region_end;
+
+			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);
+
+			if (entry.start + image_size < entry_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
+	/*
+	 * If no hotplug memory found, walk all the regions,
+	 * so use region directely.
+	 */
+	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_EFI
 /*
  * Returns true if mirror region found (and must have been processed
@@ -689,11 +738,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(&region, minimum, image_size);
-		if (slot_area_index == MAX_SLOT_AREA) {
-			debug_putstr("Aborted EFI scan (slot_areas full)!\n");
+		if (process_mem_region(&region, minimum, image_size))
 			break;
-		}
 	}
 	return true;
 }
@@ -720,11 +766,8 @@ static void process_e820_entries(unsigned long minimum,
 			continue;
 		region.start = entry->addr;
 		region.size = entry->size;
-		process_mem_region(&region, minimum, image_size);
-		if (slot_area_index == MAX_SLOT_AREA) {
-			debug_putstr("Aborted e820 scan (slot_areas full)!\n");
+		if (process_mem_region(&region, minimum, image_size))
 			break;
-		}
 	}
 }
 
-- 
2.17.0




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory.
  2018-06-12  8:10 [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
                   ` (3 preceding siblings ...)
  2018-06-12  8:10 ` [RFC PATCH 4/4] x86/boot/KASLR: Limit kaslr to choosing the " Chao Fan
@ 2018-07-02 12:18 ` Baoquan He
  2018-07-03  1:32   ` Chao Fan
  4 siblings, 1 reply; 9+ messages in thread
From: Baoquan He @ 2018-07-02 12:18 UTC (permalink / raw)
  To: Chao Fan
  Cc: linux-kernel, x86, hpa, tglx, mingo, keescook, yasu.isimatu,
	indou.takao, lcapitulino, caoj.fnst, douly.fnst

Hi Chao,

On 06/12/18 at 04:10pm, Chao Fan wrote:
> *** Issues need be discussed
> There are several issues I am not quite sure, please help review and
> give suggestions:
> 
> 1) In PATCH 1, I copy the structures and functions from ACPI head file,
>    so that ACPI head file will never been used here. I am not sure
>    whether it's good to include ACPI head file or use the method in
>    PATCH 1. If people think we can use ACPI head files directely, I
>    will remove the PATCH 1.

Usaully we try to reuse code even though they are located in different
life space. I think it applies to this SRAT handling. Copying ACPI codes
to kernel decompressing looks messy. Is there better way to reuse ACPI
code and read SRAT table, then get what we need in a simple way?

Thanks
Baoquan
> 
> ***Test results:
>  - I did a very simple test, and it can get the memory information in
>    bios and efi KVM guest machine, and put it by early printk. But no
>    more tests, so it's with RFC tag.
> 
> Any comments will be welcome.
> 
> 
> Chao Fan (4):
>   x86/boot: Add acpitb.h to help parse acpi tables
>   x86/boot: Add acpitb.c to parse acpi tables
>   x86/boot/KASLR: Walk srat tables to filter immovable memory
>   x86/boot/KASLR: Limit kaslr to choosing the immovable memory
> 
>  arch/x86/boot/compressed/Makefile |   1 +
>  arch/x86/boot/compressed/acpitb.c | 245 ++++++++++++++++++++++++++++++
>  arch/x86/boot/compressed/acpitb.h | 175 +++++++++++++++++++++
>  arch/x86/boot/compressed/kaslr.c  | 120 +++++++++++++--
>  4 files changed, 530 insertions(+), 11 deletions(-)
>  create mode 100644 arch/x86/boot/compressed/acpitb.c
>  create mode 100644 arch/x86/boot/compressed/acpitb.h
> 
> -- 
> 2.17.0
> 
> 
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory.
  2018-07-02 12:18 ` [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in " Baoquan He
@ 2018-07-03  1:32   ` Chao Fan
  2018-07-03  1:39     ` Baoquan He
  0 siblings, 1 reply; 9+ messages in thread
From: Chao Fan @ 2018-07-03  1:32 UTC (permalink / raw)
  To: Baoquan He
  Cc: linux-kernel, x86, hpa, tglx, mingo, keescook, yasu.isimatu,
	indou.takao, lcapitulino, caoj.fnst, douly.fnst

On Mon, Jul 02, 2018 at 08:18:55PM +0800, Baoquan He wrote:
>Hi Chao,
>
>On 06/12/18 at 04:10pm, Chao Fan wrote:
>> *** Issues need be discussed
>> There are several issues I am not quite sure, please help review and
>> give suggestions:
>> 
>> 1) In PATCH 1, I copy the structures and functions from ACPI head file,
>>    so that ACPI head file will never been used here. I am not sure
>>    whether it's good to include ACPI head file or use the method in
>>    PATCH 1. If people think we can use ACPI head files directely, I
>>    will remove the PATCH 1.
>
>Usaully we try to reuse code even though they are located in different
>life space. I think it applies to this SRAT handling. Copying ACPI codes

Yes, you are right. But as you said, they are in different life space,
so I don't have a better method to dig the SRAT table.
If anyone have a good way or suggestion, please tell me.

Thanks,
Chao Fan

>to kernel decompressing looks messy. Is there better way to reuse ACPI
>code and read SRAT table, then get what we need in a simple way?
>
>Thanks
>Baoquan
>> 
>> ***Test results:
>>  - I did a very simple test, and it can get the memory information in
>>    bios and efi KVM guest machine, and put it by early printk. But no
>>    more tests, so it's with RFC tag.
>> 
>> Any comments will be welcome.
>> 
>> 
>> Chao Fan (4):
>>   x86/boot: Add acpitb.h to help parse acpi tables
>>   x86/boot: Add acpitb.c to parse acpi tables
>>   x86/boot/KASLR: Walk srat tables to filter immovable memory
>>   x86/boot/KASLR: Limit kaslr to choosing the immovable memory
>> 
>>  arch/x86/boot/compressed/Makefile |   1 +
>>  arch/x86/boot/compressed/acpitb.c | 245 ++++++++++++++++++++++++++++++
>>  arch/x86/boot/compressed/acpitb.h | 175 +++++++++++++++++++++
>>  arch/x86/boot/compressed/kaslr.c  | 120 +++++++++++++--
>>  4 files changed, 530 insertions(+), 11 deletions(-)
>>  create mode 100644 arch/x86/boot/compressed/acpitb.c
>>  create mode 100644 arch/x86/boot/compressed/acpitb.h
>> 
>> -- 
>> 2.17.0
>> 
>> 
>> 
>
>



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory.
  2018-07-03  1:32   ` Chao Fan
@ 2018-07-03  1:39     ` Baoquan He
  2018-07-03  1:40       ` Chao Fan
  0 siblings, 1 reply; 9+ messages in thread
From: Baoquan He @ 2018-07-03  1:39 UTC (permalink / raw)
  To: Chao Fan
  Cc: linux-kernel, x86, hpa, tglx, mingo, keescook, yasu.isimatu,
	indou.takao, lcapitulino, caoj.fnst, douly.fnst

On 07/03/18 at 09:32am, Chao Fan wrote:
> On Mon, Jul 02, 2018 at 08:18:55PM +0800, Baoquan He wrote:
> >Hi Chao,
> >
> >On 06/12/18 at 04:10pm, Chao Fan wrote:
> >> *** Issues need be discussed
> >> There are several issues I am not quite sure, please help review and
> >> give suggestions:
> >> 
> >> 1) In PATCH 1, I copy the structures and functions from ACPI head file,
> >>    so that ACPI head file will never been used here. I am not sure
> >>    whether it's good to include ACPI head file or use the method in
> >>    PATCH 1. If people think we can use ACPI head files directely, I
> >>    will remove the PATCH 1.
> >
> >Usaully we try to reuse code even though they are located in different
> >life space. I think it applies to this SRAT handling. Copying ACPI codes
> 
> Yes, you are right. But as you said, they are in different life space,
> so I don't have a better method to dig the SRAT table.
> If anyone have a good way or suggestion, please tell me.

I think someone has told a good way, please check
arch/x86/boot/compressed/eboot.c and see what uefi has done.

> 
> >to kernel decompressing looks messy. Is there better way to reuse ACPI
> >code and read SRAT table, then get what we need in a simple way?
> >
> >Thanks
> >Baoquan
> >> 
> >> ***Test results:
> >>  - I did a very simple test, and it can get the memory information in
> >>    bios and efi KVM guest machine, and put it by early printk. But no
> >>    more tests, so it's with RFC tag.
> >> 
> >> Any comments will be welcome.
> >> 
> >> 
> >> Chao Fan (4):
> >>   x86/boot: Add acpitb.h to help parse acpi tables
> >>   x86/boot: Add acpitb.c to parse acpi tables
> >>   x86/boot/KASLR: Walk srat tables to filter immovable memory
> >>   x86/boot/KASLR: Limit kaslr to choosing the immovable memory
> >> 
> >>  arch/x86/boot/compressed/Makefile |   1 +
> >>  arch/x86/boot/compressed/acpitb.c | 245 ++++++++++++++++++++++++++++++
> >>  arch/x86/boot/compressed/acpitb.h | 175 +++++++++++++++++++++
> >>  arch/x86/boot/compressed/kaslr.c  | 120 +++++++++++++--
> >>  4 files changed, 530 insertions(+), 11 deletions(-)
> >>  create mode 100644 arch/x86/boot/compressed/acpitb.c
> >>  create mode 100644 arch/x86/boot/compressed/acpitb.h
> >> 
> >> -- 
> >> 2.17.0
> >> 
> >> 
> >> 
> >
> >
> 
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory.
  2018-07-03  1:39     ` Baoquan He
@ 2018-07-03  1:40       ` Chao Fan
  0 siblings, 0 replies; 9+ messages in thread
From: Chao Fan @ 2018-07-03  1:40 UTC (permalink / raw)
  To: Baoquan He
  Cc: linux-kernel, x86, hpa, tglx, mingo, keescook, yasu.isimatu,
	indou.takao, lcapitulino, caoj.fnst, douly.fnst

On Tue, Jul 03, 2018 at 09:39:02AM +0800, Baoquan He wrote:
>On 07/03/18 at 09:32am, Chao Fan wrote:
>> On Mon, Jul 02, 2018 at 08:18:55PM +0800, Baoquan He wrote:
>> >Hi Chao,
>> >
>> >On 06/12/18 at 04:10pm, Chao Fan wrote:
>> >> *** Issues need be discussed
>> >> There are several issues I am not quite sure, please help review and
>> >> give suggestions:
>> >> 
>> >> 1) In PATCH 1, I copy the structures and functions from ACPI head file,
>> >>    so that ACPI head file will never been used here. I am not sure
>> >>    whether it's good to include ACPI head file or use the method in
>> >>    PATCH 1. If people think we can use ACPI head files directely, I
>> >>    will remove the PATCH 1.
>> >
>> >Usaully we try to reuse code even though they are located in different
>> >life space. I think it applies to this SRAT handling. Copying ACPI codes
>> 
>> Yes, you are right. But as you said, they are in different life space,
>> so I don't have a better method to dig the SRAT table.
>> If anyone have a good way or suggestion, please tell me.
>
>I think someone has told a good way, please check
>arch/x86/boot/compressed/eboot.c and see what uefi has done.

I will check the detail, thanks.

Thanks,
Chao Fan
>
>> 
>> >to kernel decompressing looks messy. Is there better way to reuse ACPI
>> >code and read SRAT table, then get what we need in a simple way?
>> >
>> >Thanks
>> >Baoquan
>> >> 
>> >> ***Test results:
>> >>  - I did a very simple test, and it can get the memory information in
>> >>    bios and efi KVM guest machine, and put it by early printk. But no
>> >>    more tests, so it's with RFC tag.
>> >> 
>> >> Any comments will be welcome.
>> >> 
>> >> 
>> >> Chao Fan (4):
>> >>   x86/boot: Add acpitb.h to help parse acpi tables
>> >>   x86/boot: Add acpitb.c to parse acpi tables
>> >>   x86/boot/KASLR: Walk srat tables to filter immovable memory
>> >>   x86/boot/KASLR: Limit kaslr to choosing the immovable memory
>> >> 
>> >>  arch/x86/boot/compressed/Makefile |   1 +
>> >>  arch/x86/boot/compressed/acpitb.c | 245 ++++++++++++++++++++++++++++++
>> >>  arch/x86/boot/compressed/acpitb.h | 175 +++++++++++++++++++++
>> >>  arch/x86/boot/compressed/kaslr.c  | 120 +++++++++++++--
>> >>  4 files changed, 530 insertions(+), 11 deletions(-)
>> >>  create mode 100644 arch/x86/boot/compressed/acpitb.c
>> >>  create mode 100644 arch/x86/boot/compressed/acpitb.h
>> >> 
>> >> -- 
>> >> 2.17.0
>> >> 
>> >> 
>> >> 
>> >
>> >
>> 
>> 
>
>



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-07-03  1:42 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-12  8:10 [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in immovable memory Chao Fan
2018-06-12  8:10 ` [RFC PATCH 1/4] x86/boot: Add acpitb.h to help parse acpi tables Chao Fan
2018-06-12  8:10 ` [RFC PATCH 2/4] x86/boot: Add acpitb.c to " Chao Fan
2018-06-12  8:10 ` [RFC PATCH 3/4] x86/boot/KASLR: Walk srat tables to filter immovable memory Chao Fan
2018-06-12  8:10 ` [RFC PATCH 4/4] x86/boot/KASLR: Limit kaslr to choosing the " Chao Fan
2018-07-02 12:18 ` [RFC PATCH 0/4] x86/boot/KASLR: Parse ACPI table and limit kaslr in " Baoquan He
2018-07-03  1:32   ` Chao Fan
2018-07-03  1:39     ` Baoquan He
2018-07-03  1:40       ` Chao Fan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).