diff options
author | Igor Mammedov <imammedo@redhat.com> | 2013-07-29 16:47:57 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-07-29 19:33:34 -0500 |
commit | 398489018183d613306ab022653552247d93919f (patch) | |
tree | 65bd612a22d9f0c3d9d92d00ed3f9dce2b9712a2 /hw/i386 | |
parent | e8cd45c78f53501e75bd455140da63d1b7ed3685 (diff) |
pc: limit 64 bit hole to 2G by default
It turns out that some 32 bit windows guests crash
if 64 bit PCI hole size is >2G.
Limit it to 2G for piix and q35 by default.
User may override default 64-bit PCI hole size by
using "pci-hole64-size" property.
Examples:
-global i440FX-pcihost.pci-hole64-size=4G
-global q35-pcihost.pci-hole64-size=4G
Reported-by: Igor Mammedov <imammedo@redhat.com>,
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Message-id: 1375109277-25561-8-git-send-email-imammedo@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/i386')
-rw-r--r-- | hw/i386/pc.c | 56 | ||||
-rw-r--r-- | hw/i386/pc_piix.c | 14 |
2 files changed, 35 insertions, 35 deletions
diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b0b98a8f84..a2b9d889dd 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -55,6 +55,7 @@ #include "hw/acpi/acpi.h" #include "hw/cpu/icc_bus.h" #include "hw/boards.h" +#include "hw/pci/pci_host.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -1003,15 +1004,27 @@ typedef struct PcRomPciInfo { static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info) { PcRomPciInfo *info; + Object *pci_info; + bool ambiguous = false; + if (!guest_info->has_pci_info || !guest_info->fw_cfg) { return; } + pci_info = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous); + g_assert(!ambiguous); + if (!pci_info) { + return; + } info = g_malloc(sizeof *info); - info->w32_min = cpu_to_le64(guest_info->pci_info.w32.begin); - info->w32_max = cpu_to_le64(guest_info->pci_info.w32.end); - info->w64_min = cpu_to_le64(guest_info->pci_info.w64.begin); - info->w64_max = cpu_to_le64(guest_info->pci_info.w64.end); + info->w32_min = cpu_to_le64(object_property_get_int(pci_info, + PCI_HOST_PROP_PCI_HOLE_START, NULL)); + info->w32_max = cpu_to_le64(object_property_get_int(pci_info, + PCI_HOST_PROP_PCI_HOLE_END, NULL)); + info->w64_min = cpu_to_le64(object_property_get_int(pci_info, + PCI_HOST_PROP_PCI_HOLE64_START, NULL)); + info->w64_max = cpu_to_le64(object_property_get_int(pci_info, + PCI_HOST_PROP_PCI_HOLE64_END, NULL)); /* Pass PCI hole info to guest via a side channel. * Required so guest PCI enumeration does the right thing. */ fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info); @@ -1037,29 +1050,28 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); PcGuestInfo *guest_info = &guest_info_state->info; - guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; - if (sizeof(hwaddr) == 4) { - guest_info->pci_info.w64.begin = 0; - guest_info->pci_info.w64.end = 0; - } else { - /* - * BIOS does not set MTRR entries for the 64 bit window, so no need to - * align address to power of two. Align address at 1G, this makes sure - * it can be exactly covered with a PAT entry even when using huge - * pages. - */ - guest_info->pci_info.w64.begin = - ROUND_UP((0x1ULL << 32) + above_4g_mem_size, 0x1ULL << 30); - guest_info->pci_info.w64.end = guest_info->pci_info.w64.begin + - (0x1ULL << 62); - assert(guest_info->pci_info.w64.begin <= guest_info->pci_info.w64.end); - } - guest_info_state->machine_done.notify = pc_guest_info_machine_done; qemu_add_machine_init_done_notifier(&guest_info_state->machine_done); return guest_info; } +void pc_init_pci64_hole(PcPciInfo *pci_info, uint64_t pci_hole64_start, + uint64_t pci_hole64_size) +{ + if ((sizeof(hwaddr) == 4) || (!pci_hole64_size)) { + return; + } + /* + * BIOS does not set MTRR entries for the 64 bit window, so no need to + * align address to power of two. Align address at 1G, this makes sure + * it can be exactly covered with a PAT entry even when using huge + * pages. + */ + pci_info->w64.begin = ROUND_UP(pci_hole64_start, 0x1ULL << 30); + pci_info->w64.end = pci_info->w64.begin + pci_hole64_size; + assert(pci_info->w64.begin <= pci_info->w64.end); +} + void pc_acpi_init(const char *default_dsdt) { char *filename; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index b58c25596d..ab25458cd6 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -129,15 +129,6 @@ static void pc_init1(MemoryRegion *system_memory, guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); guest_info->has_pci_info = has_pci_info; - /* Set PCI window size the way seabios has always done it. */ - /* Power of 2 so bios can cover it with a single MTRR */ - if (ram_size <= 0x80000000) - guest_info->pci_info.w32.begin = 0x80000000; - else if (ram_size <= 0xc0000000) - guest_info->pci_info.w32.begin = 0xc0000000; - else - guest_info->pci_info.w32.begin = 0xe0000000; - /* allocate ram and load rom/bios */ if (!xen_enabled()) { fw_cfg = pc_memory_init(system_memory, @@ -160,10 +151,7 @@ static void pc_init1(MemoryRegion *system_memory, system_memory, system_io, ram_size, below_4g_mem_size, 0x100000000ULL - below_4g_mem_size, - 0x100000000ULL + above_4g_mem_size, - (sizeof(hwaddr) == 4 - ? 0 - : ((uint64_t)1 << 62)), + above_4g_mem_size, pci_memory, ram_memory); } else { pci_bus = NULL; |