* [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 1:59 ` David Rientjes
2015-03-08 0:56 ` [PATCH v3 2/8] x86, efi: Copy SETUP_EFI data and access directly Yinghai Lu
` (6 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu, stable
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
Reported-by: "Lee, Chun-Yi" <jlee@suse.com>
Tested-by: "Lee, Chun-Yi" <jlee@suse.com>
Cc: "Lee, Chun-Yi" <jlee@suse.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: stable@vger.kernel.org
---
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(-)
diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h
index d993e33..edc8a71 100644
--- a/arch/x86/include/uapi/asm/e820.h
+++ b/arch/x86/include/uapi/asm/e820.h
@@ -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 {
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 46201de..2a6bed9 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -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);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 912f124..aed343b 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -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))
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 91a4496..3c2752a 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -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);
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index c30efb6..63520ec 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -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;
}
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
2015-03-08 0:56 ` [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN Yinghai Lu
@ 2015-03-08 1:59 ` David Rientjes
2015-03-08 6:51 ` Yinghai Lu
2015-03-09 0:18 ` joeyli
0 siblings, 2 replies; 12+ messages in thread
From: David Rientjes @ 2015-03-08 1:59 UTC (permalink / raw)
To: Yinghai Lu
Cc: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas, Thomas Gleixner, Jiri Kosina, Chun-Yi Lee,
linux-kernel, linux-efi, linux-pci, stable
On Sat, 7 Mar 2015, Yinghai Lu wrote:
> 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
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.
> Reported-by: "Lee, Chun-Yi" <jlee@suse.com>
> Tested-by: "Lee, Chun-Yi" <jlee@suse.com>
> Cc: "Lee, Chun-Yi" <jlee@suse.com>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: stable@vger.kernel.org
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?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
2015-03-08 1:59 ` David Rientjes
@ 2015-03-08 6:51 ` Yinghai Lu
2015-03-09 0:18 ` joeyli
1 sibling, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 6:51 UTC (permalink / raw)
To: David Rientjes
Cc: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas, Thomas Gleixner, Jiri Kosina, Chun-Yi Lee,
Linux Kernel Mailing List, linux-efi@vger.kernel.org,
linux-pci@vger.kernel.org, stable@vger.kernel.org
On Sat, Mar 7, 2015 at 5:59 PM, David Rientjes <rientjes@google.com> wrote:
>
> 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?
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
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN
2015-03-08 1:59 ` David Rientjes
2015-03-08 6:51 ` Yinghai Lu
@ 2015-03-09 0:18 ` joeyli
1 sibling, 0 replies; 12+ messages in thread
From: joeyli @ 2015-03-09 0:18 UTC (permalink / raw)
To: David Rientjes
Cc: Yinghai Lu, Matt Fleming, H. Peter Anvin, Ingo Molnar,
Borislav Petkov, Bjorn Helgaas, Thomas Gleixner, Jiri Kosina,
linux-kernel, linux-efi, linux-pci, stable
On Sat, Mar 07, 2015 at 05:59:14PM -0800, David Rientjes wrote:
> On Sat, 7 Mar 2015, Yinghai Lu wrote:
>
> > 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
>
> 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.
>
> > Reported-by: "Lee, Chun-Yi" <jlee@suse.com>
> > Tested-by: "Lee, Chun-Yi" <jlee@suse.com>
> > Cc: "Lee, Chun-Yi" <jlee@suse.com>
> > Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> > Cc: stable@vger.kernel.org
>
> 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?
Thanks a lot!
Joey Lee
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 2/8] x86, efi: Copy SETUP_EFI data and access directly
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 3/8] x86, of: Let add_dtb reserve setup_data locally Yinghai Lu
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu
The copy will be in __initdata, and it is small.
We can use pointer to access the setup_data instead of using early_memmap
everywhere.
Cc: Matt Fleming <matt.fleming@intel.com>
Cc: linux-efi@vger.kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
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(-)
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 25bce45..edbecd6 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -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
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index dbc8627..1cd38e8 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -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");
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 17e80d8..a541c6c 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -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)
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 1c7380d..45fec7d 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -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)
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 3/8] x86, of: Let add_dtb reserve setup_data locally
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 1/8] x86: Kill E820_RESERVED_KERN Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 2/8] x86, efi: Copy SETUP_EFI data and access directly Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 4/8] x86, boot: Add add_pci handler for SETUP_PCI Yinghai Lu
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu, Rob Herring, David Vrabel
We 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.
Cc: Rob Herring <robh@kernel.org>
Cc: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/include/asm/prom.h | 9 ++++++---
arch/x86/kernel/devicetree.c | 43 +++++++++++++++++++++++++------------------
2 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index 1d081ac..fb716eddc 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -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__ */
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 3d35033..55cf76a 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -2,6 +2,7 @@
* Architecture specific OF callbacks.
*/
#include <linux/bootmem.h>
+#include <linux/memblock.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
@@ -23,7 +24,6 @@
#include <asm/setup.h>
#include <asm/i8259.h>
-__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
int __initdata of_ioapic;
@@ -43,11 +43,27 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
}
+#ifdef CONFIG_OF_FLATTREE
+static u64 initial_dtb __initdata;
+static u32 initial_dtb_size __initdata;
void __init add_dtb(u64 data)
{
+ u32 map_len;
+
initial_dtb = data + offsetof(struct setup_data, data);
-}
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
+ initial_boot_params = early_memremap(initial_dtb, map_len);
+ if (!initial_boot_params) {
+ initial_dtb = 0;
+ return;
+ }
+ initial_dtb_size = of_get_flat_dt_size();
+ early_memunmap(initial_boot_params, map_len);
+ initial_boot_params = NULL;
+ memblock_reserve(initial_dtb, initial_dtb_size);
+}
+#endif
/*
* CE4100 ids. Will be moved to machine_device_initcall() once we have it.
*/
@@ -272,31 +288,22 @@ static void __init dtb_apic_setup(void)
dtb_ioapic_setup();
}
-#ifdef CONFIG_OF_FLATTREE
static void __init x86_flattree_get_config(void)
{
- u32 size, map_len;
+#ifdef CONFIG_OF_FLATTREE
void *dt;
if (!initial_dtb)
return;
- map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
-
- initial_boot_params = dt = early_memremap(initial_dtb, map_len);
- size = of_get_flat_dt_size();
- if (map_len < size) {
- early_iounmap(dt, map_len);
- initial_boot_params = dt = early_memremap(initial_dtb, size);
- map_len = size;
- }
-
+ initial_boot_params = dt = early_memremap(initial_dtb,
+ initial_dtb_size);
unflatten_and_copy_device_tree();
- early_iounmap(dt, map_len);
-}
-#else
-static inline void x86_flattree_get_config(void) { }
+ early_memunmap(dt, initial_dtb_size);
+
+ memblock_free(initial_dtb, initial_dtb_size);
#endif
+}
void __init x86_dtb_init(void)
{
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 4/8] x86, boot: Add add_pci handler for SETUP_PCI
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
` (2 preceding siblings ...)
2015-03-08 0:56 ` [PATCH v3 3/8] x86, of: Let add_dtb reserve setup_data locally Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 5/8] x86: Kill not used setup_data handling code Yinghai Lu
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu
Let 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.
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Matt Fleming <matt.fleming@intel.com>
Cc: linux-pci@vger.kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
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(-)
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 4e370a5..7fbd5f3 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -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);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index aed343b..94f95e0 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -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)
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 3d2612b..f40df5c 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -9,6 +9,7 @@
#include <linux/pci-acpi.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/memblock.h>
#include <linux/dmi.h>
#include <linux/slab.h>
@@ -667,31 +668,47 @@ unsigned int pcibios_assign_all_busses(void)
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
}
+static u64 pci_setup_data;
+void __init add_pci(u64 pa_data)
+{
+ struct setup_data *data;
+
+ data = early_memremap(pa_data, sizeof(*data));
+ if (!data)
+ return;
+
+ memblock_reserve(pa_data, sizeof(*data) + data->len);
+ data->next = pci_setup_data;
+ pci_setup_data = pa_data;
+ early_memunmap(data, sizeof(*data));
+}
+
int pcibios_add_device(struct pci_dev *dev)
{
struct setup_data *data;
struct pci_setup_rom *rom;
u64 pa_data;
- pa_data = boot_params.hdr.setup_data;
+ pa_data = pci_setup_data;
while (pa_data) {
data = ioremap(pa_data, sizeof(*rom));
if (!data)
return -ENOMEM;
- if (data->type == SETUP_PCI) {
- rom = (struct pci_setup_rom *)data;
-
- if ((pci_domain_nr(dev->bus) == rom->segment) &&
- (dev->bus->number == rom->bus) &&
- (PCI_SLOT(dev->devfn) == rom->device) &&
- (PCI_FUNC(dev->devfn) == rom->function) &&
- (dev->vendor == rom->vendor) &&
- (dev->device == rom->devid)) {
- dev->rom = pa_data +
- offsetof(struct pci_setup_rom, romdata);
- dev->romlen = rom->pcilen;
- }
+ rom = (struct pci_setup_rom *)data;
+
+ if ((pci_domain_nr(dev->bus) == rom->segment) &&
+ (dev->bus->number == rom->bus) &&
+ (PCI_SLOT(dev->devfn) == rom->device) &&
+ (PCI_FUNC(dev->devfn) == rom->function) &&
+ (dev->vendor == rom->vendor) &&
+ (dev->device == rom->devid)) {
+ dev->rom = pa_data +
+ offsetof(struct pci_setup_rom, romdata);
+ dev->romlen = rom->pcilen;
+ dev_printk(KERN_DEBUG, &dev->dev, "set rom to [%#010lx, %#010lx] via SETUP_PCI\n",
+ (unsigned long)dev->rom,
+ (unsigned long)(dev->rom + dev->romlen - 1));
}
pa_data = data->next;
iounmap(data);
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 5/8] x86: Kill not used setup_data handling code
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
` (3 preceding siblings ...)
2015-03-08 0:56 ` [PATCH v3 4/8] x86, boot: Add add_pci handler for SETUP_PCI Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 6/8] x86, boot, PCI: Convert SETUP_PCI data to list Yinghai Lu
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu
Cc: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/kernel/kdebugfs.c | 142 ---------------------------------------------
arch/x86/kernel/setup.c | 17 ------
2 files changed, 159 deletions(-)
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index dc1404b..c8ca86c 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -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:
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 94f95e0..a7e688c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -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;
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 6/8] x86, boot, PCI: Convert SETUP_PCI data to list
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
` (4 preceding siblings ...)
2015-03-08 0:56 ` [PATCH v3 5/8] x86: Kill not used setup_data handling code Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 7/8] x86, boot, PCI: Copy SETUP_PCI rom to kernel space Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 8/8] x86, boot, PCI: Export SETUP_PCI data via sysfs Yinghai Lu
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu
So we could avoid ioremap every time later.
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
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(-)
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 7fbd5f3..99b261f 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -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);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index a7e688c..39940a7 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -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:
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index f40df5c..67dc2a9 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -668,7 +668,7 @@ unsigned int pcibios_assign_all_busses(void)
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
}
-static u64 pci_setup_data;
+static u64 pci_setup_data __initdata;
void __init add_pci(u64 pa_data)
{
struct setup_data *data;
@@ -683,36 +683,83 @@ void __init add_pci(u64 pa_data)
early_memunmap(data, sizeof(*data));
}
-int pcibios_add_device(struct pci_dev *dev)
+struct firmware_setup_pci_entry {
+ struct list_head list;
+ uint16_t vendor;
+ uint16_t devid;
+ uint64_t pcilen;
+ unsigned long segment;
+ unsigned long bus;
+ unsigned long device;
+ unsigned long function;
+ phys_addr_t romdata;
+};
+
+static LIST_HEAD(setup_pci_entries);
+
+int __init fill_setup_pci_entries(void)
{
struct setup_data *data;
struct pci_setup_rom *rom;
+ struct firmware_setup_pci_entry *entry;
+ phys_addr_t pa_entry;
u64 pa_data;
pa_data = pci_setup_data;
while (pa_data) {
- data = ioremap(pa_data, sizeof(*rom));
+ data = early_memremap(pa_data, sizeof(*rom));
if (!data)
return -ENOMEM;
-
rom = (struct pci_setup_rom *)data;
- if ((pci_domain_nr(dev->bus) == rom->segment) &&
- (dev->bus->number == rom->bus) &&
- (PCI_SLOT(dev->devfn) == rom->device) &&
- (PCI_FUNC(dev->devfn) == rom->function) &&
- (dev->vendor == rom->vendor) &&
- (dev->device == rom->devid)) {
- dev->rom = pa_data +
- offsetof(struct pci_setup_rom, romdata);
- dev->romlen = rom->pcilen;
+ pa_entry = memblock_alloc(sizeof(*entry), sizeof(long));
+ if (!pa_entry) {
+ early_memunmap(data, sizeof(*rom));
+ return -ENOMEM;
+ }
+
+ entry = phys_to_virt(pa_entry);
+ entry->segment = rom->segment;
+ entry->bus = rom->bus;
+ entry->device = rom->device;
+ entry->function = rom->function;
+ entry->vendor = rom->vendor;
+ entry->devid = rom->devid;
+ entry->pcilen = rom->pcilen;
+ entry->romdata = pa_data +
+ offsetof(struct pci_setup_rom, romdata);
+
+ list_add(&entry->list, &setup_pci_entries);
+
+ memblock_free(pa_data, sizeof(*rom));
+ pa_data = data->next;
+ early_memunmap(data, sizeof(*rom));
+ }
+
+ pci_setup_data = 0;
+
+ return 0;
+}
+
+int pcibios_add_device(struct pci_dev *dev)
+{
+ struct firmware_setup_pci_entry *entry;
+
+ list_for_each_entry(entry, &setup_pci_entries, list) {
+ if ((pci_domain_nr(dev->bus) == entry->segment) &&
+ (dev->bus->number == entry->bus) &&
+ (PCI_SLOT(dev->devfn) == entry->device) &&
+ (PCI_FUNC(dev->devfn) == entry->function) &&
+ (dev->vendor == entry->vendor) &&
+ (dev->device == entry->devid)) {
+ dev->rom = entry->romdata;
+ dev->romlen = entry->pcilen;
dev_printk(KERN_DEBUG, &dev->dev, "set rom to [%#010lx, %#010lx] via SETUP_PCI\n",
(unsigned long)dev->rom,
(unsigned long)(dev->rom + dev->romlen - 1));
}
- pa_data = data->next;
- iounmap(data);
}
+
return 0;
}
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 7/8] x86, boot, PCI: Copy SETUP_PCI rom to kernel space
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
` (5 preceding siblings ...)
2015-03-08 0:56 ` [PATCH v3 6/8] x86, boot, PCI: Convert SETUP_PCI data to list Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
2015-03-08 0:56 ` [PATCH v3 8/8] x86, boot, PCI: Export SETUP_PCI data via sysfs Yinghai Lu
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu
As 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.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/common.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 67dc2a9..15e1b3f 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -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);
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v3 8/8] x86, boot, PCI: Export SETUP_PCI data via sysfs
2015-03-08 0:56 [PATCH v3 0/8] x86, boot: clean up setup_data handling Yinghai Lu
` (6 preceding siblings ...)
2015-03-08 0:56 ` [PATCH v3 7/8] x86, boot, PCI: Copy SETUP_PCI rom to kernel space Yinghai Lu
@ 2015-03-08 0:56 ` Yinghai Lu
7 siblings, 0 replies; 12+ messages in thread
From: Yinghai Lu @ 2015-03-08 0:56 UTC (permalink / raw)
To: Matt Fleming, H. Peter Anvin, Ingo Molnar, Borislav Petkov,
Bjorn Helgaas
Cc: Thomas Gleixner, Jiri Kosina, Chun-Yi Lee, linux-kernel,
linux-efi, linux-pci, Yinghai Lu
So 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.
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
arch/x86/pci/common.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 175 insertions(+)
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 15e1b3f..502e707 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -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;
--
1.8.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread