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

Reply via email to