[U-Boot] [PATCH v3 0/7] x86: Add MP table support to QEMU

This patch series mainly add MP support to QEMU as well as some other necessary fixes for x86.
Verified by booting Linux kernel on QEMU i440FX and Q35, and make sure I/O APIC interrupt is being used by the kernel with the help of MP table provided by U-Boot.
This series is the prerequisite for the follow-up ACPI support which is currently being worked on by Saket.
It seems that QEMU multicore emulation is sort of random, as the mp_init() does not realibly succeed on different machines with previous patch, this v2 does not include that patch, instead it just enabled MP table with UP mode.
Changes in v3: - Remove the call to device_probe() - Add a comment to explain why return value is not checked
Changes in v2: - Drop patches that are already applied - Add a TODO comment above mp_determine_pci_dstirq() - New patch to allow cpu-x86 driver to be probed for UP - Drop QEMU mp_init patch - Change /cpus node to include just one cpu - New patch to reserve PCIe ECAM address range in the E820 table
Bin Meng (7): x86: mpspec: Allow platform to determine how PIRQ is connected to I/O APIC x86: mpspec: Move writing ISA interrupt entry after PCI x86: qemu: Enable I/O APIC chip select on PIIX3 x86: Allow cpu-x86 driver to be probed for UP x86: qemu: Enable writing MP table x86: qemu: Turn on PCIe ECAM address range decoding on Q35 x86: Reserve PCIe ECAM address range in the E820 table
arch/x86/Kconfig | 10 +++++++ arch/x86/cpu/cpu.c | 9 +++++++ arch/x86/cpu/qemu/pci.c | 45 ++++++++++++++++++++++++++++--- arch/x86/dts/qemu-x86_i440fx.dts | 12 +++++++++ arch/x86/dts/qemu-x86_q35.dts | 12 +++++++++ arch/x86/include/asm/arch-qemu/qemu.h | 10 ++++++- arch/x86/include/asm/mpspec.h | 17 ++++++++++++ arch/x86/lib/fsp/fsp_dram.c | 6 +++++ arch/x86/lib/mpspec.c | 50 ++++++++++++++++++++++++++--------- arch/x86/lib/zimage.c | 5 +++- configs/qemu-x86_defconfig | 3 +++ 11 files changed, 161 insertions(+), 18 deletions(-)

Currently during writing MP table I/O interrupt assignment entry, we assume the PIRQ is directly mapped to I/O APIC INTPIN#16-23, which however is not always the case on some platforms.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v3: None Changes in v2: - Drop patches that are already applied - Add a TODO comment above mp_determine_pci_dstirq()
arch/x86/include/asm/mpspec.h | 17 +++++++++++++++++ arch/x86/lib/mpspec.c | 24 +++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index efa9231..ad8eba9 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -432,6 +432,23 @@ void mp_write_compat_address_space(struct mp_config_table *mc, int busid, u32 mptable_finalize(struct mp_config_table *mc);
/** + * mp_determine_pci_dstirq() - Determine PCI device's int pin on the I/O APIC + * + * This determines a PCI device's interrupt pin number on the I/O APIC. + * + * This can be implemented by platform codes to handle specifal cases, which + * do not conform to the normal chipset/board design where PIRQ[A-H] are mapped + * directly to I/O APIC INTPIN#16-23. + * + * @bus: bus number of the pci device + * @dev: device number of the pci device + * @func: function number of the pci device + * @pirq: PIRQ number the PCI device's interrupt pin is routed to + * @return: interrupt pin number on the I/O APIC + */ +int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq); + +/** * write_mp_table() - Write MP table * * This writes MP table at a given address. diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c index f16fbcb..9b2a59b 100644 --- a/arch/x86/lib/mpspec.c +++ b/arch/x86/lib/mpspec.c @@ -269,6 +269,13 @@ static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base, return (i == entry_num) ? false : true; }
+/* TODO: move this to driver model */ +__weak int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) +{ + /* PIRQ[A-H] are connected to I/O APIC INTPIN#16-23 */ + return pirq + 16; +} + static int mptable_add_intsrc(struct mp_config_table *mc, int bus_isa, int apicid) { @@ -304,24 +311,27 @@ static int mptable_add_intsrc(struct mp_config_table *mc,
for (i = 0; i < count; i++) { struct pirq_routing pr; + int bus, dev, func; + int dstirq;
pr.bdf = fdt_addr_to_cpu(cell[0]); pr.pin = fdt_addr_to_cpu(cell[1]); pr.pirq = fdt_addr_to_cpu(cell[2]); + bus = PCI_BUS(pr.bdf); + dev = PCI_DEV(pr.bdf); + func = PCI_FUNC(pr.bdf);
if (check_dup_entry(intsrc_base, intsrc_entries, - PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) { + bus, dev, pr.pin)) { debug("found entry for bus %d device %d INT%c, skipping\n", - PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), - 'A' + pr.pin - 1); + bus, dev, 'A' + pr.pin - 1); cell += sizeof(struct pirq_routing) / sizeof(u32); continue; }
- /* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */ - mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf), - PCI_DEV(pr.bdf), pr.pin, apicid, - pr.pirq + 16); + dstirq = mp_determine_pci_dstirq(bus, dev, func, pr.pirq); + mp_write_pci_intsrc(mc, MP_INT, bus, dev, pr.pin, + apicid, dstirq); intsrc_entries++; cell += sizeof(struct pirq_routing) / sizeof(u32); }

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
Currently during writing MP table I/O interrupt assignment entry, we assume the PIRQ is directly mapped to I/O APIC INTPIN#16-23, which however is not always the case on some platforms.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2:
- Drop patches that are already applied
- Add a TODO comment above mp_determine_pci_dstirq()
arch/x86/include/asm/mpspec.h | 17 +++++++++++++++++ arch/x86/lib/mpspec.c | 24 +++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-)
Applied to u-boot-x86, thanks!

