Patchwork [qemu] pci: pass i/o windows via fwcfg

login
register
mail settings
Submitter Gerd Hoffmann
Date May 4, 2012, 8:21 a.m.
Message ID <1336119681-6248-1-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/156811/
State New
Headers show

Comments

Gerd Hoffmann - May 4, 2012, 8:21 a.m.
This patch adds a fw_cfg entry for the PCI I/O windows.  It holds four
values, 64bit each.  The first two specify the 32bit PCI I/O window
below 4G, the second two the 64bit PCI I/O window above 4G.

The 32bit PCI I/O window used to start at the fixed address 0xe0000000.
Now it starts at the end of low ram, i.e. machines with less than 3.5 GB
of memory get a larger PCI I/O window.

The 64bit PCI I/O window is located above all memory, is 64G in size and
is aligned according to its size, i.e. usually it starts at 64GB and
ends at 128GB.  When guests have lots of memory it gets moved up
accordingly.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/fw_cfg.h |    1 +
 hw/pc.c     |   15 ++++++++++++++-
 2 files changed, 15 insertions(+), 1 deletions(-)

Patch

diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h
index 856bf91..3042954 100644
--- a/hw/fw_cfg.h
+++ b/hw/fw_cfg.h
@@ -27,6 +27,7 @@ 
 #define FW_CFG_SETUP_SIZE       0x17
 #define FW_CFG_SETUP_DATA       0x18
 #define FW_CFG_FILE_DIR         0x19
+#define FW_CFG_PCI_WINDOWS      0x1a
 
 #define FW_CFG_FILE_FIRST       0x20
 #define FW_CFG_FILE_SLOTS       0x10
diff --git a/hw/pc.c b/hw/pc.c
index 4d34a33..a823b27 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -72,7 +72,8 @@ 
 
 #define MSI_ADDR_BASE 0xfee00000
 
-#define E820_NR_ENTRIES		16
+#define E820_NR_ENTRIES   16
+#define PCI64_SIZE        0x1000000000LL /* 64 GB */
 
 struct e820_entry {
     uint64_t address;
@@ -987,6 +988,7 @@  void pc_memory_init(MemoryRegion *system_memory,
     int linux_boot, i;
     MemoryRegion *ram, *option_rom_mr;
     MemoryRegion *ram_below_4g, *ram_above_4g;
+    uint64_t *pcimem, pci64_base;
     void *fw_cfg;
 
     linux_boot = (kernel_filename != NULL);
@@ -1027,6 +1029,17 @@  void pc_memory_init(MemoryRegion *system_memory,
     fw_cfg = bochs_bios_init();
     rom_set_fw(fw_cfg);
 
+    pcimem = g_malloc0(sizeof(uint64_t) * 4);
+    /* 32bit pci io window */
+    pcimem[0] = cpu_to_le64(below_4g_mem_size);
+    pcimem[1] = cpu_to_le64(0xFEC00000 - 1);
+    /* 64bit pci io window */
+    pci64_base = (0x100000000ULL + above_4g_mem_size + PCI64_SIZE) & ~(PCI64_SIZE-1);
+    pcimem[2] = cpu_to_le64(pci64_base);
+    pcimem[3] = cpu_to_le64(pci64_base + PCI64_SIZE - 1);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_PCI_WINDOWS,
+                     (uint8_t *)pcimem, sizeof(uint64_t) * 4);
+
     if (linux_boot) {
         load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
     }