@@ -17,3 +17,4 @@ rombios32start.o
rombiosl.s
rombiosl.sym
rombiosl.txt
+mcfg.h
@@ -46,7 +46,7 @@ clean:
$(RM) *.o *.a *.s _rombios*_.c rombios*.txt rombios*.sym *.aml *.hex
$(RM) usage biossums rombios16.bin
$(RM) rombios32.bin rombios32.out
- $(RM) BIOS-bochs-latest BIOS-bochs-legacy
+ $(RM) BIOS-bochs-latest BIOS-bochs-legacy mcfg.h
dist-clean: clean
$(RM) Makefile
@@ -75,6 +75,9 @@ rombios16.bin: rombios.c apmbios.S biossums rombios.h makesym.perl
./biossums rombios16.bin
$(RM) _rombios_.s
+rombios.sym: rombios16.bin
+mcfg.h: rombios.sym
+ awk '/_mcfg_/{print "#define "toupper($$2)" ((uint32_t *)0x"$$1")"}' $< > $@
rombios32.bin: rombios32.out rombios.h
$(OBJCOPY) -O binary $< $@
@@ -83,7 +86,7 @@ rombios32.bin: rombios32.out rombios.h
rombios32.out: rombios32start.o rombios32.o rombios32.ld
$(LD) -o $@ -T $(SRC_PATH)/rombios32.ld rombios32start.o rombios32.o
-rombios32.o: rombios32.c acpi-dsdt.hex
+rombios32.o: rombios32.c acpi-dsdt.hex mcfg.h
$(GCC32) -O2 -Wall -I. -c -o $@ $<
acpi-dsdt.hex: acpi-dsdt.dsl
@@ -4488,6 +4488,13 @@ void set_e820_range(ES, DI, start, end, extra_start, extra_end, type)
write_word(ES, DI+18, 0x0);
}
+#if BX_ROMBIOS32
+extern Bit32u rombios32_mcfg_addr; /* addr: lsb 32 bit */
+extern Bit32u rombios32_extra_mcfg_addr; /* addr: msb 32 bit */
+extern Bit32u rombios32_mcfg_end; /* size: lsb 32b it */
+extern Bit32u rombios32_extra_mcfg_end; /* size: msb 32 bit */
+#endif
+
void
int15_function32(regs, ES, DS, FLAGS)
pushad_regs_t regs; // REGS pushed via pushad
@@ -4497,6 +4504,10 @@ int15_function32(regs, ES, DS, FLAGS)
Bit32u extra_lowbits_memory_size=0;
Bit16u CX,DX;
Bit32u extra_highbits_memory_size=0;
+ Bit32u mcfg_addr;
+ Bit32u extra_mcfg_addr;
+ Bit32u mcfg_end;
+ Bit32u extra_mcfg_end;
BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
@@ -4577,6 +4588,14 @@ ASM_END
extra_lowbits_memory_size *= 1024;
extra_highbits_memory_size = inb_cmos(0x5d);
+#if BX_ROMBIOS32
+ mcfg_addr = read_dword(0xf000, &rombios32_mcfg_addr);
+ extra_mcfg_addr = read_dword(0xf000,
+ &rombios32_extra_mcfg_addr);
+ mcfg_end = read_dword(0xf000, &rombios32_mcfg_end);
+ extra_mcfg_end = read_dword(0xf000,
+ &rombios32_extra_mcfg_end);
+#endif
switch(regs.u.r16.bx)
{
case 0:
@@ -4619,6 +4638,10 @@ ASM_END
0xfffc0000L, 0x00000000L ,0L, 0L, 2);
if (extra_highbits_memory_size || extra_lowbits_memory_size)
regs.u.r32.ebx = 6;
+#if BX_ROMBIOS32
+ else if (mcfg_end || extra_mcfg_end)
+ regs.u.r32.ebx = 7;
+#endif
else
regs.u.r32.ebx = 0;
break;
@@ -4627,8 +4650,25 @@ ASM_END
set_e820_range(ES, regs.u.r16.di, 0x00000000L,
extra_lowbits_memory_size, 1, extra_highbits_memory_size
+ 1, 1);
+#if BX_ROMBIOS32
+ if (mcfg_end || extra_mcfg_end)
+ regs.u.r32.ebx = 7;
+ else
+ regs.u.r32.ebx = 0;
+#else
+ regs.u.r32.ebx = 0;
+#endif
+ break;
+#if BX_ROMBIOS32
+ case 7:
+ /* MCFG reserved area */
+ set_e820_range(ES, regs.u.r16.di,
+ mcfg_addr, mcfg_end,
+ extra_mcfg_addr, extra_mcfg_end,
+ 2);
regs.u.r32.ebx = 0;
break;
+#endif
default: /* AX=E820, DX=534D4150, BX unrecognized */
goto int15_unimplemented;
break;
@@ -10364,6 +10404,14 @@ post_init_pic:
;; the following area can be used to write dynamically generated tables
.align 16
+_rombios32_mcfg_addr:
+ dd 0
+_rombios32_extra_mcfg_addr:
+ dd 0
+_rombios32_mcfg_end:
+ dd 0
+_rombios32_extra_mcfg_end:
+ dd 0
bios_table_area_start:
dd 0xaafb4442
dd bios_table_area_end - bios_table_area_start - 8;
@@ -32,6 +32,8 @@ typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
+#include "mcfg.h"
+
/* if true, put the MP float table and ACPI RSDT in EBDA and the MP
table in RAM. Unfortunately, Linux has bugs with that, so we prefer
to modify the BIOS in shadow RAM */
@@ -716,6 +718,7 @@ void smp_probe(void)
#define Q35_HOST_BRDIGE_SMRAM 0x9d
#define Q35_HOST_BRIDGE_PCIEXBAR 0x60
+#define Q35_HOST_BRIDGE_PCIEXBAR_SIZE (256 * 1024 * 1024)
#define Q35_HOST_BRIDGE_PCIEXBAR_ADDR 0xe0000000
#define Q35_HOST_BRIDGE_PCIEXBAREN ((uint64_t)1)
#define Q35_HOST_PCIE_PCI_SEGMENT 0
@@ -899,14 +902,34 @@ static void mch_bios_lock_shadow_ram(PCIDevice *d)
static void mch_pcie_init(PCIDevice *d)
{
- uint64_t val = Q35_HOST_BRIDGE_PCIEXBAR_ADDR | Q35_HOST_BRIDGE_PCIEXBAREN;
- uint32_t upper = val >> 32;
- uint32_t lower = val & 0xffffffff;
+ uint64_t addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR | Q35_HOST_BRIDGE_PCIEXBAREN;
+ uint32_t upper = addr >> 32;
+ uint32_t lower = addr & 0xffffffff;
+ uint64_t end;
+ uint32_t upper_end;
+ uint32_t lower_end;
/* at first disable the region. and then update/enable it. */
pci_config_writel(d, Q35_HOST_BRIDGE_PCIEXBAR, 0);
pci_config_writel(d, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
pci_config_writel(d, Q35_HOST_BRIDGE_PCIEXBAR, lower);
+
+ /* for e820 */
+ addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
+ upper = addr >> 32;
+ lower = addr & 0xffffffff;
+ end = addr + Q35_HOST_BRIDGE_PCIEXBAR_SIZE;
+ upper_end = end >> 32;
+ lower_end = end & 0xffffffff;
+
+ /* This function must be called after shadow ram initialization
+ * otherwise those area are read only as ROM so that those
+ * stores are lost.
+ */
+ *_ROMBIOS32_MCFG_ADDR = lower;
+ *_ROMBIOS32_EXTRA_MCFG_ADDR = upper;
+ *_ROMBIOS32_MCFG_END = lower_end;
+ *_ROMBIOS32_EXTRA_MCFG_END = upper_end;
}
static void bios_lock_shadow_ram(void)
@@ -961,7 +984,7 @@ static void pci_bios_init_bridges(PCIDevice *d)
device_id == PCI_DEVICE_ID_INTEL_Q35_MCH) {
/* ich9 PCI host bridge */
mch_bios_shadow_init(d);
- mch_pcie_init(d);
+ mch_pcie_init(d); /* must be after shadow init */
}
}
reserve mcfg area by e820. Linux checks whether e820 covers mcfg area. If not, linux won't to use MCFG. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> --- .gitignore | 1 + Makefile | 7 +++++-- rombios.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ rombios32.c | 31 +++++++++++++++++++++++++++---- 4 files changed, 81 insertions(+), 6 deletions(-)