mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
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>
This commit is contained in:
parent
e8cd45c78f
commit
3984890181
6 changed files with 211 additions and 58 deletions
|
@ -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 = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue