qboot: enable mmconfig
Need to enable mmconfig in qboot and also need to reserve
mmconfig space in bios.
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
Message-Id: <1490869973-4562-1-git-send-email-yang.zhong@intel.com>
[Do not affect e820 memory map on i440FX chipset. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/hwsetup.c b/hwsetup.c
index 0e186eb..e8a452e 100644
--- a/hwsetup.c
+++ b/hwsetup.c
@@ -127,3 +127,31 @@
setup_pic();
}
+
+#define Q35_HOST_BRIDGE_PCIEXBAREN 1
+#define Q35_HOST_BRIDGE_PCIEXBAR 0x60
+
+static void setup_q35_mmconfig(void)
+{
+ const int bdf = 0;
+ uint64_t addr = PCIE_MMCONFIG_BASE;
+ uint32_t upper = addr >> 32;
+ uint32_t lower = (addr & 0xffffffff) | Q35_HOST_BRIDGE_PCIEXBAREN;
+
+ pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
+ pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
+ pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
+}
+
+bool setup_mmconfig(void)
+{
+ const int bdf = 0;
+ uint32_t id = pci_config_readl(bdf, 0);
+
+ if (id == (PCI_VENDOR_ID_INTEL | (PCI_DEVICE_ID_INTEL_Q35_MCH << 16))) {
+ setup_q35_mmconfig();
+ return true;
+ }
+
+ return false;
+}
diff --git a/include/bios.h b/include/bios.h
index bc96f87..df60c5a 100644
--- a/include/bios.h
+++ b/include/bios.h
@@ -40,6 +40,7 @@
extern void setup_pci(void);
extern void setup_hw(void);
+extern bool setup_mmconfig(void);
extern void extract_acpi(void);
extern void boot_from_fwcfg(void);
extern bool boot_from_cbfs(void *base, size_t sz);
diff --git a/include/pci.h b/include/pci.h
index bb37b86..7f40f38 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -72,4 +72,7 @@
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
+#define PCIE_MMCONFIG_BASE 0xb0000000
+#define PCIE_MMCONFIG_SIZE (256 * 1024 * 1024)
+
#endif
diff --git a/main.c b/main.c
index 1913b37..f092289 100644
--- a/main.c
+++ b/main.c
@@ -6,6 +6,7 @@
#include "segment.h"
#include "fw_cfg.h"
#include "pflash.h"
+#include "pci.h"
static void set_realmode_int(int vec, void *p)
{
@@ -30,6 +31,7 @@
/* Top of memory below 4GB. */
uint32_t lowmem;
struct e820map *e820;
+static bool have_mmconfig;
static void extract_e820(void)
{
@@ -42,7 +44,7 @@
panic();
size = fw_cfg_file_size(id);
- nr_map = size / sizeof(e820->map[0]) + 4;
+ nr_map = size / sizeof(e820->map[0]) + 5;
e820 = malloc(offsetof(struct e820map, map[nr_map]));
e820->nr_map = nr_map;
@@ -54,8 +56,16 @@
{ .addr = 0xd0000, .size = 128 * 1024, .type = E820_NVS }; /* ACPI tables */
e820->map[3] = (struct e820entry)
{ .addr = 0xf0000, .size = 64 * 1024, .type = E820_RESERVED }; /* firmware */
- fw_cfg_read_file(id, &e820->map[4], size);
- for (i = 4; i < e820->nr_map; i++)
+
+ i = 4;
+ if (have_mmconfig)
+ e820->map[i++] = (struct e820entry)
+ { .addr = PCIE_MMCONFIG_BASE, .size = PCIE_MMCONFIG_SIZE, .type = E820_RESERVED };
+ else
+ nr_map--;
+
+ fw_cfg_read_file(id, &e820->map[i], size);
+ for (; i < e820->nr_map; i++)
if (e820->map[i].addr == 0) {
lowmem = e820->map[i].size;
e820->map[i].addr = 1024 * 1024;
@@ -85,6 +95,7 @@
// in order to probe CBFS!
asm("ljmp $0x8, $1f; 1:");
+ have_mmconfig = setup_mmconfig();
setup_pci();
setup_idt();
fw_cfg_setup();