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(a)redhat.com>
---
hw/fw_cfg.h | 1 +
hw/pc.c | 15 ++++++++++++++-
2 files changed, 15 insertions(+), 1 deletions(-)
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);
}
--
1.7.1