Hi,
On Wed, Jan 16, 2013 at 03:20:40PM +0800, Hu Tao wrote:
Hi Vasilis,
On Tue, Dec 18, 2012 at 01:41:41PM +0100, Vasilis Liaskovitis wrote:
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"
Can't find this file. Did you forget to add this file to git?
sorry, you are right. Below is the corrected patch with the missing header
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 ++++++++++++++------------------------------------------- hw/piix_pci.h | 116 +++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+), 182 deletions(-) create mode 100644 hw/piix_pci.h
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, };
diff --git a/hw/piix_pci.h b/hw/piix_pci.h new file mode 100644 index 0000000..26b3fa0 --- /dev/null +++ b/hw/piix_pci.h @@ -0,0 +1,116 @@ +/* + * piix_pci.h + * + * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * Copyright (C) 2012 Jason Baron jbaron@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see http://www.gnu.org/licenses/ + */ + +#ifndef HW_I440FX_H +#define HW_I440FX_H + +#include "hw.h" +#include "range.h" +#include "isa.h" +#include "sysbus.h" +#include "pc.h" +#include "apm.h" +#include "apic.h" +#include "pci.h" +#include "pcie_host.h" +#include "acpi.h" +#include "pam.h" +#include "dimm.h" + +/* + * I440FX chipset data sheet. + * http://download.intel.com/design/chipsets/datashts/29054901.pdf + */ +#define I440FX_PCI_HOLE_START 0xe0000000 + +#define TYPE_I440FX_HOST_DEVICE "i440FX-pcihost" +#define I440FX_HOST_DEVICE(obj) \ + OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_HOST_DEVICE) + +#define TYPE_I440FX_PCI_DEVICE "i440FX" +#define I440FX_PCI_DEVICE(obj) \ + OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) + +typedef struct PCII440FXState { + PCIDevice dev; + MemoryRegion *system_memory; + MemoryRegion *pci_address_space; + MemoryRegion *ram_memory; + MemoryRegion *address_space_io; + PAMMemoryRegion pam_regions[13]; + MemoryRegion pci_hole; + MemoryRegion pci_hole_64bit; + MemoryRegion smram_region; + uint8_t smm_enabled; + ram_addr_t below_4g_mem_size; + ram_addr_t above_4g_mem_size; + /* i440fx allows for 1 DRAM channels x 8 DRAM ranks */ + DimmBus *dram_channel0; + /* paravirtual memory bus */ + DimmBus *pv_dram_channel; + void *fw_cfg; +} PCII440FXState; + +typedef struct I440FXState { + PCIHostState parent_obj; + PCII440FXState mch; +} 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; + + +int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx); +void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq); +void piix3_set_irq(void *opaque, int pirq, int level); +PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx); +hwaddr i440fx_pmc_dimm_offset(DeviceState *dev, uint64_t size); + +#define I440FX_PAM 0x59 +#define I440FX_PAM_SIZE 7 +#define I440FX_SMRAM 0x72 + +#endif /* HW_I440FX_H */