On some platforms the I/O APIC interrupt pin#0-15 may be connected to platform pci devices' interrupt pin. In such cases the legacy ISA IRQ is not available so we should not write ISA interrupt entry if it is already occupied.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/x86/lib/mpspec.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c index 9b2a59b..f3ad116 100644 --- a/arch/x86/lib/mpspec.c +++ b/arch/x86/lib/mpspec.c @@ -21,6 +21,8 @@
DECLARE_GLOBAL_DATA_PTR;
+static bool isa_irq_occupied[16]; + struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf) { u32 mc; @@ -243,10 +245,18 @@ static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, 0, apicid, 2);
- for (i = 3; i < 16; i++) + for (i = 3; i < 16; i++) { + /* + * Do not write ISA interrupt entry if it is already occupied + * by the platform devices. + */ + if (isa_irq_occupied[i]) + continue; + mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, i, apicid, i); + } }
/* @@ -287,10 +297,6 @@ static int mptable_add_intsrc(struct mp_config_table *mc, const u32 *cell; int i;
- /* Legacy Interrupts */ - debug("Writing ISA IRQs\n"); - mptable_add_isa_interrupts(mc, bus_isa, apicid, 0); - /* Get I/O interrupt information from device tree */ node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER); if (node < 0) { @@ -330,12 +336,22 @@ static int mptable_add_intsrc(struct mp_config_table *mc, }
dstirq = mp_determine_pci_dstirq(bus, dev, func, pr.pirq); + /* + * For PIRQ which is connected to I/O APIC interrupt pin#0-15, + * mark it as occupied so that we can skip it later. + */ + if (dstirq < 16) + isa_irq_occupied[dstirq] = true; mp_write_pci_intsrc(mc, MP_INT, bus, dev, pr.pin, apicid, dstirq); intsrc_entries++; cell += sizeof(struct pirq_routing) / sizeof(u32); }
+ /* Legacy Interrupts */ + debug("Writing ISA IRQs\n"); + mptable_add_isa_interrupts(mc, bus_isa, apicid, 0); + return 0; }

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
On some platforms the I/O APIC interrupt pin#0-15 may be connected to platform pci devices' interrupt pin. In such cases the legacy ISA IRQ is not available so we should not write ISA interrupt entry if it is already occupied.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2: None
arch/x86/lib/mpspec.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
Applied to u-boot-x86, thanks!

