Under SeaBIOS, I'm noticing that not all of the PCIe-related area is marked uncachable in the MTRR settings, at least in the Q35 platform (QEMU).
I feel like this is a bug, but I'm not familar with the lore behind Q35 and MTRRs, feedback would be appreciated. The MCFG table contains an entry starting at Q35_HOST_BRIDGE_PCIEXBAR_ADDR (0xb0000000) corresponding to a 256MB area. Later, the mch_mem_addr_setup() routine defines the PCIe window (pcimem_start) starting at 0xc0000000 (Q35_HOST_BRIDGE_PCIEXBAR_ADDR + Q35_HOST_BRIDGE_PCIEXBAR_SIZE). I see in mtrr_setup(), that only a single variable MTRR is configured based solely on pcimem_start and extends to the end of the 4GB boundary. It looks to me that this is probably fine for 440fx, but seems insufficient for Q35. Q35 - original SeaBIOS 1.15.0: # cat /proc/mtrr reg00: base=0x0c0000000 ( 3072MB), size= 1024MB, count=1: uncachable Q35 - original EFI (ovmf 2202.02) # cat /proc/mtrr reg00: base=0x0c0000000 ( 3072MB), size= 1024MB, count=1: uncachable reg01: base=0x0b0000000 ( 2816MB), size= 256MB, count=1: uncachable reg02: base=0x800000000 (32768MB), size=32768MB, count=1: uncachable Thus, for Q35, there is no explict attempt to configure the Q35_HOST_BRIDGE_PCIEXBAR_ADDR area nor any potential the >4GB area used for PCIe I/O. The inherent size restrictions on MTRR mask definitions make a completely generic solution a bit tricky. Attached is a simple patch that enables use of the other variable MTRR registers. I believe solves the issue, but I'm not sure how to test it with a 64-bit PCIe window. In a simple setup, it results in the following: # cat /proc/mtrr reg00: base=0x0c0000000 ( 3072MB), size= 1024MB, count=1: uncachable reg01: base=0x0b0000000 ( 2816MB), size= 256MB, count=1: uncachable Is this type of change appropriate? Would it make sense to remove direct use of pcimem_start from the mtrr.c code and just like the PCI code directly register the related range using the new mechanism? Thanks -Alex
diff --git a/src/fw/mtrr.c b/src/fw/mtrr.c --- a/src/fw/mtrr.c +++ b/src/fw/mtrr.c @@ -33,6 +33,24 @@ #define MTRR_MEMTYPE_WP 5 #define MTRR_MEMTYPE_WB 6 +static struct +{ + u64 base; + u64 size; +} s_extra_uncached[8]; +static unsigned s_extra_uncached_count = 0; + +void mtrr_add_uncached(u64 base, u64 size) +{ + if (s_extra_uncached_count < ARRAY_SIZE(s_extra_uncached)) { + s_extra_uncached[s_extra_uncached_count].base = base; + s_extra_uncached[s_extra_uncached_count].size = size; + ++s_extra_uncached_count; + } else { + dprintf(1, "mtrr_add_uncached: no free slots left!\n"); + } + +} void mtrr_setup(void) { if (!CONFIG_MTRR_INIT) @@ -100,6 +118,12 @@ void mtrr_setup(void) wrmsr_smp(MTRRphysMask_MSR(0) , (-((1ull<<32)-pcimem_start) & phys_mask) | 0x800); + #define MTRR_MASK(size) ((~(size - 1) & ((1ULL << 52) - 1)) | 0x800) + for(unsigned k=0, i=1; k < s_extra_uncached_count && i < vcnt; ++k, ++i) { + wrmsr_smp(MTRRphysBase_MSR(i), s_extra_uncached[k].base | MTRR_MEMTYPE_UC); + wrmsr_smp(MTRRphysMask_MSR(i), MTRR_MASK(s_extra_uncached[k].size)); + } + // Enable fixed and variable MTRRs; set default type. wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB); } diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -492,6 +492,7 @@ static void mch_mem_addr_setup(struct pci_device *dev, void *arg) MCHMmcfgBDF = dev->bdf; mch_mmconfig_setup(dev->bdf); e820_add(addr, size, E820_RESERVED); + mtrr_add_uncached(addr, size); /* setup pci i/o window (above mmconfig) */ pcimem_start = addr + size; @@ -1140,6 +1141,7 @@ static void pci_bios_map_devices(struct pci_bus *busses) pci_region_map_entries(busses, &r64_mem); pci_region_map_entries(busses, &r64_pref); + mtrr_add_uncached(pcimem64_start, pcimem64_end - pcimem64_start); } else { // no bars mapped high -> drop 64bit window (see dsdt) pcimem64_start = 0; diff --git a/src/util.h b/src/util.h --- a/src/util.h +++ b/src/util.h @@ -127,6 +127,7 @@ void mptable_setup(void); // fw/mtrr.c void mtrr_setup(void); +void mtrr_add_uncached(u64 base, u64 size); // fw/multiboot.c void multiboot_init(void);
_______________________________________________ SeaBIOS mailing list -- seabios@seabios.org To unsubscribe send an email to seabios-le...@seabios.org