x86, boot: clean up setup_data handling
Subsystems (6)
v3 cover x86, boot: clean up setup_data handling
Now setup_data is reserved via memblock and e820 and different handlers have different ways, and it is confusing.
1. SETUP_E820_EXT: is consumed early and will not copy or access again. have memory wasted.
2. SETUP_EFI: is accessed via ioremap every time at early stage. have memory wasted.
3. SETUP_DTB: is copied locally.
have memory wasted.
4. SETUP_PCI: is accessed via ioremap for every pci devices, even run-time.
5. SETUP_KASLR: is accessed early, will not copy or access again. have memory wasted.
Also setup_data is exported to debugfs for debug purpose.
Here will convert to let every handler to decide how to handle it. and will not reserve the setup_data generally, so will not waste memory and also make memblock/e820 keep page aligned.
1. not touch E820 anymore.
2. copy SETUP_EFI to __initdata variable and access it without ioremap.
3. SETUP_DTB: reserver and copy to local and free.
4. SETUP_PCI: reverve localy and convert to list, to avoid keeping ioremap.
5. export SETUP_PCI via sysfs.
Also put them in:git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-x86-4.0-rc2-setup_data
Should be materials for v4.1.
Thanks
Yinghai Lu
-v3: separated with kasl patches, and fix early_ioremap return checking.
Yinghai Lu (8):
x86: Kill E820_RESERVED_KERN
x86, efi: Copy SETUP_EFI data and access directly x86, of: Let add_dtb reserve setup_data locally x86, boot: Add add_pci handler for SETUP_PCI
x86: Kill not used setup_data handling code x86, boot, PCI: Convert SETUP_PCI data to list x86, boot, PCI: Copy SETUP_PCI rom to kernel space x86, boot, PCI: Export SETUP_PCI data via sysfs
arch/x86/include/asm/efi.h | 2 +- arch/x86/include/asm/pci.h | 4 + arch/x86/include/asm/prom.h | 9 +- arch/x86/include/uapi/asm/e820.h | 9 -- arch/x86/kernel/devicetree.c | 43 +++--- arch/x86/kernel/e820.c | 6 +- arch/x86/kernel/kdebugfs.c | 142 ------------------ arch/x86/kernel/setup.c | 52 ++----- arch/x86/kernel/tboot.c | 3 +- arch/x86/mm/init_64.c | 11 +- arch/x86/pci/common.c | 316 ++++++++++++++++++++++++++++++++++++--- arch/x86/platform/efi/efi.c | 13 +- arch/x86/platform/efi/efi_64.c | 13 +- arch/x86/platform/efi/quirks.c | 23 +-- 14 files changed, 371 insertions(+), 275 deletions(-)
Signature · 1 line
1.8.4.5
PATCH v3 1/8 x86: Kill E820_RESERVED_KERN
Now we are using memblock to do early resource reserver/allocation instead of using e820 map directly, and setup_data is reserved in memblock early already.
Also kexec generate setup_data and pass pointer to second kernel, so second kernel reserve setup_data by their own.
(Now kexec-tools create SETUP_EFI and SETUP_E820_EXT).
We can kill E820_RESERVED_KERN and not touch e820 map at all.
That will fix bug in mark_nonsave_region that can not handle that
case: E820_RAM and E820_RESERVED_KERN ranges are continuous and boundary is not page aligned.
Bugzilla: https://bugzilla.opensuse.org/show_bug.cgi?id=913885
--- arch/x86/include/uapi/asm/e820.h | 9 --------- arch/x86/kernel/e820.c | 6 ++---- arch/x86/kernel/setup.c | 26 -------------------------- arch/x86/kernel/tboot.c | 3 +-- arch/x86/mm/init_64.c | 11 ++++------- 5 files changed, 7 insertions(+), 48 deletions(-)
arch/x86/include/uapi/asm/e820.h +0 -9
@@ -33,15 +33,6 @@#define E820_NVS 4#define E820_UNUSABLE 5 - -/* -* reserved RAM used by kernel itself -* if CONFIG_INTEL_TXT is enabled, memory of this type will be -* included in the S3 integrity calculation and so should not include -* any memory that BIOS might alter over the S3 transition -*/ -#define E820_RESERVED_KERN 128 -#ifndef __ASSEMBLY__#include <linux/types.h> struct e820entry {
arch/x86/kernel/e820.c +2 -4
@@ -134,7 +134,6 @@ static void __init e820_print_type(u32 type) {switch (type) {case E820_RAM : -case E820_RESERVED_KERN :printk (KERN_CONT "usable" );break ;case E820_RESERVED :
@@ -688,7 +687,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)register_nosave_region (pfn,PFN_UP (ei->addr)); pfn =PFN_DOWN (ei->addr + ei->size); -if (ei->type !=E820_RAM && ei->type !=E820_RESERVED_KERN ) +if (ei->type !=E820_RAM )register_nosave_region (PFN_UP (ei->addr), pfn);if (pfn >= limit_pfn)
@@ -902,7 +901,6 @@ void __init finish_e820_parsing(void)static inline const char *e820_type_to_string (int e820_type) {switch (e820_type) { -case E820_RESERVED_KERN :case E820_RAM :return "System RAM" ;case E820_ACPI :return "ACPI Tables" ;case E820_NVS :return "ACPI Non-volatile Storage" ;
@@ -1077,7 +1075,7 @@ void __init memblock_x86_fill(void)if (end != (resource_size_t )end)continue ; -if (ei->type !=E820_RAM && ei->type !=E820_RESERVED_KERN ) +if (ei->type !=E820_RAM )continue ;memblock_add (ei->addr, ei->size);
arch/x86/kernel/setup.c +0 -26
@@ -478,30 +478,6 @@ static void __init parse_setup_data(void) } } -static void __init e820_reserve_setup_data (void ) -{ -struct setup_data *data; -u64 pa_data; -int found =0 ; - - pa_data = boot_params.hdr.setup_data; -while (pa_data) { - data =early_memremap (pa_data,sizeof (*data)); -e820_update_range (pa_data,sizeof (*data)+data->len, -E820_RAM ,E820_RESERVED_KERN ); - found =1 ; - pa_data = data->next; -early_iounmap (data,sizeof (*data)); - } -if (!found) -return ; - -sanitize_e820_map (e820.map,ARRAY_SIZE (e820.map), &e820.nr_map); -memcpy (&e820_saved, &e820,sizeof (struct e820map )); -printk (KERN_INFO "extended physical RAM map:\n" ); -e820_print_map ("reserve setup_data" ); -} -static void __init memblock_x86_reserve_range_setup_data (void ) {struct setup_data *data;
@@ -1037,8 +1013,6 @@ void __init setup_arch(char **cmdline_p)early_dump_pci_devices ();#endif -/* update the e820_saved too */ -e820_reserve_setup_data ();finish_e820_parsing ();if (efi_enabled (EFI_BOOT ))
arch/x86/kernel/tboot.c +1 -2
@@ -195,8 +195,7 @@ static int tboot_setup_sleep(void) tboot->num_mac_regions =0 ;for (i =0 ; i < e820.nr_map; i++) { -if ((e820.map[i].type !=E820_RAM ) - && (e820.map[i].type !=E820_RESERVED_KERN )) +if (e820.map[i].type !=E820_RAM )continue ;add_mac_region (e820.map[i].addr, e820.map[i].size);
arch/x86/mm/init_64.c +4 -7
@@ -354,8 +354,7 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, next = (addr &PAGE_MASK ) +PAGE_SIZE ;if (addr >= end) {if (!after_bootmem && - !e820_any_mapped (addr &PAGE_MASK , next,E820_RAM ) && - !e820_any_mapped (addr &PAGE_MASK , next,E820_RESERVED_KERN )) + !e820_any_mapped (addr &PAGE_MASK , next,E820_RAM ))set_pte (pte,__pte (0 ));continue ; }
@@ -401,9 +400,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, next = (address &PMD_MASK ) +PMD_SIZE ;if (address >= end) { -if (!after_bootmem && - !e820_any_mapped (address &PMD_MASK , next,E820_RAM ) && - !e820_any_mapped (address &PMD_MASK , next,E820_RESERVED_KERN )) +if (!after_bootmem && !e820_any_mapped ( + address &PMD_MASK , next,E820_RAM ))set_pmd (pmd,__pmd (0 ));continue ; }
@@ -476,8 +474,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, next = (addr &PUD_MASK ) +PUD_SIZE ;if (addr >= end) {if (!after_bootmem && - !e820_any_mapped (addr &PUD_MASK , next,E820_RAM ) && - !e820_any_mapped (addr &PUD_MASK , next,E820_RESERVED_KERN )) + !e820_any_mapped (addr &PUD_MASK , next,E820_RAM ))set_pud (pud,__pud (0 ));continue ; }
Signature · 1 line
1.8.4.5
PATCH v3 2/8 x86, efi: Copy SETUP_EFI data and access directly
In reply to Yinghai LuThe copy will be in __initdata, and it is small.
We can use pointer to access the setup_data instead of using early_memmap everywhere.
--- arch/x86/include/asm/efi.h | 2 +- arch/x86/platform/efi/efi.c | 13 ++----------- arch/x86/platform/efi/efi_64.c | 13 ++++++++++++- arch/x86/platform/efi/quirks.c | 23 ++++++----------------- 4 files changed, 21 insertions(+), 30 deletions(-)
arch/x86/include/asm/efi.h +1 -1
@@ -114,7 +114,7 @@ struct efi_setup_data {u64 reserved[8 ]; }; -extern u64 efi_setup; +extern struct efi_setup_data *efi_setup;#ifdef CONFIG_EFI
arch/x86/platform/efi/efi.c +2 -11
@@ -68,7 +68,7 @@ static efi_config_table_type_t arch_tables[] __initdata = { {NULL_GUID, NULL, NULL}, }; -u64 efi_setup;/* efi setup_data physical address */ +struct efi_setup_data *efi_setup__initdata ;/* cached efi setup_data pointer */ static int add_efi_memmap__initdata ;static int __init setup_add_efi_memmap (char *arg)
@@ -225,20 +225,13 @@ static int __init efi_systab_init(void *phys) {if (efi_enabled (EFI_64BIT )) {efi_system_table_64_t *systab64; -struct efi_setup_data *data =NULL ; +struct efi_setup_data *data = efi_setup;u64 tmp =0 ; -if (efi_setup) { - data =early_memremap (efi_setup,sizeof (*data)); -if (!data) -return -ENOMEM ; - } systab64 =early_memremap ((unsigned long )phys,sizeof (*systab64));if (systab64 ==NULL ) {pr_err ("Couldn't map the system table!\n" ); -if (data) -early_memunmap (data,sizeof (*data));return -ENOMEM ; }
@@ -271,8 +264,6 @@ static int __init efi_systab_init(void *phys) tmp |= data ? data->tables : systab64->tables;early_memunmap (systab64,sizeof (*systab64)); -if (data) -early_memunmap (data,sizeof (*data));#ifdef CONFIG_X86_32 if (tmp >>32 ) {pr_err ("EFI data located above 4GB, disabling EFI.\n" );
arch/x86/platform/efi/efi_64.c +12 -1
@@ -292,9 +292,20 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,return (void __iomem *)__va (phys_addr); } +static struct efi_setup_data efi_setup_data__initdata ; +void __init parse_efi_setup (u64 phys_addr,u32 data_len) { - efi_setup = phys_addr +sizeof (struct setup_data ); +struct efi_setup_data *data; + + data =early_memremap (phys_addr +sizeof (struct setup_data ), +sizeof (*data)); +if (!data) +return ; + + efi_setup_data = *data; +early_memunmap (data,sizeof (*data)); + efi_setup = &efi_setup_data; }void __init efi_runtime_mkexec (void )
arch/x86/platform/efi/quirks.c +6 -17
@@ -203,9 +203,8 @@ void __init efi_free_boot_services(void)*/ int __init efi_reuse_config (u64 tables,int nr_tables) { -int i, sz, ret =0 ; +int i, sz;void *p, *tablep; -struct efi_setup_data *data;if (!efi_setup)return 0 ;
@@ -213,22 +212,15 @@ int __init efi_reuse_config(u64 tables, int nr_tables)if (!efi_enabled (EFI_64BIT ))return 0 ; - data =early_memremap (efi_setup,sizeof (*data)); -if (!data) { - ret = -ENOMEM ; - goto out; - } - -if (!data->smbios) - goto out_memremap; +if (!efi_setup->smbios) +return 0 ; sz =sizeof (efi_config_table_64_t); p = tablep =early_memremap (tables, nr_tables * sz);if (!p) {pr_err ("Could not map Configuration table!\n" ); - ret = -ENOMEM ; - goto out_memremap; +return -ENOMEM ; }for (i =0 ; i < efi.systab->nr_tables; i++) {
@@ -237,15 +229,12 @@ int __init efi_reuse_config(u64 tables, int nr_tables) guid = ((efi_config_table_64_t *)p)->guid;if (!efi_guidcmp (guid,SMBIOS_TABLE_GUID )) - ((efi_config_table_64_t *)p)->table = data->smbios; + ((efi_config_table_64_t *)p)->table = efi_setup->smbios; p += sz; }early_memunmap (tablep, nr_tables * sz); -out_memremap: -early_memunmap (data,sizeof (*data)); -out: -return ret; +return 0 ; }void __init efi_apply_memmap_quirks (void )
Signature · 1 line
1.8.4.5