The PIIX3 chipset does not integrate an I/O APIC, instead it supports connecting to an external I/O APIC which needs to be enabled manually.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v3: None Changes in v2: None
arch/x86/cpu/qemu/pci.c | 7 ++++++- arch/x86/include/asm/arch-qemu/qemu.h | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/qemu/pci.c b/arch/x86/cpu/qemu/pci.c index 1a9140b..ab93e76 100644 --- a/arch/x86/cpu/qemu/pci.c +++ b/arch/x86/cpu/qemu/pci.c @@ -50,7 +50,7 @@ void board_pci_setup_hose(struct pci_controller *hose) int board_pci_post_scan(struct pci_controller *hose) { int ret = 0; - u16 device; + u16 device, xbcs; int pam, i; pci_dev_t vga; ulong start; @@ -82,6 +82,11 @@ int board_pci_post_scan(struct pci_controller *hose) */ x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); + + /* Enable I/O APIC */ + xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); + xbcs |= APIC_EN; + x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); }
/* diff --git a/arch/x86/include/asm/arch-qemu/qemu.h b/arch/x86/include/asm/arch-qemu/qemu.h index 5cbffff..8c8e4ac 100644 --- a/arch/x86/include/asm/arch-qemu/qemu.h +++ b/arch/x86/include/asm/arch-qemu/qemu.h @@ -13,10 +13,14 @@ #define PAM_NUM 7 #define PAM_RW 0x33
+/* X-Bus Chip Select Register */ +#define XBCS 0x4e +#define APIC_EN (1 << 8) + /* IDE Timing Register */ #define IDE0_TIM 0x40 #define IDE1_TIM 0x42 -#define IDE_DECODE_EN 0x8000 +#define IDE_DECODE_EN (1 << 15)
/* I/O Ports */ #define CMOS_ADDR_PORT 0x70

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
The PIIX3 chipset does not integrate an I/O APIC, instead it supports connecting to an external I/O APIC which needs to be enabled manually.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2: None
arch/x86/cpu/qemu/pci.c | 7 ++++++- arch/x86/include/asm/arch-qemu/qemu.h | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-)
Applied to u-boot-x86, thanks!

Currently cpu-x86 driver is probed only for SMP. We add the same support for UP when there is only one cpu node in the deive tree.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v3: - Remove the call to device_probe() - Add a comment to explain why return value is not checked
Changes in v2: - New patch to allow cpu-x86 driver to be probed for UP
arch/x86/cpu/cpu.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index b4e0fd9..b9134cf 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -696,6 +696,15 @@ __weak int x86_init_cpus(void) #ifdef CONFIG_SMP debug("Init additional CPUs\n"); x86_mp_init(); +#else + struct udevice *dev; + + /* + * This causes the cpu-x86 driver to be probed. + * We don't check return value here as we want to allow boards + * which have not been converted to use cpu uclass driver to boot. + */ + uclass_first_device(UCLASS_CPU, &dev); #endif
return 0;

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
Currently cpu-x86 driver is probed only for SMP. We add the same support for UP when there is only one cpu node in the deive tree.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v3:
- Remove the call to device_probe()
- Add a comment to explain why return value is not checked
Changes in v2:
- New patch to allow cpu-x86 driver to be probed for UP
arch/x86/cpu/cpu.c | 9 +++++++++ 1 file changed, 9 insertions(+)
Acked-by: Simon Glass sjg@chromium.org

On 22 July 2015 at 07:22, Simon Glass sjg@chromium.org wrote:
On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
Currently cpu-x86 driver is probed only for SMP. We add the same support for UP when there is only one cpu node in the deive tree.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v3:
- Remove the call to device_probe()
- Add a comment to explain why return value is not checked
Changes in v2:
- New patch to allow cpu-x86 driver to be probed for UP
arch/x86/cpu/cpu.c | 9 +++++++++ 1 file changed, 9 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot-x86, thanks!

