qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 10/14] pcibos: add mcfg entry to ACPI table for q35


From: Isaku Yamahata
Subject: [Qemu-devel] [PATCH 10/14] pcibos: add mcfg entry to ACPI table for q35 pcie.
Date: Wed, 30 Sep 2009 19:18:45 +0900

add mcfg entry to ACPI table for q35 pcie.

Signed-off-by: Isaku Yamahata <address@hidden>
---
 rombios32.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/rombios32.c b/rombios32.c
index f7e906f..3259433 100644
--- a/rombios32.c
+++ b/rombios32.c
@@ -715,6 +715,13 @@ void smp_probe(void)
 #define  Q35_HOST_BRIDGE_PAM0           0x90
 #define  Q35_HOST_BRDIGE_SMRAM          0x9d
 
+#define Q35_HOST_BRIDGE_PCIEXBAR        0x60
+#define  Q35_HOST_BRIDGE_PCIEXBAR_ADDR  0xe0000000
+#define  Q35_HOST_BRIDGE_PCIEXBAREN     ((uint64_t)1)
+#define  Q35_HOST_PCIE_PCI_SEGMENT      0
+#define  Q35_HOST_PCIE_START_BUS_NUMBER 0
+#define  Q35_HOST_PCIE_END_BUS_NUMBER   255
+
 #define PCI_DEVICE_ID_INTEL_ICH9_LPC    0x2918
 #define  ICH9_LPC_PMBASE                0x40
 #define    ICH9_PMBASE_SMI_EN           0x30
@@ -890,6 +897,18 @@ static void mch_bios_lock_shadow_ram(PCIDevice *d)
     bios_lock_shadow_ram_common(d, Q35_HOST_BRIDGE_PAM0);
 }
 
+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;
+
+    /* 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);
+}
+
 static void bios_lock_shadow_ram(void)
 {
     if (i440_found)
@@ -942,6 +961,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);
     }
 }
 
@@ -1481,7 +1501,7 @@ struct rsdt_descriptor_rev1
 {
        ACPI_TABLE_HEADER_DEF                           /* ACPI common table 
header */
 #ifdef BX_QEMU
-       uint32_t                             table_offset_entry [5]; /* Array 
of pointers to other */
+       uint32_t                             table_offset_entry [6]; /* Array 
of pointers to other */
 #else
        uint32_t                             table_offset_entry [3]; /* Array 
of pointers to other */
 #endif
@@ -1708,6 +1728,22 @@ struct madt_int_override
 } __attribute__((__packed__));
 #endif
 
+/* PCI fw r3.0 MCFG table. stolen from linux header file */
+struct acpi_table_mcfg {
+       ACPI_TABLE_HEADER_DEF;
+       uint8_t                 reserved[8];
+} __attribute__((__packed__));
+
+/* Subtable */
+struct acpi_mcfg_allocation {
+        uint64_t       address;                /* Base address, 
processor-relative */
+        uint16_t       pci_segment;            /* PCI segment group number */
+        uint8_t                start_bus_number;       /* Starting PCI Bus 
number */
+        uint8_t                end_bus_number;         /* Final PCI Bus number 
*/
+        uint32_t       reserved;
+} __attribute__((__packed__));
+
+
 #include "acpi-dsdt.hex"
 
 static inline uint16_t cpu_to_le16(uint16_t x)
@@ -1832,12 +1868,17 @@ void acpi_bios_init(void)
     struct system_resource_affinity_table *srat;
     struct acpi_20_hpet *hpet;
     uint32_t hpet_addr;
+    uint32_t mcfg_addr = 0;
+    uint32_t mcfg_size;
+    struct acpi_table_mcfg *mcfg = NULL;
+    struct acpi_mcfg_allocation *mcfg_alloc = NULL;
 #endif
     uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, 
ssdt_addr;
     uint32_t acpi_tables_size, madt_addr, madt_size, rsdt_size;
     uint32_t srat_addr,srat_size;
     uint16_t i, external_tables;
     int nb_numa_nodes;
+    int nb_entry;
 
     /* reserve memory space for tables */
 #ifdef BX_USE_EBDA_TABLES
@@ -1916,6 +1957,16 @@ void acpi_bios_init(void)
     hpet_addr = addr;
     hpet = (void *)(addr);
     addr += sizeof(*hpet);
+
+    mcfg_size = 0;
+    if (mch_found) {
+        addr = (addr + 7) & ~7;
+        mcfg_addr = addr;
+        mcfg = (void*)addr;
+        mcfg_alloc = (void*)(addr + sizeof(*mcfg));
+        mcfg_size = sizeof(*mcfg) + sizeof(*mcfg_alloc);
+        addr += mcfg_size;
+    }
 #endif
 
     /* RSDP */
@@ -2117,19 +2168,42 @@ void acpi_bios_init(void)
         if(addr >= ram_size)
             BX_PANIC("ACPI table overflow\n");
     }
+
+    /* MCFG */
+    if (mch_found) {
+        memset(mcfg, 0, mcfg_size);
+        mcfg_alloc->address = Q35_HOST_BRIDGE_PCIEXBAR_ADDR;
+        mcfg_alloc->pci_segment = Q35_HOST_PCIE_PCI_SEGMENT;
+        mcfg_alloc->start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER;
+        mcfg_alloc->end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER;
+
+        acpi_build_table_header((struct acpi_table_header *)mcfg,
+                                "MCFG", mcfg_size, 1);
+    }
 #endif
 
     /* RSDT */
-    rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
-    rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
-    rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
+    nb_entry = 0;
+    rsdt->table_offset_entry[nb_entry++] = cpu_to_le32(fadt_addr);
+    rsdt->table_offset_entry[nb_entry++] = cpu_to_le32(madt_addr);
+    rsdt->table_offset_entry[nb_entry++] = cpu_to_le32(ssdt_addr);
 #ifdef BX_QEMU
-    rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr);
+    rsdt->table_offset_entry[nb_entry++] = cpu_to_le32(hpet_addr);
     if (nb_numa_nodes > 0)
-        rsdt->table_offset_entry[4] = cpu_to_le32(srat_addr);
+        rsdt->table_offset_entry[nb_entry++] = cpu_to_le32(srat_addr);
+    if (mcfg_size > 0)
+        rsdt->table_offset_entry[nb_entry++] = cpu_to_le32(mcfg_addr);
 #endif
+    if (sizeof(rsdt->table_offset_entry) /
+        sizeof(rsdt->table_offset_entry[0]) >= nb_entry)
+        BX_INFO("rdst table_offset_entry size is too short %d."
+                "increase it to %d.\n",
+                sizeof(rsdt->table_offset_entry) /
+                sizeof(rsdt->table_offset_entry[0]),
+                nb_entry);
     acpi_build_table_header((struct acpi_table_header *)rsdt, "RSDT",
-        rsdt_size - (nb_numa_nodes > 0? 0: sizeof(uint32_t)), 1);
+        offsetof(struct rsdt_descriptor_rev1, table_offset_entry) +
+        nb_entry * sizeof(uint32_t), 1);
 
     acpi_tables_size = addr - base_addr;
 
-- 
1.6.0.2





reply via email to

[Prev in Thread] Current Thread [Next in Thread]