Refactor code so that chipset initialization is similar to q35. This will allow memory map initialization at chipset qdev init time for both machines, as well as more similar code structure overall.
Signed-off-by: Vasilis Liaskovitis vasilis.liaskovitis@profitbricks.com --- hw/pc_piix.c | 57 ++++++++++++--- hw/piix_pci.c | 225 ++++++++++++++------------------------------------------- 2 files changed, 100 insertions(+), 182 deletions(-)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 19e342a..6a9b508 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -47,6 +47,7 @@ #ifdef CONFIG_XEN # include <xen/hvm/hvm_info_table.h> #endif +#include "piix_pci.h"
#define MAX_IDE_BUS 2
@@ -85,6 +86,8 @@ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *pci_memory; MemoryRegion *rom_memory; void *fw_cfg = NULL; + I440FXState *i440fx_host; + PIIX3State *piix3;
pc_cpus_init(cpu_model);
@@ -127,21 +130,53 @@ static void pc_init1(MemoryRegion *system_memory, }
if (pci_enabled) { - pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, - 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)), - pci_memory, ram_memory); + i440fx_host = I440FX_HOST_DEVICE(qdev_create(NULL, + TYPE_I440FX_HOST_DEVICE)); + i440fx_host->mch.ram_memory = ram_memory; + i440fx_host->mch.pci_address_space = pci_memory; + i440fx_host->mch.system_memory = get_system_memory(); + i440fx_host->mch.address_space_io = get_system_io();; + i440fx_host->mch.below_4g_mem_size = below_4g_mem_size; + i440fx_host->mch.above_4g_mem_size = above_4g_mem_size; + + qdev_init_nofail(DEVICE(i440fx_host)); + i440fx_state = &i440fx_host->mch; + pci_bus = i440fx_host->parent_obj.bus; + /* Xen supports additional interrupt routes from the PCI devices to + * the IOAPIC: the four pins of each PCI device on the bus are also + * connected to the IOAPIC directly. + * These additional routes can be discovered through ACPI. */ + if (xen_enabled()) { + piix3 = DO_UPCAST(PIIX3State, dev, + pci_create_simple_multifunction(pci_bus, -1, true, + "PIIX3-xen")); + pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq, + piix3, XEN_PIIX_NUM_PIRQS); + } else { + piix3 = DO_UPCAST(PIIX3State, dev, + pci_create_simple_multifunction(pci_bus, -1, true, + "PIIX3")); + pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq, piix3, + PIIX_NUM_PIRQS); + pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq); + } + piix3->pic = gsi; + isa_bus = DO_UPCAST(ISABus, qbus, + qdev_get_child_bus(&piix3->dev.qdev, "isa.0")); + + piix3_devfn = piix3->dev.devfn; + + ram_size = ram_size / 8 / 1024 / 1024; + if (ram_size > 255) { + ram_size = 255; + } + i440fx_state->dev.config[0x57] = ram_size; } else { pci_bus = NULL; - i440fx_state = NULL; isa_bus = isa_bus_new(NULL, system_io); no_hpet = 1; } + isa_bus_irqs(isa_bus, gsi);
if (kvm_irqchip_in_kernel()) { @@ -157,7 +192,7 @@ static void pc_init1(MemoryRegion *system_memory, gsi_state->i8259_irq[i] = i8259[i]; } if (pci_enabled) { - ioapic_init_gsi(gsi_state, "i440fx"); + ioapic_init_gsi(gsi_state, NULL); }
pc_register_ferr_irq(gsi[13]); diff --git a/hw/piix_pci.c b/hw/piix_pci.c index ba1b3de..7ca3c73 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -31,70 +31,15 @@ #include "range.h" #include "xen.h" #include "pam.h" +#include "piix_pci.h"
-/* - * I440FX chipset data sheet. - * http://download.intel.com/design/chipsets/datashts/29054901.pdf - */ - -typedef struct I440FXState { - PCIHostState parent_obj; -} I440FXState; - -#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */ -#define PIIX_NUM_PIRQS 4ULL /* PIRQ[A-D] */ -#define XEN_PIIX_NUM_PIRQS 128ULL -#define PIIX_PIRQC 0x60 - -typedef struct PIIX3State { - PCIDevice dev; - - /* - * bitmap to track pic levels. - * The pic level is the logical OR of all the PCI irqs mapped to it - * So one PIC level is tracked by PIIX_NUM_PIRQS bits. - * - * PIRQ is mapped to PIC pins, we track it by - * PIIX_NUM_PIRQS * PIIX_NUM_PIC_IRQS = 64 bits with - * pic_irq * PIIX_NUM_PIRQS + pirq - */ -#if PIIX_NUM_PIC_IRQS * PIIX_NUM_PIRQS > 64 -#error "unable to encode pic state in 64bit in pic_levels." -#endif - uint64_t pic_levels; - - qemu_irq *pic; - - /* This member isn't used. Just for save/load compatibility */ - int32_t pci_irq_levels_vmstate[PIIX_NUM_PIRQS]; -} PIIX3State; - -struct PCII440FXState { - PCIDevice dev; - MemoryRegion *system_memory; - MemoryRegion *pci_address_space; - MemoryRegion *ram_memory; - MemoryRegion pci_hole; - MemoryRegion pci_hole_64bit; - PAMMemoryRegion pam_regions[13]; - MemoryRegion smram_region; - uint8_t smm_enabled; -}; - - -#define I440FX_PAM 0x59 -#define I440FX_PAM_SIZE 7 -#define I440FX_SMRAM 0x72 - -static void piix3_set_irq(void *opaque, int pirq, int level); -static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx); static void piix3_write_config_xen(PCIDevice *dev, uint32_t address, uint32_t val, int len);
/* return the global irq number corresponding to a given device irq pin. We could also use the bus number to have a more precise mapping. */ -static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) +int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) { int slot_addend; slot_addend = (pci_dev->devfn >> 3) - 1; @@ -180,149 +125,86 @@ static const VMStateDescription vmstate_i440fx = { } };
-static int i440fx_pcihost_initfn(SysBusDevice *dev) +static void i440fx_pcihost_initfn(Object *obj) { - PCIHostState *s = PCI_HOST_BRIDGE(dev); + I440FXState *s = I440FX_HOST_DEVICE(obj); + object_initialize(&s->mch, TYPE_I440FX_PCI_DEVICE); + object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL); +}
- memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s, - "pci-conf-idx", 4); - sysbus_add_io(dev, 0xcf8, &s->conf_mem); - sysbus_init_ioports(&s->busdev, 0xcf8, 4); +static int i440fx_pcihost_init(SysBusDevice *dev) +{ + PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev); + I440FXState *s = I440FX_HOST_DEVICE(&dev->qdev); + PCIBus *b; + + memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci, + "pci-conf-idx", 4); + sysbus_add_io(dev, 0xcf8, &pci->conf_mem); + sysbus_init_ioports(&pci->busdev, 0xcf8, 4); + memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci, + "pci-conf-data", 4);
- memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s, - "pci-conf-data", 4); - sysbus_add_io(dev, 0xcfc, &s->data_mem); - sysbus_init_ioports(&s->busdev, 0xcfc, 4); + sysbus_add_io(dev, 0xcfc, &pci->data_mem); + sysbus_init_ioports(&pci->busdev, 0xcfc, 4); + + b = pci_bus_new(&s->parent_obj.busdev.qdev, NULL, s->mch.pci_address_space, + s->mch.address_space_io, 0); + s->parent_obj.bus = b; + qdev_set_parent_bus(DEVICE(&s->mch), BUS(b)); + qdev_init_nofail(DEVICE(&s->mch));
return 0; }
static int i440fx_initfn(PCIDevice *dev) { - PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev); + int i; + PCII440FXState *f = DO_UPCAST(PCII440FXState, dev, dev); + hwaddr pci_hole64_size;
- d->dev.config[I440FX_SMRAM] = 0x02; + f->dev.config[I440FX_SMRAM] = 0x02;
- cpu_smm_register(&i440fx_set_smm, d); - return 0; -} + cpu_smm_register(&i440fx_set_smm, f);
-static PCIBus *i440fx_common_init(const char *device_name, - PCII440FXState **pi440fx_state, - int *piix3_devfn, - ISABus **isa_bus, qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - ram_addr_t ram_size, - hwaddr pci_hole_start, - hwaddr pci_hole_size, - hwaddr pci_hole64_start, - hwaddr pci_hole64_size, - MemoryRegion *pci_address_space, - MemoryRegion *ram_memory) -{ - DeviceState *dev; - PCIBus *b; - PCIDevice *d; - PCIHostState *s; - PIIX3State *piix3; - PCII440FXState *f; - unsigned i; - - dev = qdev_create(NULL, "i440FX-pcihost"); - s = PCI_HOST_BRIDGE(dev); - s->address_space = address_space_mem; - b = pci_bus_new(dev, NULL, pci_address_space, - address_space_io, 0); - s->bus = b; - object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL); - qdev_init_nofail(dev); - - d = pci_create_simple(b, 0, device_name); - *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d); - f = *pi440fx_state; - f->system_memory = address_space_mem; - f->pci_address_space = pci_address_space; - f->ram_memory = ram_memory; + pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 : + ((uint64_t)1 << 62)); memory_region_init_alias(&f->pci_hole, "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); + f->below_4g_mem_size, + 0x100000000LL - f->below_4g_mem_size); + memory_region_add_subregion(f->system_memory, f->below_4g_mem_size, + &f->pci_hole); memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64", f->pci_address_space, - pci_hole64_start, pci_hole64_size); + 0x100000000LL + f->above_4g_mem_size, + pci_hole64_size); if (pci_hole64_size) { - memory_region_add_subregion(f->system_memory, pci_hole64_start, + memory_region_add_subregion(f->system_memory, + 0x100000000LL + f->above_4g_mem_size, &f->pci_hole_64bit); } + memory_region_init_alias(&f->smram_region, "smram-region", f->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(f->system_memory, 0xa0000, &f->smram_region, 1); memory_region_set_enabled(&f->smram_region, false); + init_pam(f->ram_memory, f->system_memory, f->pci_address_space, &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); for (i = 0; i < 12; ++i) { init_pam(f->ram_memory, f->system_memory, f->pci_address_space, - &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, + &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE); } - - /* Xen supports additional interrupt routes from the PCI devices to - * the IOAPIC: the four pins of each PCI device on the bus are also - * connected to the IOAPIC directly. - * These additional routes can be discovered through ACPI. */ - if (xen_enabled()) { - piix3 = DO_UPCAST(PIIX3State, dev, - pci_create_simple_multifunction(b, -1, true, "PIIX3-xen")); - pci_bus_irqs(b, xen_piix3_set_irq, xen_pci_slot_get_pirq, - piix3, XEN_PIIX_NUM_PIRQS); - } else { - piix3 = DO_UPCAST(PIIX3State, dev, - pci_create_simple_multifunction(b, -1, true, "PIIX3")); - pci_bus_irqs(b, piix3_set_irq, pci_slot_get_pirq, piix3, - PIIX_NUM_PIRQS); - pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq); - } - piix3->pic = pic; - *isa_bus = DO_UPCAST(ISABus, qbus, - qdev_get_child_bus(&piix3->dev.qdev, "isa.0")); - - *piix3_devfn = piix3->dev.devfn; - - ram_size = ram_size / 8 / 1024 / 1024; - if (ram_size > 255) - ram_size = 255; - (*pi440fx_state)->dev.config[0x57]=ram_size; - + f->dev.config[0x57] = f->below_4g_mem_size; i440fx_update_memory_mappings(f);
- return b; -} - -PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, - ISABus **isa_bus, qemu_irq *pic, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - ram_addr_t ram_size, - hwaddr pci_hole_start, - hwaddr pci_hole_size, - hwaddr pci_hole64_start, - hwaddr pci_hole64_size, - MemoryRegion *pci_memory, MemoryRegion *ram_memory) - -{ - PCIBus *b; - - b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, isa_bus, pic, - address_space_mem, address_space_io, ram_size, - pci_hole_start, pci_hole_size, - pci_hole64_start, pci_hole64_size, - pci_memory, ram_memory); - return b; + return 0; }
/* PIIX3 PCI to ISA bridge */ -static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq) +void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq) { qemu_set_irq(piix3->pic[pic_irq], !!(piix3->pic_levels & @@ -347,13 +229,13 @@ static void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level) piix3_set_irq_pic(piix3, pic_irq); }
-static void piix3_set_irq(void *opaque, int pirq, int level) +void piix3_set_irq(void *opaque, int pirq, int level) { PIIX3State *piix3 = opaque; piix3_set_irq_level(piix3, pirq, level); }
-static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) +PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) { PIIX3State *piix3 = opaque; int irq = piix3->dev.config[PIIX_PIRQC + pin]; @@ -550,7 +432,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) }
static const TypeInfo i440fx_info = { - .name = "i440FX", + .name = TYPE_I440FX_PCI_DEVICE, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCII440FXState), .class_init = i440fx_class_init, @@ -561,15 +443,16 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = i440fx_pcihost_initfn; + k->init = i440fx_pcihost_init; dc->fw_name = "pci"; dc->no_user = 1; }
static const TypeInfo i440fx_pcihost_info = { - .name = "i440FX-pcihost", + .name = TYPE_I440FX_HOST_DEVICE, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(I440FXState), + .instance_init = i440fx_pcihost_initfn, .class_init = i440fx_pcihost_class_init, };