Enable writing MP table for QEMU boads (i440fx and q35).
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v3: None Changes in v2: - Drop QEMU mp_init patch - Change /cpus node to include just one cpu
arch/x86/cpu/qemu/pci.c | 34 +++++++++++++++++++++++++++++++--- arch/x86/dts/qemu-x86_i440fx.dts | 12 ++++++++++++ arch/x86/dts/qemu-x86_q35.dts | 12 ++++++++++++ configs/qemu-x86_defconfig | 3 +++ 4 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/arch/x86/cpu/qemu/pci.c b/arch/x86/cpu/qemu/pci.c index ab93e76..acbd922 100644 --- a/arch/x86/cpu/qemu/pci.c +++ b/arch/x86/cpu/qemu/pci.c @@ -13,6 +13,8 @@
DECLARE_GLOBAL_DATA_PTR;
+static bool i440fx; + void board_pci_setup_hose(struct pci_controller *hose) { hose->first_busno = 0; @@ -61,7 +63,8 @@ int board_pci_post_scan(struct pci_controller *hose) * PCI device ID. */ device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID); - pam = (device == PCI_DEVICE_ID_INTEL_82441) ? I440FX_PAM : Q35_PAM; + i440fx = (device == PCI_DEVICE_ID_INTEL_82441); + pam = i440fx ? I440FX_PAM : Q35_PAM;
/* * Initialize Programmable Attribute Map (PAM) Registers @@ -71,7 +74,7 @@ int board_pci_post_scan(struct pci_controller *hose) for (i = 0; i < PAM_NUM; i++) x86_pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
- if (device == PCI_DEVICE_ID_INTEL_82441) { + if (i440fx) { /* * Enable legacy IDE I/O ports decode * @@ -97,10 +100,35 @@ int board_pci_post_scan(struct pci_controller *hose) * board, it shows as device 2, while for Q35 and ICH9 chipset board, * it shows as device 1. */ - vga = (device == PCI_DEVICE_ID_INTEL_82441) ? I440FX_VGA : Q35_VGA; + vga = i440fx ? I440FX_VGA : Q35_VGA; start = get_timer(0); ret = pci_run_vga_bios(vga, NULL, PCI_ROM_USE_NATIVE); debug("BIOS ran in %lums\n", get_timer(start));
return ret; } + +#ifdef CONFIG_GENERATE_MP_TABLE +int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) +{ + u8 irq; + + if (i440fx) { + /* + * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not + * connected to I/O APIC INTPIN#16-19. Instead they are routed + * to an irq number controled by the PIRQ routing register. + */ + irq = x86_pci_read_config8(PCI_BDF(bus, dev, func), + PCI_INTERRUPT_LINE); + } else { + /* + * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7. + * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11]. + */ + irq = pirq < 8 ? pirq + 16 : pirq + 12; + } + + return irq; +} +#endif diff --git a/arch/x86/dts/qemu-x86_i440fx.dts b/arch/x86/dts/qemu-x86_i440fx.dts index 0c522c8..c26c71b 100644 --- a/arch/x86/dts/qemu-x86_i440fx.dts +++ b/arch/x86/dts/qemu-x86_i440fx.dts @@ -24,6 +24,18 @@ stdout-path = "/serial"; };
+ cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "cpu-x86"; + reg = <0>; + intel,apic-id = <0>; + }; + }; + pci { compatible = "pci-x86"; #address-cells = <3>; diff --git a/arch/x86/dts/qemu-x86_q35.dts b/arch/x86/dts/qemu-x86_q35.dts index 5fbabc2..2e785fa 100644 --- a/arch/x86/dts/qemu-x86_q35.dts +++ b/arch/x86/dts/qemu-x86_q35.dts @@ -35,6 +35,18 @@ stdout-path = "/serial"; };
+ cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "cpu-x86"; + reg = <0>; + intel,apic-id = <0>; + }; + }; + pci { compatible = "pci-x86"; #address-cells = <3>; diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index a4c20bd..4b18d51 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -1,6 +1,8 @@ CONFIG_X86=y CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx" CONFIG_GENERATE_PIRQ_TABLE=y +CONFIG_GENERATE_MP_TABLE=y +CONFIG_CMD_CPU=y # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set @@ -9,6 +11,7 @@ CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_CONTROL=y +CONFIG_CPU=y CONFIG_SPI_FLASH=y CONFIG_VIDEO_VESA=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
Enable writing MP table for QEMU boads (i440fx and q35).
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2:
- Drop QEMU mp_init patch
- Change /cpus node to include just one cpu
arch/x86/cpu/qemu/pci.c | 34 +++++++++++++++++++++++++++++++--- arch/x86/dts/qemu-x86_i440fx.dts | 12 ++++++++++++ arch/x86/dts/qemu-x86_q35.dts | 12 ++++++++++++ configs/qemu-x86_defconfig | 3 +++ 4 files changed, 58 insertions(+), 3 deletions(-)
Applied to u-boot-x86, thanks!

Turn on PCIe ECAM address range decoding on Q35.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v3: None Changes in v2: None
arch/x86/cpu/qemu/pci.c | 4 ++++ arch/x86/include/asm/arch-qemu/qemu.h | 4 ++++ 2 files changed, 8 insertions(+)
diff --git a/arch/x86/cpu/qemu/pci.c b/arch/x86/cpu/qemu/pci.c index acbd922..2e94456 100644 --- a/arch/x86/cpu/qemu/pci.c +++ b/arch/x86/cpu/qemu/pci.c @@ -90,6 +90,10 @@ int board_pci_post_scan(struct pci_controller *hose) xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); xbcs |= APIC_EN; x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); + } else { + /* Configure PCIe ECAM base address */ + x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR, + CONFIG_PCIE_ECAM_BASE | BAR_EN); }
/* diff --git a/arch/x86/include/asm/arch-qemu/qemu.h b/arch/x86/include/asm/arch-qemu/qemu.h index 8c8e4ac..b67d342 100644 --- a/arch/x86/include/asm/arch-qemu/qemu.h +++ b/arch/x86/include/asm/arch-qemu/qemu.h @@ -22,6 +22,10 @@ #define IDE1_TIM 0x42 #define IDE_DECODE_EN (1 << 15)
+/* PCIe ECAM Base Address Register */ +#define PCIEX_BAR 0x60 +#define BAR_EN (1 << 0) + /* I/O Ports */ #define CMOS_ADDR_PORT 0x70 #define CMOS_DATA_PORT 0x71

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
Turn on PCIe ECAM address range decoding on Q35.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2: None
arch/x86/cpu/qemu/pci.c | 4 ++++ arch/x86/include/asm/arch-qemu/qemu.h | 4 ++++ 2 files changed, 8 insertions(+)
Applied to u-boot-x86, thanks!

We should mark PCIe ECAM address range in the E820 table as reserved otherwise kernel will not attempt to use ECAM.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
---
Changes in v3: None Changes in v2: - New patch to reserve PCIe ECAM address range in the E820 table
arch/x86/Kconfig | 10 ++++++++++ arch/x86/lib/fsp/fsp_dram.c | 6 ++++++ arch/x86/lib/zimage.c | 5 ++++- 3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cbbaa4f..e8968a7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -369,4 +369,14 @@ config PCIE_ECAM_BASE assigned to PCI devices - i.e. the memory and prefetch regions, as passed to pci_set_region().
+config PCIE_ECAM_SIZE + hex + default 0x10000000 + help + This is the size of memory-mapped address of PCI configuration space, + which is only available through the Enhanced Configuration Access + Mechanism (ECAM) with PCI Express. Each bus consumes 1 MiB memory, + so a default 0x10000000 size covers all of the 256 buses which is the + maximum number of PCI buses as defined by the PCI specification. + endmenu diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index 4c0a7c8..28552fa 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -77,5 +77,11 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) num_entries++; }
+ /* Mark PCIe ECAM address range as reserved */ + entries[num_entries].addr = CONFIG_PCIE_ECAM_BASE; + entries[num_entries].size = CONFIG_PCIE_ECAM_SIZE; + entries[num_entries].type = E820_RESERVED; + num_entries++; + return num_entries; } diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 144471c..a1ec57e 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -61,8 +61,11 @@ __weak unsigned install_e820_map(unsigned max_entries, entries[2].addr = ISA_END_ADDRESS; entries[2].size = gd->ram_size - ISA_END_ADDRESS; entries[2].type = E820_RAM; + entries[3].addr = CONFIG_PCIE_ECAM_BASE; + entries[3].size = CONFIG_PCIE_ECAM_SIZE; + entries[3].type = E820_RESERVED;
- return 3; + return 4; }
static void build_command_line(char *command_line, int auto_boot)

On 22 July 2015 at 02:21, Bin Meng bmeng.cn@gmail.com wrote:
We should mark PCIe ECAM address range in the E820 table as reserved otherwise kernel will not attempt to use ECAM.
Signed-off-by: Bin Meng bmeng.cn@gmail.com Acked-by: Simon Glass sjg@chromium.org
Changes in v3: None Changes in v2:
- New patch to reserve PCIe ECAM address range in the E820 table
arch/x86/Kconfig | 10 ++++++++++ arch/x86/lib/fsp/fsp_dram.c | 6 ++++++ arch/x86/lib/zimage.c | 5 ++++- 3 files changed, 20 insertions(+), 1 deletion(-)
Applied to u-boot-x86, thanks!
participants (2)
-
Bin Meng
-
Simon Glass