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/pci-host/piix.c | |
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/pci-host/piix.c')
-rw-r--r-- | hw/pci-host/piix.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 3f539ec140..dc1718fe30 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -32,6 +32,8 @@ #include "hw/xen/xen.h" #include "hw/pci-host/pam.h" #include "sysemu/sysemu.h" +#include "hw/i386/ioapic.h" +#include "qapi/visitor.h" /* * I440FX chipset data sheet. @@ -44,6 +46,8 @@ typedef struct I440FXState { PCIHostState parent_obj; + PcPciInfo pci_info; + uint64_t pci_hole64_size; } I440FXState; #define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */ @@ -207,14 +211,71 @@ static const VMStateDescription vmstate_i440fx = { } }; +static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); + uint32_t value = s->pci_info.w32.begin; + + visit_type_uint32(v, &value, name, errp); +} + +static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); + uint32_t value = s->pci_info.w32.end; + + visit_type_uint32(v, &value, name, errp); +} + +static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); + + visit_type_uint64(v, &s->pci_info.w64.begin, name, errp); +} + +static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp) +{ + I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj); + + visit_type_uint64(v, &s->pci_info.w64.end, name, errp); +} + static void i440fx_pcihost_initfn(Object *obj) { PCIHostState *s = PCI_HOST_BRIDGE(obj); + I440FXState *d = I440FX_PCI_HOST_BRIDGE(obj); memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s, "pci-conf-idx", 4); memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s, "pci-conf-data", 4); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int", + i440fx_pcihost_get_pci_hole_start, + NULL, NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int", + i440fx_pcihost_get_pci_hole_end, + NULL, NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int", + i440fx_pcihost_get_pci_hole64_start, + NULL, NULL, NULL, NULL); + + object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int", + i440fx_pcihost_get_pci_hole64_end, + NULL, NULL, NULL, NULL); + + d->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; } static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) @@ -247,8 +308,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, ram_addr_t ram_size, hwaddr pci_hole_start, hwaddr pci_hole_size, - hwaddr pci_hole64_start, - hwaddr pci_hole64_size, + ram_addr_t above_4g_mem_size, MemoryRegion *pci_address_space, MemoryRegion *ram_memory) { @@ -259,6 +319,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, PIIX3State *piix3; PCII440FXState *f; unsigned i; + I440FXState *i440fx; dev = qdev_create(NULL, TYPE_I440FX_PCI_HOST_BRIDGE); s = PCI_HOST_BRIDGE(dev); @@ -274,14 +335,31 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, f->system_memory = address_space_mem; f->pci_address_space = pci_address_space; f->ram_memory = ram_memory; + + i440fx = I440FX_PCI_HOST_BRIDGE(dev); + /* 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) { + i440fx->pci_info.w32.begin = 0x80000000; + } else if (ram_size <= 0xc0000000) { + i440fx->pci_info.w32.begin = 0xc0000000; + } else { + i440fx->pci_info.w32.begin = 0xe0000000; + } + memory_region_init_alias(&f->pci_hole, OBJECT(d), "pci-hole", f->pci_address_space, pci_hole_start, pci_hole_size); memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole); + + pc_init_pci64_hole(&i440fx->pci_info, 0x100000000ULL + above_4g_mem_size, + i440fx->pci_hole64_size); memory_region_init_alias(&f->pci_hole_64bit, OBJECT(d), "pci-hole64", f->pci_address_space, - pci_hole64_start, pci_hole64_size); - if (pci_hole64_size) { - memory_region_add_subregion(f->system_memory, pci_hole64_start, + i440fx->pci_info.w64.begin, + i440fx->pci_hole64_size); + if (i440fx->pci_hole64_size) { + memory_region_add_subregion(f->system_memory, + i440fx->pci_info.w64.begin, &f->pci_hole_64bit); } memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region", @@ -629,6 +707,12 @@ static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, return "0000"; } +static Property i440fx_props[] = { + DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState, + pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE), + DEFINE_PROP_END_OF_LIST(), +}; + static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -638,6 +722,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) dc->realize = i440fx_pcihost_realize; dc->fw_name = "pci"; dc->no_user = 1; + dc->props = i440fx_props; } static const TypeInfo i440fx_pcihost_info = { |