diff --git a/hw/spapr.c b/hw/spapr.c index bfaf260d5423842171bba488011ff907abd06bc0..cca20f9a5124e65270e84a1308cecdd23251371d 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -631,8 +631,7 @@ static void ppc_spapr_init(ram_addr_t ram_size, for (i = 0; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { - spapr_vty_create(spapr->vio_bus, SPAPR_VTY_BASE_ADDRESS + i, - serial_hds[i]); + spapr_vty_create(spapr->vio_bus, serial_hds[i]); } } @@ -650,14 +649,14 @@ static void ppc_spapr_init(ram_addr_t ram_size, } if (strcmp(nd->model, "ibmveth") == 0) { - spapr_vlan_create(spapr->vio_bus, 0x1000 + i, nd); + spapr_vlan_create(spapr->vio_bus, nd); } else { pci_nic_init_nofail(&nd_table[i], nd->model, NULL); } } for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { - spapr_vscsi_create(spapr->vio_bus, 0x2000 + i); + spapr_vscsi_create(spapr->vio_bus); } if (rma_size < (MIN_RMA_SLOF << 20)) { diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c index e18d2eb901d483c9444097438907fa42104b81e6..8313043652f0132a2dd2da682d30d7a72188963c 100644 --- a/hw/spapr_llan.c +++ b/hw/spapr_llan.c @@ -204,12 +204,11 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev) return 0; } -void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd) +void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd) { DeviceState *dev; dev = qdev_create(&bus->bus, "spapr-vlan"); - qdev_prop_set_uint32(dev, "reg", reg); qdev_set_nic_properties(dev, nd); @@ -480,7 +479,7 @@ static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr, } static Property spapr_vlan_properties[] = { - DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x1000, 0x10000000), + DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x10000000), DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index fccf48bd67638aba2b7319c60696156629ed5478..315ab8091ccc200b8b0991fef6085ff5447782ec 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -620,28 +620,22 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token, rtas_st(rets, 0, 0); } -static int spapr_vio_check_reg(VIOsPAPRDevice *sdev) +static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev) { - VIOsPAPRDevice *other_sdev; + VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus); DeviceState *qdev; - VIOsPAPRBus *sbus; - - sbus = DO_UPCAST(VIOsPAPRBus, bus, sdev->qdev.parent_bus); + VIOsPAPRDevice *other; /* - * Check two device aren't given clashing addresses by the user (or some - * other mechanism). We have to open code this because we have to check - * for matches with devices other than us. + * Check for a device other than the given one which is already + * using the requested address. We have to open code this because + * the given dev might already be in the list. */ - QTAILQ_FOREACH(qdev, &sbus->bus.children, sibling) { - other_sdev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); + QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { + other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); - if (other_sdev != sdev && other_sdev->reg == sdev->reg) { - fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n", - object_get_typename(OBJECT(sdev)), - object_get_typename(OBJECT(qdev)), - sdev->reg); - return -EEXIST; + if (other != dev && other->reg == dev->reg) { + return other; } } @@ -667,11 +661,30 @@ static int spapr_vio_busdev_init(DeviceState *qdev) VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); char *id; - int ret; - ret = spapr_vio_check_reg(dev); - if (ret) { - return ret; + if (dev->reg != -1) { + /* + * Explicitly assigned address, just verify that no-one else + * is using it. other mechanism). We have to open code this + * rather than using spapr_vio_find_by_reg() because sdev + * itself is already in the list. + */ + VIOsPAPRDevice *other = reg_conflict(dev); + + if (other) { + fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n", + object_get_typename(OBJECT(qdev)), + object_get_typename(OBJECT(&other->qdev)), + dev->reg); + return -1; + } + } else { + /* Need to assign an address */ + VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus); + + do { + dev->reg = bus->next_reg++; + } while (reg_conflict(dev)); } /* Don't overwrite ids assigned on the command line */ @@ -731,6 +744,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void) qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio"); bus = DO_UPCAST(VIOsPAPRBus, bus, qbus); + bus->next_reg = 0x1000; /* hcall-vio */ spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal); diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 10ab3594c0e7e6dff17efe8ecdf1105135f0eeba..87816e456d39998ecd6c7475b63e7ba7afe06a4c 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -32,8 +32,6 @@ enum VIOsPAPR_TCEAccess { SPAPR_TCE_RW = 3, }; -#define SPAPR_VTY_BASE_ADDRESS 0x30000000 - #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device" #define VIO_SPAPR_DEVICE(obj) \ OBJECT_CHECK(VIOsPAPRDevice, (obj), TYPE_VIO_SPAPR_DEVICE) @@ -82,13 +80,14 @@ struct VIOsPAPRDevice { VIOsPAPR_CRQ crq; }; -#define DEFINE_SPAPR_PROPERTIES(type, field, default_reg, default_dma_window) \ - DEFINE_PROP_UINT32("reg", type, field.reg, default_reg), \ +#define DEFINE_SPAPR_PROPERTIES(type, field, default_dma_window) \ + DEFINE_PROP_UINT32("reg", type, field.reg, -1), \ DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \ default_dma_window) struct VIOsPAPRBus { BusState bus; + uint32_t next_reg; int (*init)(VIOsPAPRDevice *dev); int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); }; @@ -119,9 +118,9 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq); VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg); void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len); -void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev); -void spapr_vlan_create(VIOsPAPRBus *bus, uint32_t reg, NICInfo *nd); -void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg); +void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev); +void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd); +void spapr_vscsi_create(VIOsPAPRBus *bus); VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus); diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c index 538e0b7938a4045c293c5c09f0ce12e3417c5b22..037867ab4fe7fecede82450c8d9e5a779aa082f3 100644 --- a/hw/spapr_vscsi.c +++ b/hw/spapr_vscsi.c @@ -918,12 +918,11 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev) return 0; } -void spapr_vscsi_create(VIOsPAPRBus *bus, uint32_t reg) +void spapr_vscsi_create(VIOsPAPRBus *bus) { DeviceState *dev; dev = qdev_create(&bus->bus, "spapr-vscsi"); - qdev_prop_set_uint32(dev, "reg", reg); qdev_init_nofail(dev); } @@ -946,7 +945,7 @@ static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off) } static Property spapr_vscsi_properties[] = { - DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x2000, 0x10000000), + DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x10000000), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index a30c040b979c9e857f3cf046ecc36896e131bbd9..c9674f36a64d0f2cebdba2799c5d03cceb09112b 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -123,18 +123,17 @@ static target_ulong h_get_term_char(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } -void spapr_vty_create(VIOsPAPRBus *bus, uint32_t reg, CharDriverState *chardev) +void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev) { DeviceState *dev; dev = qdev_create(&bus->bus, "spapr-vty"); - qdev_prop_set_uint32(dev, "reg", reg); qdev_prop_set_chr(dev, "chardev", chardev); qdev_init_nofail(dev); } static Property spapr_vty_properties[] = { - DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0), + DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0), DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev), DEFINE_PROP_END_OF_LIST(), };