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
Re: [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
Quoted 7 lines · Yinghai Lu
Now we are using memblock to do early resource reserver/allocation instead of using e820 map directly, and
setup_datais reserved in memblock early already.
Also kexec generatesetup_dataand pass pointer to second kernel, so second kernel reservesetup_databy their own.
(Now kexec-tools createSETUP_EFIandSETUP_E820_EXT).
Quoted 7 lines
We can kill
E820_RESERVED_KERNand not touch e820 map at all.That will fix bug in
mark_nonsave_regionthat can not handle that
case:E820_RAMandE820_RESERVED_KERNranges are continuous and boundary is not page aligned.Bugzilla: https://bugzilla.opensuse.org/show_bug.cgi?id=913885
Is this the bug referenced in the commit message that is fixed? If so, it's only a bug for resume, correct? I'm not sure if that's clear enough just from the commit message, I was looking at this patch for an e820 problem I'm currently facing on 3.3.
Quoted 5 lines
Reported-by "Lee, Chun-Yi" <jlee-IBi9RG/[email protected]>Cc "Lee, Chun-Yi" <jlee-IBi9RG/[email protected]>Signed-off-by Yinghai Lu <[email protected]>
Hmm, although the bug is reported for a 3.12 kernel, I assume this is for stable 3.10+? If so, it should apply fine with the exception of removing e820_reserve_setup_data() from setup_arch() rather than memblock_x86_reserve_range_setup_data(). Or is it for 3.2 as well and needs to be completely rebased for that kernel?
Re: [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
Quoted 6 lines · David Rientjes
Hmm, although the bug is reported for a 3.12 kernel, I assume this is for stable 3.10+? If so, it should apply fine with the exception of removing
e820_reserve_setup_data()fromsetup_arch()rather thanmemblock_x86_reserve_range_setup_data(). Or is it for 3.2 as well and needs to be completely rebased for that kernel?
For 3.10+, we will need to following patches, otherwise will have warning for SETUP_PCI with ioremap.
for 3.2 that does not SETUP_PCI, should be ok, but will need rebase.
Thanks
Yinghai
Re: [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
In reply to David RientjesQuoted 15 lines · David Rientjes
Quoted 13 lines · Yinghai Lu
Now we are using memblock to do early resource reserver/allocation instead of using e820 map directly, and
setup_datais reserved in memblock early already.
Also kexec generatesetup_dataand pass pointer to second kernel, so second kernel reservesetup_databy their own.
(Now kexec-tools createSETUP_EFIandSETUP_E820_EXT).We can kill
E820_RESERVED_KERNand not touch e820 map at all.That will fix bug in
mark_nonsave_regionthat can not handle that
case:E820_RAMandE820_RESERVED_KERNranges are continuous and boundary is not page aligned.
Quoted 6 lines
Quoted 1 line
Bugzilla: https://bugzilla.opensuse.org/show_bug.cgi?id=913885
Is this the bug referenced in the commit message that is fixed? If so, it's only a bug for resume, correct? I'm not sure if that's clear enough just from the commit message, I was looking at this patch for an e820 problem I'm currently facing on 3.3.
Yinghai's patches fixed the e820 not page aligned issue that's one of the issues on bug reporter's machine. I found another issue of the BIOS that sometimes it doesn't really keep the e820 table unchanging for hibernate resuming, this BIOS issue causes the total available page number checking fail. I will file another openSUSE bug to separate those 2 issues.
Quoted 7 lines
Quoted 6 lines
Reported-by "Lee, Chun-Yi" <jlee-IBi9RG/[email protected]>Cc "Lee, Chun-Yi" <jlee-IBi9RG/[email protected]>Signed-off-by Yinghai Lu <[email protected]>
Quoted 5 lines
Hmm, although the bug is reported for a 3.12 kernel, I assume this is for stable 3.10+? If so, it should apply fine with the exception of removing
e820_reserve_setup_data()fromsetup_arch()rather thanmemblock_x86_reserve_range_setup_data(). Or is it for 3.2 as well and needs to be completely rebased for that kernel?
Thanks a lot!
Joey Lee
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
PATCH v3 3/8 x86, of: Let add_dtb reserve setup_data locally
In reply to Yinghai LuWe will not reserve setup_data in generic code. Every handler need to reserve and copy setup_data locally.
Current dtd handling already have code for copying, just add reserve code.
Also simplify code a bit by storing real dtb size.
--- arch/x86/include/asm/prom.h | 9 ++++++--- arch/x86/kernel/devicetree.c | 43 +++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 21 deletions(-)
arch/x86/include/asm/prom.h +6 -3
@@ -24,17 +24,20 @@#ifdef CONFIG_OF extern int of_ioapic; -extern u64 initial_dtb; -extern void add_dtb (u64 data);void x86_of_pci_init (void );void x86_dtb_init (void );#else -static inline void add_dtb (u64 data) { }static inline void x86_of_pci_init (void ) { }static inline void x86_dtb_init (void ) { }#define of_ioapic 0#endif +#ifdef CONFIG_OF_FLATTREE +extern void add_dtb (u64 data); +#else +static inline void add_dtb (u64 data) { } +#endif +extern char cmd_line[COMMAND_LINE_SIZE ];#endif /* __ASSEMBLY__ */
arch/x86/kernel/devicetree.c +25 -18
80 lines not on this page · raw message
Signature · 1 line
1.8.4.5
PATCH v3 4/8 x86, boot: Add add_pci handler for SETUP_PCI
In reply to Yinghai LuLet it reserve setup_data, and keep it's own list.
Also clear the hdr.setup_data, as all handler now handle or reserve setup_data locally already.
--- arch/x86/include/asm/pci.h | 2 ++ arch/x86/kernel/setup.c | 8 ++++++++ arch/x86/pci/common.c | 45 +++++++++++++++++++++++++++++++-------------- 3 files changed, 41 insertions(+), 14 deletions(-)
arch/x86/include/asm/pci.h +2 -0
@@ -87,8 +87,10 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, *strat =PCI_DMA_BURST_INFINITY ; *strategy_parameter = ~0UL; } +void add_pci (u64 pa_data);#else static inline void early_quirks (void ) { } +static inline void add_pci (u64 pa_data) { }#endif extern void pci_iommu_alloc (void );
arch/x86/kernel/setup.c +8 -0
@@ -458,6 +458,8 @@ static void __init parse_setup_data(void) pa_next = data->next;early_iounmap (data,sizeof (*data)); +printk (KERN_DEBUG "setup_data type: %d @ %#010llx\n" , + data_type, pa_data);switch (data_type) {case SETUP_E820_EXT :parse_e820_ext (pa_data, data_len);
@@ -465,6 +467,9 @@ static void __init parse_setup_data(void)case SETUP_DTB :add_dtb (pa_data);break ; +case SETUP_PCI : +add_pci (pa_data); +break ;case SETUP_EFI :parse_efi_setup (pa_data, data_len);break ;
@@ -472,10 +477,13 @@ static void __init parse_setup_data(void)parse_kaslr_setup (pa_data, data_len);break ;default : +pr_warn ("Unknown setup_data type: %d @ %#010llx ignored!\n" , + data_type, pa_data);break ; } pa_data = pa_next; } + boot_params.hdr.setup_data =0 ;/* all done */ }static void __init memblock_x86_reserve_range_setup_data (void )
arch/x86/pci/common.c +31 -14
68 lines not on this page · raw message
Signature · 1 line
1.8.4.5
PATCH v3 5/8 x86: Kill not used setup_data handling code
In reply to Yinghai Lu--- arch/x86/kernel/kdebugfs.c | 142 --------------------------------------------- arch/x86/kernel/setup.c | 17 ------ 2 files changed, 159 deletions(-)
arch/x86/kernel/kdebugfs.c +0 -142
@@ -21,142 +21,6 @@ struct dentry *arch_debugfs_dir;EXPORT_SYMBOL (arch_debugfs_dir);#ifdef CONFIG_DEBUG_BOOT_PARAMS -struct setup_data_node { -u64 paddr; -u32 type; -u32 len; -}; - -static ssize_t setup_data_read (struct file *file,char __user *user_buf, -size_t count,loff_t *ppos) -{ -struct setup_data_node *node = file->private_data; -unsigned long remain; -loff_t pos = *ppos; -struct page *pg; -void *p; -u64 pa; - -if (pos <0 ) -return -EINVAL ; - -if (pos >= node->len) -return 0 ; - -if (count > node->len - pos) - count = node->len - pos; - - pa = node->paddr +sizeof (struct setup_data ) + pos; - pg =pfn_to_page ((pa + count -1 ) >>PAGE_SHIFT ); -if (PageHighMem (pg)) { - p =ioremap_cache (pa, count); -if (!p) -return -ENXIO ; - }else - p =__va (pa); - - remain =copy_to_user (user_buf, p, count); - -if (PageHighMem (pg)) -iounmap (p); - -if (remain) -return -EFAULT ; - - *ppos = pos + count; - -return count; -} - -static const struct file_operations fops_setup_data = { - .read = setup_data_read, - .open = simple_open, - .llseek = default_llseek, -}; - -static int __init -create_setup_data_node (struct dentry *parent,int no, -struct setup_data_node *node) -{ -struct dentry *d, *type, *data; -char buf[16 ]; - -sprintf (buf,"%d" , no); - d =debugfs_create_dir (buf, parent); -if (!d) -return -ENOMEM ; - - type =debugfs_create_x32 ("type" ,S_IRUGO , d, &node->type); -if (!type) - goto err_dir; - - data =debugfs_create_file ("data" ,S_IRUGO , d, node, &fops_setup_data); -if (!data) - goto err_type; - -return 0 ; - -err_type: -debugfs_remove (type); -err_dir: -debugfs_remove (d); -return -ENOMEM ; -} - -static int __init create_setup_data_nodes (struct dentry *parent) -{ -struct setup_data_node *node; -struct setup_data *data; -int error; -struct dentry *d; -struct page *pg; -u64 pa_data; -int no =0 ; - - d =debugfs_create_dir ("setup_data" , parent); -if (!d) -return -ENOMEM ; - - pa_data = boot_params.hdr.setup_data; - -while (pa_data) { - node =kmalloc (sizeof (*node),GFP_KERNEL ); -if (!node) { - error = -ENOMEM ; - goto err_dir; - } - - pg =pfn_to_page ((pa_data+sizeof (*data)-1 ) >>PAGE_SHIFT ); -if (PageHighMem (pg)) { - data =ioremap_cache (pa_data,sizeof (*data)); -if (!data) { -kfree (node); - error = -ENXIO ; - goto err_dir; - } - }else - data =__va (pa_data); - - node->paddr = pa_data; - node->type = data->type; - node->len = data->len; - error =create_setup_data_node (d, no, node); - pa_data = data->next; - -if (PageHighMem (pg)) -iounmap (data); -if (error) - goto err_dir; - no++; - } - -return 0 ; - -err_dir: -debugfs_remove (d); -return error; -} -static struct debugfs_blob_wrapper boot_params_blob = { .data = &boot_params, .size = sizeof(boot_params),
@@ -181,14 +45,8 @@ static int __init boot_params_kdebugfs_init(void)if (!data) goto err_version; - error =create_setup_data_nodes (dbp); -if (error) - goto err_data; -return 0 ; -err_data: -debugfs_remove (data); err_version:debugfs_remove (version); err_dir:
arch/x86/kernel/setup.c +0 -17
@@ -486,20 +486,6 @@ static void __init parse_setup_data(void) boot_params.hdr.setup_data =0 ;/* all done */ } -static void __init memblock_x86_reserve_range_setup_data (void ) -{ -struct setup_data *data; -u64 pa_data; - - pa_data = boot_params.hdr.setup_data; -while (pa_data) { - data =early_memremap (pa_data,sizeof (*data)); -memblock_reserve (pa_data,sizeof (*data) + data->len); - pa_data = data->next; -early_iounmap (data,sizeof (*data)); - } -} -/* * --------- Crashkernel reservation ------------------------------ */
@@ -1006,9 +992,6 @@ void __init setup_arch(char **cmdline_p)x86_report_nx (); -/* after early param, so could get panic from serial */ -memblock_x86_reserve_range_setup_data (); -if (acpi_mps_check ()) {#ifdef CONFIG_X86_LOCAL_APIC disable_apic =1 ;
Signature · 1 line
1.8.4.5
PATCH v3 6/8 x86, boot, PCI: Convert SETUP_PCI data to list
In reply to Yinghai LuSo we could avoid ioremap every time later.
--- arch/x86/include/asm/pci.h | 2 ++ arch/x86/kernel/setup.c | 1 + arch/x86/pci/common.c | 77 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 65 insertions(+), 15 deletions(-)
arch/x86/include/asm/pci.h +2 -0
@@ -88,9 +88,11 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, *strategy_parameter = ~0UL; }void add_pci (u64 pa_data); +int fill_setup_pci_entries (void );#else static inline void early_quirks (void ) { }static inline void add_pci (u64 pa_data) { } +static inline int fill_setup_pci_entries (void ) { }#endif extern void pci_iommu_alloc (void );
arch/x86/kernel/setup.c +1 -0
@@ -1195,6 +1195,7 @@ void __init setup_arch(char **cmdline_p)acpi_boot_init ();sfi_init ();x86_dtb_init (); +fill_setup_pci_entries ();/* * get boot-time SMP configuration:
arch/x86/pci/common.c +62 -15
105 lines not on this page · raw message
Signature · 1 line
1.8.4.5
PATCH v3 7/8 x86, boot, PCI: Copy SETUP_PCI rom to kernel space
In reply to Yinghai LuAs EFI stub code could put them high when on 32bit or with exactmap= on 64bit conf.
Check if the range is mapped, otherwise allocate new one and have the rom data copied. So we could access them directly.
--- arch/x86/pci/common.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)
arch/x86/pci/common.c +45 -2
@@ -697,6 +697,48 @@ struct firmware_setup_pci_entry {static LIST_HEAD (setup_pci_entries); +static phys_addr_t check_copy (phys_addr_t start,unsigned long size) +{ +unsigned long start_pfn =PFN_DOWN (start); +unsigned long end_pfn =PFN_UP (start + size); +unsigned char *p, *q; +phys_addr_t pa_p, pa_q; +long sz = size; + +if (pfn_range_is_mapped (start_pfn, end_pfn)) +return start; + +/* allocate and copy */ + pa_p =memblock_alloc (size,PAGE_SIZE ); +if (!pa_p) +return start; + + p =phys_to_virt (pa_p); + + pa_q = start; +while (sz >0 ) { +long chunk_size =64 <<10 ; + +if (chunk_size > sz) + chunk_size = sz; + + q =early_memremap (pa_q, chunk_size); +if (!q) { +memblock_free (pa_p, size); +return start; + } +memcpy (p, q, chunk_size); +early_memunmap (q, chunk_size); + p += chunk_size; + pa_q += chunk_size; + sz -= chunk_size; + } + +memblock_free (start, size); + +return pa_p; +} +int __init fill_setup_pci_entries (void ) {struct setup_data *data;
@@ -726,8 +768,9 @@ int __init fill_setup_pci_entries(void) entry->vendor = rom->vendor; entry->devid = rom->devid; entry->pcilen = rom->pcilen; - entry->romdata = pa_data + - offsetof(struct pci_setup_rom , romdata); + entry->romdata =check_copy (pa_data + + offsetof(struct pci_setup_rom , romdata), + rom->pcilen);list_add (&entry->list, &setup_pci_entries);
Signature · 1 line
1.8.4.5
PATCH v3 8/8 x86, boot, PCI: Export SETUP_PCI data via sysfs
In reply to Yinghai LuSo we could let kexec-tools to rebuild SETUP_PCI and pass it to second kernel if needed.
Now kexec-tools already build SETUP_EFI and SETUP_E820EXT.
--- arch/x86/pci/common.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+)
arch/x86/pci/common.c +175 -0
@@ -685,6 +685,8 @@ void __init add_pci(u64 pa_data)struct firmware_setup_pci_entry {struct list_head list; +struct kobject kobj; +struct bin_attribute *rom_attr;uint16_t vendor;uint16_t devid;uint64_t pcilen;
@@ -806,6 +808,179 @@ int pcibios_add_device(struct pci_dev *dev)return 0 ; } +#ifdef CONFIG_SYSFS +static inline struct firmware_setup_pci_entry * +to_setup_pci_entry (struct kobject *kobj) +{ + return container_of(kobj, struct firmware_setup_pci_entry, kobj); +} + +static ssize_t vendor_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%04llx\n" , + (unsigned long long )entry->vendor); +} + +static ssize_t devid_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%04llx\n" , + (unsigned long long )entry->devid); +} + +static ssize_t pcilen_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%llx\n" , + (unsigned long long )entry->pcilen); +} + +static ssize_t segment_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%04llx\n" , + (unsigned long long )entry->segment); +} + +static ssize_t bus_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%02llx\n" , + (unsigned long long )entry->bus); +} + +static ssize_t device_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%02llx\n" , + (unsigned long long )entry->device); +} + +static ssize_t function_show (struct firmware_setup_pci_entry *entry,char *buf) +{ +return snprintf (buf,PAGE_SIZE ,"0x%1llx\n" , + (unsigned long long )entry->function); +} + +struct setup_pci_attribute { +struct attribute attr; +ssize_t (*show)(struct firmware_setup_pci_entry *entry,char *buf); +}; + +static inline struct setup_pci_attribute *to_setup_pci_attr ( +struct attribute *attr) +{ + return container_of(attr, struct setup_pci_attribute, attr); +} + +static ssize_t setup_pci_attr_show (struct kobject *kobj, +struct attribute *attr,char *buf) +{ +struct firmware_setup_pci_entry *entry =to_setup_pci_entry (kobj); +struct setup_pci_attribute *setup_pci_attr =to_setup_pci_attr (attr); + +return setup_pci_attr->show (entry, buf); +} + +static struct setup_pci_attribute setup_pci_vendor_attr =__ATTR_RO (vendor); +static struct setup_pci_attribute setup_pci_devid_attr =__ATTR_RO (devid); +static struct setup_pci_attribute setup_pci_pcilen_attr =__ATTR_RO (pcilen); +static struct setup_pci_attribute setup_pci_segment_attr =__ATTR_RO (segment); +static struct setup_pci_attribute setup_pci_bus_attr =__ATTR_RO (bus); +static struct setup_pci_attribute setup_pci_device_attr =__ATTR_RO (device); +static struct setup_pci_attribute setup_pci_function_attr =__ATTR_RO (function); + +/* +* These are default attributes that are added for every memmap entry. +*/ +static struct attribute *def_attrs[] = { + &setup_pci_vendor_attr.attr, + &setup_pci_devid_attr.attr, + &setup_pci_pcilen_attr.attr, + &setup_pci_segment_attr.attr, + &setup_pci_bus_attr.attr, + &setup_pci_device_attr.attr, + &setup_pci_function_attr.attr, +NULL +}; + +static const struct sysfs_ops setup_pci_attr_ops = { + .show = setup_pci_attr_show, +}; + +static struct kobj_type __refdata setup_pci_ktype = { + .sysfs_ops = &setup_pci_attr_ops, + .default_attrs = def_attrs, +}; + +static ssize_t setup_pci_rom_read (struct file *filp,struct kobject *kobj, +struct bin_attribute *bin_attr,char *buf, +loff_t off,size_t count) +{ +struct firmware_setup_pci_entry *entry =to_setup_pci_entry (kobj); + +if (off >= entry->pcilen) + count =0 ; +else { +unsigned char *rom =phys_to_virt (entry->romdata); + +if (off + count > entry->pcilen) + count = entry->pcilen - off; + +memcpy (buf, rom + off, count); + } + +return count; +} + +static int __init add_sysfs_fw_setup_pci_entry ( +struct firmware_setup_pci_entry *entry) +{ +int retval =0 ; +static int setup_pci_entries_nr; +static struct kset *setup_pci_kset; +struct bin_attribute *attr; + +kobject_init (&entry->kobj, &setup_pci_ktype); + +if (!setup_pci_kset) { + setup_pci_kset =kset_create_and_add ("setup_pci" ,NULL , + firmware_kobj); +if (!setup_pci_kset) +return -ENOMEM ; + } + + entry->kobj.kset = setup_pci_kset; + retval =kobject_add (&entry->kobj,NULL ,"%d" , setup_pci_entries_nr++); +if (retval) { +kobject_put (&entry->kobj); +return retval; + } + + attr =kzalloc (sizeof (*attr),GFP_ATOMIC ); +if (!attr) +return -ENOMEM ; + +sysfs_bin_attr_init (attr); + attr->size = entry->pcilen; + attr->attr.name ="rom" ; + attr->attr.mode =S_IRUSR ; + attr->read = setup_pci_rom_read; + retval =sysfs_create_bin_file (&entry->kobj, attr); +if (retval) +kfree (attr); + entry->rom_attr = attr; + +return retval; +} + +static int __init firmware_setup_pci_init (void ) +{ +struct firmware_setup_pci_entry *entry; + +list_for_each_entry (entry, &setup_pci_entries, list) +add_sysfs_fw_setup_pci_entry (entry); + +return 0 ; +} +late_initcall (firmware_setup_pci_init); +#endif +int pcibios_enable_device (struct pci_dev *dev,int mask) {int err;
Signature · 1 line
1.8.4.5