<div dir="ltr"><div>Seabios patch<br></div><div><br></div><div>This patch covers all the changes to seabios. The intentions are to make seabios behave like the hosts BIOS. and like the hosts BIOS, configure the Q35 chipset more thoroughly.</div><div><br></div><div>This patch configures TOM, TOUUD, TOLUD, BDSM, BGSM, TSEG, IGD-OPREGION.</div><div><br></div><div>by writing new base addresses, VFIO and Q35 trap these writes and enable memory mapping from the host memory to the new guest locations.</div><div> </div><div>----------------------</div><div><br></div><div>diff --git a/src/fw/dev-q35.h b/src/fw/dev-q35.h</div><div>index 6ae039f..dac8799 100644</div><div>--- a/src/fw/dev-q35.h</div><div>+++ b/src/fw/dev-q35.h</div><div>@@ -14,7 +14,18 @@</div><div> #define Q35_HOST_PCIE_START_BUS_NUMBER  0</div><div> #define Q35_HOST_PCIE_END_BUS_NUMBER    255</div><div> </div><div>-#define PCI_DEVICE_ID_INTEL_ICH9_LPC    0x2918</div><div>+/* TODO: Replace this hack for a non-hack!</div><div>+ * PCI_DEVICE_ID_INTEL_ICH9_LPC must be set to</div><div>+ * `setpci -s 00:1f.0 0x02.w` (LPC device id) </div><div>+ * of the host - so that seabios recognises</div><div>+ * the hardware QEMU is providing, </div><div>+ * which now includes the hosts LPC */</div><div>+#define Q35_BEARLAKE<span class="" style="white-space:pre">                       </span>0x2918 // QEMU DEFAULT</div><div>+#define Q35_COUGARPOINT<span class="" style="white-space:pre">                     </span>0x1c4e</div><div>+#define Q35_PANTHERPOINT<span class="" style="white-space:pre">            </span>0x</div><div>+#define Q35_LYNXPOINT<span class="" style="white-space:pre">                   </span>0x8c4e</div><div>+</div><div>+#define PCI_DEVICE_ID_INTEL_ICH9_LPC    Q35_COUGARPOINT</div><div> #define ICH9_LPC_PMBASE                 0x40</div><div> #define ICH9_LPC_PMBASE_RTE             0x1</div><div> </div><div>diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c</div><div>index 0e5d51b..bcd519b 100644</div><div>--- a/src/fw/pciinit.c</div><div>+++ b/src/fw/pciinit.c</div><div>@@ -389,20 +389,111 @@ static void i440fx_mem_addr_setup(struct pci_device *dev, void *arg)</div><div> </div><div> static void mch_mem_addr_setup(struct pci_device *dev, void *arg)</div><div> {</div><div>-    u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;</div><div>-    u32 size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE;</div><div>+    /* Base addresses are either calculated by their location with respect to</div><div>+     * TOM as described by Intel documentation.</div><div>+     * Or they are allocated using malloc. In either case, the new base addresses</div><div>+     * are written to pci_config space, where by qemu(q35) and vfio catch these changes</div><div>+     * and respond accordingly.</div><div>+     * The intention is to mimic the hosts BIOS role in configuring the PCI_CONFIG space.</div><div>+     * TODO: Clearly, this is not complete </div><div>+     * - as complete Direct Assignment is not completly working.*/</div><div>+</div><div>+    /* TODO: Move these defines to be consistent with seabios */</div><div>+    #define Q35_TOM                 0xa0</div><div>+    #define Q35_TOM_BASEADDR        0x7FFFF00000</div><div>+    #define Q35_TOUUD               0xa8</div><div>+    #define Q35_TOUUD_BASEADDR      0x7FFFF00000</div><div>+    #define Q35_TOLUD               0xbc</div><div>+    #define Q35_TOLUD_BASEADDR      0xFFF00000</div><div>+    #define Q35_APIC_FLASH_TXT_SIZE 20 * 1024 * 1024</div><div>+    #define Q35_PCIEXBAR_SIZE       256 * 1024 * 1024</div><div>+    #define Q35_IDK_SIZE            768 * 1024 * 1024</div><div>+    #define Q35_PCIEXBAR_BASEADDR   0x7FF0000000</div><div>+    #define Q35_BDSM                0xb0</div><div>+    #define Q35_BDSM_BASEADDR       0xFFF00000</div><div>+    #define Q35_GMCH_DSM_MASK       0xF8</div><div>+    #define Q35_BGSM                0xb4</div><div>+    #define Q35_BGSM_BASEADDR       0xFFF00000</div><div>+    #define Q35_GMCH_GSM_MASK       0x300</div><div>+    #define Q35_TSEG                0xb8</div><div>+    #define Q35_TSEG_BASEADDR       0xFFF00000</div><div>+    #define TSEG_SIZE               8 * 1024 * 1024</div><div>+    #define Q35_MCHBAR              0x48</div><div>+    #define Q35_MCHBAR_BASEADDR     0x7FFFFF8000</div><div>+    #define Q35_MCHBAR_EN           0x1</div><div>+    #define Q35_MCHBAR_SIZE         0x8000</div><div>+    #define Q35_DMIBAR              0x68</div><div>+    #define Q35_DMIBAR_BASEADDR     0x7FFFFFF000</div><div>+    #define Q35_DMIBAR_EN           0x1</div><div>+    #define Q35_DMIBAR_SIZE         0x1000</div><div>+    #define IGD_OPREGION            0xfc</div><div>+    #define IGD_OPREGION_PAGES      3</div><div>+    #define IGD_OPREGION_SIZE       IGD_OPREGION_PAGES * PAGE_SIZE</div><div>+    #define IGD_BDSM            0x5c</div><div>+    #define Q35_GDSM            0x52</div><div>+</div><div>+    u16 q35bdf = dev->bdf;</div><div>+</div><div>+    /* setup TOM - Top Of Memory */</div><div>+    u32 tom_lower, tom_upper;</div><div>+    u64 tom, touud;</div><div>+</div><div>+    if (RamSizeOver4G)</div><div>+    {</div><div>+<span class="" style="white-space:pre">       </span>/* TODO: not finished. +4GB no supported */</div><div>+        tom = (0x100000000 + RamSizeOver4G) & Q35_TOM_BASEADDR;</div><div>+        touud = tom & Q35_TOUUD_BASEADDR; // minus all Intel ME stolen memory if reclaim/remap is disabled</div><div>+        dprintf(1, "Q35: RamSizeOver4G: %016llX\n", tom);</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        tom = RamSize & Q35_TOM_BASEADDR;</div><div>+        touud = 0x0; // disabled if RamSize is under 4G</div><div>+        dprintf(1, "Q35: RamSize: %x\n", RamSize);</div><div>+    }</div><div> </div><div>-    /* setup mmconfig */</div><div>-    u16 bdf = dev->bdf;</div><div>-    u32 upper = addr >> 32;</div><div>-    u32 lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;</div><div>-    pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);</div><div>-    pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);</div><div>-    pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);</div><div>-    add_e820(addr, size, E820_RESERVED);</div><div>+    tom_lower = (tom & 0xffffffff);</div><div>+    tom_upper = tom >> 32;</div><div>+    pci_config_writel(q35bdf,</div><div>+                      Q35_TOM,</div><div>+                      tom_lower);</div><div>+    pci_config_writel(q35bdf,</div><div>+                      Q35_TOM+0x4,</div><div>+                      tom_upper);</div><div>+</div><div>+    /* setup TOUUD - Top of Upper Usable DRAM */</div><div>+    u32 touud_lower, touud_upper;</div><div>+    touud_lower = (touud & 0xffffffff);</div><div>+    touud_upper = touud >> 32;</div><div>+    pci_config_writel(q35bdf,</div><div>+                      Q35_TOUUD,</div><div>+                      touud_lower);</div><div>+    pci_config_writel(q35bdf,</div><div>+                      Q35_TOUUD+0x4,</div><div>+                      touud_upper);</div><div>+</div><div>+    /* setup TOLUD - Top of Lower Usable DRAM */</div><div>+    u32 tolud;</div><div>+</div><div>+    tolud = (tom - Q35_APIC_FLASH_TXT_SIZE) & Q35_TOLUD_BASEADDR;</div><div>+    pci_config_writel(q35bdf,</div><div>+                      Q35_TOLUD,</div><div>+                      tolud);</div><div>+</div><div>+</div><div>+    /* setup PCIEXBAR/MMCONFIG */</div><div>+    u64 pciexbar;</div><div>+    pciexbar = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;</div><div>+</div><div>+    u32 upper = pciexbar >> 32;</div><div>+    u32 lower = (pciexbar & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;</div><div>+    pci_config_writel(q35bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0); // This sets bit 2:1 0x0 == 256 MB (PCIEXBAR_SIZE)</div><div>+    pci_config_writel(q35bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);</div><div>+    pci_config_writel(q35bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);</div><div>+    add_e820(pciexbar, Q35_PCIEXBAR_SIZE, E820_RESERVED);</div><div> </div><div>     /* setup pci i/o window (above mmconfig) */</div><div>-    pcimem_start = addr + size;</div><div>+    pcimem_start = pciexbar + Q35_PCIEXBAR_SIZE;</div><div> </div><div>     pci_slot_get_irq = mch_pci_slot_get_irq;</div><div> </div><div>@@ -411,6 +502,107 @@ static void mch_mem_addr_setup(struct pci_device *dev, void *arg)</div><div>         pci_io_low_end = 0x10000;</div><div>     else</div><div>         pci_io_low_end = acpi_pm_base;</div><div>+</div><div>+    /* setup BDSM - Base Data of Stolen Memory */</div><div>+    u16 gmch_config = pci_config_readw(q35bdf,0x50);</div><div>+</div><div>+    int dsm_size;</div><div>+    u16 gmch_dsm = (gmch_config & Q35_GMCH_DSM_MASK) >> 3;</div><div>+</div><div>+    switch (gmch_dsm)</div><div>+    {</div><div>+      case 0x0: dsm_size = 0; break;</div><div>+      case 0x1: dsm_size = 32; break;</div><div>+      case 0x2: dsm_size = 64; break;</div><div>+      case 0x3: dsm_size = 96; break;</div><div>+      case 0x4: dsm_size = 128; break;</div><div>+      case 0x5: dsm_size = 160; break;</div><div>+      case 0x6: dsm_size = 192; break;</div><div>+      case 0x7: dsm_size = 224; break;</div><div>+      case 0x8: dsm_size = 256; break;</div><div>+      case 0x9: dsm_size = 288; break;</div><div>+      case 0xa: dsm_size = 320; break;</div><div>+      case 0xb: dsm_size = 352; break;</div><div>+      case 0xc: dsm_size = 384; break;</div><div>+      case 0xd: dsm_size = 416; break;</div><div>+      case 0xe: dsm_size = 448; break;</div><div>+      case 0xf: dsm_size = 480; break;</div><div>+      case 0x10: dsm_size = 512; break;</div><div>+     // default: /* panic */</div><div>+    }</div><div>+</div><div>+    dsm_size = dsm_size * 1024 * 1024;</div><div>+</div><div>+    u32 bdsm = (tolud - dsm_size) & Q35_BDSM_BASEADDR;</div><div>+    pci_config_writel(q35bdf,Q35_BDSM,bdsm);</div><div>+    add_e820(bdsm, dsm_size, E820_RESERVED);</div><div>+</div><div>+    /* setup BGSM - Base Data of GTT Stolen Memory */</div><div>+    int gsm_size;</div><div>+    u16 gmch_gsm = (gmch_config & Q35_GMCH_GSM_MASK) >> 8;</div><div>+</div><div>+    switch (gmch_gsm)</div><div>+    {</div><div>+      case 0x2: gsm_size = 2; break;</div><div>+      case 0x1: gsm_size = 1; break;</div><div>+      case 0x0: gsm_size = 0; break;</div><div>+     // default: /* panic */</div><div>+    }</div><div>+</div><div>+    gsm_size = gsm_size * 1024 * 1024;</div><div>+</div><div>+    u32 bgsm = (tolud - dsm_size - gsm_size) & Q35_BGSM_BASEADDR;</div><div>+    pci_config_writel(q35bdf,Q35_BGSM,bgsm);</div><div>+    add_e820(bgsm, gsm_size, E820_RESERVED);</div><div>+</div><div>+    /* setup TSEG -  */</div><div>+    u32 tseg = (tolud - dsm_size - gsm_size - TSEG_SIZE) & Q35_TSEG_BASEADDR;</div><div>+    pci_config_writel(q35bdf,Q35_TSEG,tseg);</div><div>+    add_e820(tseg, TSEG_SIZE, E820_RESERVED);</div><div>+</div><div>+    /* setup MCHBAR */</div><div>+    u32 mchbar_addr, mchbar_lower, mchbar_upper;</div><div>+    u64 mchbar;</div><div>+</div><div>+    mchbar_addr = malloc_high(Q35_MCHBAR_SIZE);</div><div>+    mchbar = (mchbar_addr & Q35_MCHBAR_BASEADDR) | Q35_MCHBAR_EN;</div><div>+    mchbar_lower = (mchbar & 0xffffffff);</div><div>+    mchbar_upper = mchbar >> 32;</div><div>+</div><div>+    add_e820(mchbar_addr,Q35_MCHBAR_SIZE,E820_RESERVED);</div><div>+    pci_config_writel(pci_to_bdf(0,0,0),</div><div>+                      Q35_MCHBAR,</div><div>+                      mchbar_lower);</div><div>+    pci_config_writel(pci_to_bdf(0,0,0),</div><div>+                      Q35_MCHBAR+0x4,</div><div>+                      mchbar_upper);</div><div>+</div><div>+    /* setup DMIBAR */</div><div>+    u32 dmibar_addr, dmibar_lower, dmibar_upper;</div><div>+    u64 dmibar;</div><div>+</div><div>+    dmibar_addr = malloc_high(Q35_DMIBAR_SIZE);</div><div>+    dmibar = (dmibar_addr & Q35_DMIBAR_BASEADDR) | Q35_DMIBAR_EN;</div><div>+    dmibar_lower = (dmibar & 0xffffffff);</div><div>+    dmibar_upper = dmibar >> 32;</div><div>+</div><div>+    add_e820(dmibar_addr,Q35_DMIBAR_SIZE,E820_RESERVED);</div><div>+    pci_config_writel(pci_to_bdf(0,0,0),</div><div>+                      Q35_DMIBAR,</div><div>+                      dmibar_lower);</div><div>+    pci_config_writel(pci_to_bdf(0,0,0),</div><div>+                      Q35_DMIBAR+0x4,</div><div>+                      dmibar_upper);</div><div>+</div><div>+    /* setup igd opregion */</div><div>+    u32 host_opregion = pci_config_readl(pci_to_bdf(0,2,0),IGD_OPREGION);</div><div>+    u32 guest_opregion = malloc_high(IGD_OPREGION_SIZE);</div><div>+</div><div>+    add_e820(guest_opregion,IGD_OPREGION_SIZE,E820_NVS);</div><div>+    pci_config_writel(pci_to_bdf(0,2,0),</div><div>+                      IGD_OPREGION,</div><div>+                      ((guest_opregion & 0xfffff000) | (host_opregion & 0xfff)));</div><div>+</div><div> }</div><div> </div><div> static const struct pci_device_id pci_platform_tbl[] = {</div></div>