diff options
Diffstat (limited to 'hw')
67 files changed, 1357 insertions, 628 deletions
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 194c1306c6..2efebf3571 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -38,10 +38,6 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, }); v9fs_path_unlock(s); } - /* The ioctl may not be supported depending on the path */ - if (err == -ENOTTY) { - err = 0; - } return err; } diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index fe8e0ed19d..17002a3d28 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -582,6 +582,7 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir, static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { +#ifdef FS_IOC_GETVERSION int err; V9fsFidOpenState fid_open; @@ -590,7 +591,8 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, * We can get fd for regular files and directories only */ if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { - return 0; + errno = ENOTTY; + return -1; } err = handle_open(ctx, path, O_RDONLY, &fid_open); if (err < 0) { @@ -599,6 +601,10 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); handle_close(ctx, &fid_open); return err; +#else + errno = ENOTTY; + return -1; +#endif } static int handle_init(FsContext *ctx) diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index fc93e9e6e8..df0dbffa7a 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -1068,8 +1068,8 @@ err_out: static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { - int err; #ifdef FS_IOC_GETVERSION + int err; V9fsFidOpenState fid_open; /* @@ -1077,7 +1077,8 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, * We can get fd for regular files and directories only */ if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { - return 0; + errno = ENOTTY; + return -1; } err = local_open(ctx, path, O_RDONLY, &fid_open); if (err < 0) { @@ -1085,10 +1086,11 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, } err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); local_close(ctx, &fid_open); + return err; #else - err = -ENOTTY; + errno = ENOTTY; + return -1; #endif - return err; } static int local_init(FsContext *ctx) diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c index 5f44bb758b..b57966d9d8 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/virtio-9p-proxy.c @@ -1086,7 +1086,8 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path, * we can get fd for regular files and directories only */ if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { - return 0; + errno = ENOTTY; + return -1; } err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, "s", path); if (err < 0) { diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 8cbb8ae32a..83e4e93983 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -1080,10 +1080,18 @@ static void v9fs_getattr(void *opaque) /* fill st_gen if requested and supported by underlying fs */ if (request_mask & P9_STATS_GEN) { retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl); - if (retval < 0) { + switch (retval) { + case 0: + /* we have valid st_gen: update result mask */ + v9stat_dotl.st_result_mask |= P9_STATS_GEN; + break; + case -EINTR: + /* request cancelled, e.g. by Tflush */ goto out; + default: + /* failed to get st_gen: not fatal, ignore */ + break; } - v9stat_dotl.st_result_mask |= P9_STATS_GEN; } retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl); if (retval < 0) { diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 3fa3d7c290..f80c48008c 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -46,13 +46,15 @@ # define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0) #endif -#define PCI_HOTPLUG_ADDR 0xae00 -#define PCI_HOTPLUG_SIZE 0x0014 -#define PCI_UP_BASE 0xae00 -#define PCI_DOWN_BASE 0xae04 -#define PCI_EJ_BASE 0xae08 -#define PCI_RMV_BASE 0xae0c -#define PCI_SEL_BASE 0xae10 +#define ACPI_PCI_HOTPLUG_STATUS 2 +#define ACPI_PCIHP_ADDR 0xae00 +#define ACPI_PCIHP_SIZE 0x0014 +#define ACPI_PCIHP_LEGACY_SIZE 0x000f +#define PCI_UP_BASE 0x0000 +#define PCI_DOWN_BASE 0x0004 +#define PCI_EJ_BASE 0x0008 +#define PCI_RMV_BASE 0x000c +#define PCI_SEL_BASE 0x0010 typedef struct AcpiPciHpFind { int bsel; @@ -104,19 +106,19 @@ static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel) static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + DeviceClass *dc = DEVICE_GET_CLASS(dev); /* * ACPI doesn't allow hotplug of bridge devices. Don't allow * hot-unplug of bridge devices unless they were added by hotplug * (and so, not described by acpi). */ - return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug; + return (pc->is_bridge && !dev->qdev.hotplugged) || !dc->hotpluggable; } static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots) { BusChild *kid, *next; int slot = ffs(slots) - 1; - bool slot_free = true; PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel); if (!bus) { @@ -125,21 +127,17 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo /* Mark request as complete */ s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot); + s->acpi_pcihp_pci_status[bsel].up &= ~(1U << slot); QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) { DeviceState *qdev = kid->child; PCIDevice *dev = PCI_DEVICE(qdev); if (PCI_SLOT(dev->devfn) == slot) { - if (acpi_pcihp_pc_no_hotplug(s, dev)) { - slot_free = false; - } else { + if (!acpi_pcihp_pc_no_hotplug(s, dev)) { object_unparent(OBJECT(qdev)); } } } - if (slot_free) { - s->acpi_pcihp_pci_status[bsel].device_present &= ~(1U << slot); - } } static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) @@ -153,7 +151,6 @@ static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) } s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0; - s->acpi_pcihp_pci_status[bsel].device_present = 0; if (!bus) { return; @@ -166,8 +163,6 @@ static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel) if (acpi_pcihp_pc_no_hotplug(s, pdev)) { s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot); } - - s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); } } @@ -185,40 +180,47 @@ void acpi_pcihp_reset(AcpiPciHpState *s) acpi_pcihp_update(s); } -static void enable_device(AcpiPciHpState *s, unsigned bsel, int slot) -{ - s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); -} - -static void disable_device(AcpiPciHpState *s, unsigned bsel, int slot) -{ - s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); -} - -int acpi_pcihp_device_hotplug(AcpiPciHpState *s, PCIDevice *dev, - PCIHotplugState state) +void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp) { - int slot = PCI_SLOT(dev->devfn); - int bsel = acpi_pcihp_get_bsel(dev->bus); + PCIDevice *pdev = PCI_DEVICE(dev); + int slot = PCI_SLOT(pdev->devfn); + int bsel = acpi_pcihp_get_bsel(pdev->bus); if (bsel < 0) { - return -1; + error_setg(errp, "Unsupported bus. Bus doesn't have property '" + ACPI_PCIHP_PROP_BSEL "' set"); + return; } /* Don't send event when device is enabled during qemu machine creation: * it is present on boot, no hotplug event is necessary. We do send an * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot); - return 0; + if (!dev->hotplugged) { + return; } - if (state == PCI_HOTPLUG_ENABLED) { - enable_device(s, bsel, slot); - } else { - disable_device(s, bsel, slot); + s->acpi_pcihp_pci_status[bsel].up |= (1U << slot); + + ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS; + acpi_update_sci(ar, irq); +} + +void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp) +{ + PCIDevice *pdev = PCI_DEVICE(dev); + int slot = PCI_SLOT(pdev->devfn); + int bsel = acpi_pcihp_get_bsel(pdev->bus); + if (bsel < 0) { + error_setg(errp, "Unsupported bus. Bus doesn't have property '" + ACPI_PCIHP_PROP_BSEL "' set"); + return; } - return 0; + s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); + + ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS; + acpi_update_sci(ar, irq); } static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) @@ -232,26 +234,26 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) } switch (addr) { - case PCI_UP_BASE - PCI_HOTPLUG_ADDR: - /* Manufacture an "up" value to cause a device check on any hotplug - * slot with a device. Extra device checks are harmless. */ - val = s->acpi_pcihp_pci_status[bsel].device_present & - s->acpi_pcihp_pci_status[bsel].hotplug_enable; + case PCI_UP_BASE: + val = s->acpi_pcihp_pci_status[bsel].up; + if (!s->legacy_piix) { + s->acpi_pcihp_pci_status[bsel].up = 0; + } ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val); break; - case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR: + case PCI_DOWN_BASE: val = s->acpi_pcihp_pci_status[bsel].down; ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val); break; - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: + case PCI_EJ_BASE: /* No feature defined yet */ ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val); break; - case PCI_RMV_BASE - PCI_HOTPLUG_ADDR: + case PCI_RMV_BASE: val = s->acpi_pcihp_pci_status[bsel].hotplug_enable; ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val); break; - case PCI_SEL_BASE - PCI_HOTPLUG_ADDR: + case PCI_SEL_BASE: val = s->hotplug_select; ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val); default: @@ -266,7 +268,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data, { AcpiPciHpState *s = opaque; switch (addr) { - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: + case PCI_EJ_BASE: if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) { break; } @@ -274,7 +276,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data, ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, data); break; - case PCI_SEL_BASE - PCI_HOTPLUG_ADDR: + case PCI_SEL_BASE: s->hotplug_select = data; ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, data); @@ -294,13 +296,26 @@ static const MemoryRegionOps acpi_pcihp_io_ops = { }; void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus, - MemoryRegion *address_space_io) + MemoryRegion *address_space_io, bool bridges_enabled) { + uint16_t io_size = ACPI_PCIHP_SIZE; + s->root= root_bus; + s->legacy_piix = !bridges_enabled; + + if (s->legacy_piix) { + unsigned *bus_bsel = g_malloc(sizeof *bus_bsel); + + io_size = ACPI_PCIHP_LEGACY_SIZE; + + *bus_bsel = ACPI_PCIHP_BSEL_DEFAULT; + object_property_add_uint32_ptr(OBJECT(root_bus), ACPI_PCIHP_PROP_BSEL, + bus_bsel, NULL); + } + memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s, - "acpi-pci-hotplug", - PCI_HOTPLUG_SIZE); - memory_region_add_subregion(address_space_io, PCI_HOTPLUG_ADDR, &s->io); + "acpi-pci-hotplug", io_size); + memory_region_add_subregion(address_space_io, ACPI_PCIHP_ADDR, &s->io); } const VMStateDescription vmstate_acpi_pcihp_pci_status = { diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 5d55a3c222..9f21653e94 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -32,6 +32,7 @@ #include "hw/acpi/piix4.h" #include "hw/acpi/pcihp.h" #include "hw/acpi/cpu_hotplug.h" +#include "hw/hotplug.h" //#define DEBUG @@ -44,15 +45,6 @@ #define GPE_BASE 0xafe0 #define GPE_LEN 4 -#define PCI_HOTPLUG_ADDR 0xae00 -#define PCI_HOTPLUG_SIZE 0x000f -#define PCI_UP_BASE 0xae00 -#define PCI_DOWN_BASE 0xae04 -#define PCI_EJ_BASE 0xae08 -#define PCI_RMV_BASE 0xae0c - -#define PIIX4_PCI_HOTPLUG_STATUS 2 - struct pci_status { uint32_t up; /* deprecated, maintained for migration compatibility */ uint32_t down; @@ -80,13 +72,6 @@ typedef struct PIIX4PMState { Notifier machine_ready; Notifier powerdown_notifier; - /* for legacy pci hotplug (compatible with qemu 1.6 and older) */ - MemoryRegion io_pci; - struct pci_status pci0_status; - uint32_t pci0_hotplug_enable; - uint32_t pci0_slot_device_present; - - /* for new pci hotplug (with PCI2PCI bridge support) */ AcpiPciHpState acpi_pci_hotplug; bool use_acpi_pci_hotplug; @@ -170,17 +155,6 @@ static void pm_write_config(PCIDevice *d, } } -static void vmstate_pci_status_pre_save(void *opaque) -{ - struct pci_status *pci0_status = opaque; - PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status); - - /* We no longer track up, so build a safe value for migrating - * to a version that still does... of course these might get lost - * by an old buggy implementation, but we try. */ - pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable; -} - static int vmstate_acpi_post_load(void *opaque, int version_id) { PIIX4PMState *s = opaque; @@ -216,10 +190,9 @@ static const VMStateDescription vmstate_pci_status = { .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, - .pre_save = vmstate_pci_status_pre_save, .fields = (VMStateField []) { - VMSTATE_UINT32(up, struct pci_status), - VMSTATE_UINT32(down, struct pci_status), + VMSTATE_UINT32(up, struct AcpiPciHpPciStatus), + VMSTATE_UINT32(down, struct AcpiPciHpPciStatus), VMSTATE_END_OF_LIST() } }; @@ -256,7 +229,8 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id) qemu_get_be16s(f, &temp); } - ret = vmstate_load_state(f, &vmstate_pci_status, &s->pci0_status, 1); + ret = vmstate_load_state(f, &vmstate_pci_status, + &s->acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], 1); return ret; } @@ -294,70 +268,18 @@ static const VMStateDescription vmstate_acpi = { VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState), VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState), VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE), - VMSTATE_STRUCT_TEST(pci0_status, PIIX4PMState, - vmstate_test_no_use_acpi_pci_hotplug, - 2, vmstate_pci_status, - struct pci_status), + VMSTATE_STRUCT_TEST( + acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], + PIIX4PMState, + vmstate_test_no_use_acpi_pci_hotplug, + 2, vmstate_pci_status, + struct AcpiPciHpPciStatus), VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState, vmstate_test_use_acpi_pci_hotplug), VMSTATE_END_OF_LIST() } }; -static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) -{ - BusChild *kid, *next; - BusState *bus = qdev_get_parent_bus(DEVICE(s)); - int slot = ffs(slots) - 1; - bool slot_free = true; - - /* Mark request as complete */ - s->pci0_status.down &= ~(1U << slot); - - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { - DeviceState *qdev = kid->child; - PCIDevice *dev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - if (PCI_SLOT(dev->devfn) == slot) { - if (pc->no_hotplug) { - slot_free = false; - } else { - object_unparent(OBJECT(qdev)); - } - } - } - if (slot_free) { - s->pci0_slot_device_present &= ~(1U << slot); - } -} - -static void piix4_update_hotplug(PIIX4PMState *s) -{ - BusState *bus = qdev_get_parent_bus(DEVICE(s)); - BusChild *kid, *next; - - /* Execute any pending removes during reset */ - while (s->pci0_status.down) { - acpi_piix_eject_slot(s, s->pci0_status.down); - } - - s->pci0_hotplug_enable = ~0; - s->pci0_slot_device_present = 0; - - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { - DeviceState *qdev = kid->child; - PCIDevice *pdev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev); - int slot = PCI_SLOT(pdev->devfn); - - if (pc->no_hotplug) { - s->pci0_hotplug_enable &= ~(1U << slot); - } - - s->pci0_slot_device_present |= (1U << slot); - } -} - static void piix4_reset(void *opaque) { PIIX4PMState *s = opaque; @@ -377,11 +299,7 @@ static void piix4_reset(void *opaque) pci_conf[0x5B] = 0x02; } pm_io_space_update(s); - if (s->use_acpi_pci_hotplug) { - acpi_pcihp_reset(&s->acpi_pci_hotplug); - } else { - piix4_update_hotplug(s); - } + acpi_pcihp_reset(&s->acpi_pci_hotplug); } static void piix4_pm_powerdown_req(Notifier *n, void *opaque) @@ -392,24 +310,26 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque) acpi_pm1_evt_power_down(&s->ar); } -static int piix4_acpi_pci_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state) +static void piix4_pci_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { - PIIX4PMState *s = PIIX4_PM(qdev); - int ret = acpi_pcihp_device_hotplug(&s->acpi_pci_hotplug, dev, state); - if (ret < 0) { - return ret; - } - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; + PIIX4PMState *s = PIIX4_PM(hotplug_dev); + acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, errp); +} - acpi_update_sci(&s->ar, s->irq); - return 0; +static void piix4_pci_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + PIIX4PMState *s = PIIX4_PM(hotplug_dev); + acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, + errp); } -static void piix4_update_bus_hotplug(PCIBus *bus, void *opaque) +static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque) { PIIX4PMState *s = opaque; - pci_bus_hotplug(bus, piix4_acpi_pci_hotplug, DEVICE(s)); + + qbus_set_hotplug_handler(BUS(pci_bus), DEVICE(s), &error_abort); } static void piix4_pm_machine_ready(Notifier *n, void *opaque) @@ -428,6 +348,8 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque) if (s->use_acpi_pci_hotplug) { pci_for_each_bus(d->bus, piix4_update_bus_hotplug, s); + } else { + piix4_update_bus_hotplug(d->bus, s); } } @@ -545,52 +467,6 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, return s->smb.smbus; } -static Property piix4_pm_properties[] = { - DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), - DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0), - DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0), - DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2), - DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState, - use_acpi_pci_hotplug, true), - DEFINE_PROP_END_OF_LIST(), -}; - -static void piix4_pm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->no_hotplug = 1; - k->init = piix4_pm_initfn; - k->config_write = pm_write_config; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3; - k->revision = 0x03; - k->class_id = PCI_CLASS_BRIDGE_OTHER; - dc->desc = "PM"; - dc->vmsd = &vmstate_acpi; - dc->props = piix4_pm_properties; - /* - * Reason: part of PIIX4 southbridge, needs to be wired up, - * e.g. by mips_malta_init() - */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo piix4_pm_info = { - .name = TYPE_PIIX4_PM, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PIIX4PMState), - .class_init = piix4_pm_class_init, -}; - -static void piix4_pm_register_types(void) -{ - type_register_static(&piix4_pm_info); -} - -type_init(piix4_pm_register_types) - static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width) { PIIX4PMState *s = opaque; @@ -621,60 +497,6 @@ static const MemoryRegionOps piix4_gpe_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size) -{ - PIIX4PMState *s = opaque; - uint32_t val = 0; - - switch (addr) { - case PCI_UP_BASE - PCI_HOTPLUG_ADDR: - /* Manufacture an "up" value to cause a device check on any hotplug - * slot with a device. Extra device checks are harmless. */ - val = s->pci0_slot_device_present & s->pci0_hotplug_enable; - PIIX4_DPRINTF("pci_up_read %" PRIu32 "\n", val); - break; - case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR: - val = s->pci0_status.down; - PIIX4_DPRINTF("pci_down_read %" PRIu32 "\n", val); - break; - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: - /* No feature defined yet */ - PIIX4_DPRINTF("pci_features_read %" PRIu32 "\n", val); - break; - case PCI_RMV_BASE - PCI_HOTPLUG_ADDR: - val = s->pci0_hotplug_enable; - break; - default: - break; - } - - return val; -} - -static void pci_write(void *opaque, hwaddr addr, uint64_t data, - unsigned int size) -{ - switch (addr) { - case PCI_EJ_BASE - PCI_HOTPLUG_ADDR: - acpi_piix_eject_slot(opaque, (uint32_t)data); - PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n", - addr, data); - break; - default: - break; - } -} - -static const MemoryRegionOps piix4_pci_ops = { - .read = pci_read, - .write = pci_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - static void piix4_cpu_added_req(Notifier *n, void *opaque) { PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier); @@ -684,9 +506,6 @@ static void piix4_cpu_added_req(Notifier *n, void *opaque) acpi_update_sci(&s->ar, s->irq); } -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state); - static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, PCIBus *bus, PIIX4PMState *s) { @@ -694,15 +513,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, "acpi-gpe0", GPE_LEN); memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); - if (s->use_acpi_pci_hotplug) { - acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent); - } else { - memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s, - "acpi-pci-hotplug", PCI_HOTPLUG_SIZE); - memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR, - &s->io_pci); - pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s)); - } + acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent, + s->use_acpi_pci_hotplug); AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu, PIIX4_CPU_HOTPLUG_IO_BASE); @@ -710,39 +522,55 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, qemu_register_cpu_added_notifier(&s->cpu_added_notifier); } -static void enable_device(PIIX4PMState *s, int slot) -{ - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_slot_device_present |= (1U << slot); -} +static Property piix4_pm_properties[] = { + DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), + DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0), + DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0), + DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2), + DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState, + use_acpi_pci_hotplug, true), + DEFINE_PROP_END_OF_LIST(), +}; -static void disable_device(PIIX4PMState *s, int slot) +static void piix4_pm_class_init(ObjectClass *klass, void *data) { - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_status.down |= (1U << slot); -} + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state) -{ - int slot = PCI_SLOT(dev->devfn); - PIIX4PMState *s = PIIX4_PM(qdev); - - /* Don't send event when device is enabled during qemu machine creation: - * it is present on boot, no hotplug event is necessary. We do send an - * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - s->pci0_slot_device_present |= (1U << slot); - return 0; - } + k->init = piix4_pm_initfn; + k->config_write = pm_write_config; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3; + k->revision = 0x03; + k->class_id = PCI_CLASS_BRIDGE_OTHER; + dc->desc = "PM"; + dc->vmsd = &vmstate_acpi; + dc->props = piix4_pm_properties; + /* + * Reason: part of PIIX4 southbridge, needs to be wired up, + * e.g. by mips_malta_init() + */ + dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; + hc->plug = piix4_pci_device_plug_cb; + hc->unplug = piix4_pci_device_unplug_cb; +} - if (state == PCI_HOTPLUG_ENABLED) { - enable_device(s, slot); - } else { - disable_device(s, slot); +static const TypeInfo piix4_pm_info = { + .name = TYPE_PIIX4_PM, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PIIX4PMState), + .class_init = piix4_pm_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } } +}; - acpi_update_sci(&s->ar, s->irq); - - return 0; +static void piix4_pm_register_types(void) +{ + type_register_static(&piix4_pm_info); } + +type_init(piix4_pm_register_types) diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 20795ac0fd..1351ba55bd 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -161,8 +161,9 @@ static void clipper_init(QEMUMachineInitArgs *args) load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); - stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL); - stq_phys(param_offset + 0x108, initrd_size); + stq_phys(&address_space_memory, + param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL); + stq_phys(&address_space_memory, param_offset + 0x108, initrd_size); } } } diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index 71a5a37fdc..67a1070281 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -613,7 +613,7 @@ static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret) translation, given the address of the PTE. */ static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret) { - uint64_t pte = ldq_phys(pte_addr); + uint64_t pte = ldq_phys(&address_space_memory, pte_addr); /* Check valid bit. */ if ((pte & 1) == 0) { diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c index 4658e19504..01206f243c 100644 --- a/hw/arm/allwinner-a10.c +++ b/hw/arm/allwinner-a10.c @@ -31,6 +31,13 @@ static void aw_a10_init(Object *obj) object_initialize(&s->timer, sizeof(s->timer), TYPE_AW_A10_PIT); qdev_set_parent_bus(DEVICE(&s->timer), sysbus_get_default()); + + object_initialize(&s->emac, sizeof(s->emac), TYPE_AW_EMAC); + qdev_set_parent_bus(DEVICE(&s->emac), sysbus_get_default()); + if (nd_table[0].used) { + qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC); + qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]); + } } static void aw_a10_realize(DeviceState *dev, Error **errp) @@ -76,6 +83,15 @@ static void aw_a10_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(sysbusdev, 4, s->irq[67]); sysbus_connect_irq(sysbusdev, 5, s->irq[68]); + object_property_set_bool(OBJECT(&s->emac), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + sysbusdev = SYS_BUS_DEVICE(&s->emac); + sysbus_mmio_map(sysbusdev, 0, AW_A10_EMAC_BASE); + sysbus_connect_irq(sysbusdev, 0, s->irq[55]); + serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, s->irq[1], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); } diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 4036262f50..dc62918da2 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -16,6 +16,7 @@ #include "elf.h" #include "sysemu/device_tree.h" #include "qemu/config-file.h" +#include "exec/address-spaces.h" /* Kernel boot protocol is specified in the kernel docs * Documentation/arm/Booting and Documentation/arm64/booting.txt @@ -169,7 +170,7 @@ static void default_reset_secondary(ARMCPU *cpu, { CPUARMState *env = &cpu->env; - stl_phys_notdirty(info->smp_bootreg_addr, 0); + stl_phys_notdirty(&address_space_memory, info->smp_bootreg_addr, 0); env->regs[15] = info->smp_loader_start; } @@ -179,7 +180,7 @@ static inline bool have_dtb(const struct arm_boot_info *info) } #define WRITE_WORD(p, value) do { \ - stl_phys_notdirty(p, value); \ + stl_phys_notdirty(&address_space_memory, p, value); \ p += 4; \ } while (0) diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c index 3fcb6d22f5..d95a7f35eb 100644 --- a/hw/arm/cubieboard.c +++ b/hw/arm/cubieboard.c @@ -36,10 +36,17 @@ static void cubieboard_init(QEMUMachineInitArgs *args) Error *err = NULL; s->a10 = AW_A10(object_new(TYPE_AW_A10)); + + object_property_set_int(OBJECT(&s->a10->emac), 1, "phy-addr", &err); + if (err != NULL) { + error_report("Couldn't set phy address: %s", error_get_pretty(err)); + exit(1); + } + object_property_set_bool(OBJECT(s->a10), true, "realized", &err); if (err != NULL) { - error_report("Couldn't realize Allwinner A10: %s\n", - error_get_pretty(err)); + error_report("Couldn't realize Allwinner A10: %s", + error_get_pretty(err)); exit(1); } diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index d76a1d1f78..f66d57b113 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -69,11 +69,11 @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info) switch (info->nb_cpus) { case 4: - stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0); + stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x30, 0); case 3: - stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0); + stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x20, 0); case 2: - stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0); + stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x10, 0); env->regs[15] = SMP_BOOT_ADDR; break; default: diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 950146c6ff..9e324befd6 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -2,6 +2,7 @@ common-obj-y += qdev.o qdev-properties.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o +common-obj-y += hotplug.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c new file mode 100644 index 0000000000..5573d9d2d9 --- /dev/null +++ b/hw/core/hotplug.c @@ -0,0 +1,48 @@ +/* + * Hotplug handler interface. + * + * Copyright (c) 2014 Red Hat Inc. + * + * Authors: + * Igor Mammedov <imammedo@redhat.com>, + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "hw/hotplug.h" +#include "qemu/module.h" + +void hotplug_handler_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp) +{ + HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); + + if (hdc->plug) { + hdc->plug(plug_handler, plugged_dev, errp); + } +} + +void hotplug_handler_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp) +{ + HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); + + if (hdc->unplug) { + hdc->unplug(plug_handler, plugged_dev, errp); + } +} + +static const TypeInfo hotplug_handler_info = { + .name = TYPE_HOTPLUG_HANDLER, + .parent = TYPE_INTERFACE, + .class_size = sizeof(HotplugHandlerClass), +}; + +static void hotplug_handler_register_types(void) +{ + type_register_static(&hotplug_handler_info); +} + +type_init(hotplug_handler_register_types) diff --git a/hw/core/loader.c b/hw/core/loader.c index 0634bee20c..e1c3f3a860 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -778,7 +778,8 @@ static void rom_reset(void *unused) void *host = memory_region_get_ram_ptr(rom->mr); memcpy(host, rom->data, rom->datasize); } else { - cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize); + cpu_physical_memory_write_rom(&address_space_memory, + rom->addr, rom->data, rom->datasize); } if (rom->isrom) { /* rom needs to be written only once */ diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 82a9123038..64b66e07ef 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -32,6 +32,7 @@ #include "qapi/visitor.h" #include "qapi/qmp/qjson.h" #include "monitor/monitor.h" +#include "hw/hotplug.h" int qdev_hotplug = 0; static bool qdev_hot_added = false; @@ -212,13 +213,22 @@ void qdev_unplug(DeviceState *dev, Error **errp) error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); return; } - assert(dc->unplug != NULL); + + if (!dc->hotpluggable) { + error_set(errp, QERR_DEVICE_NO_HOTPLUG, + object_get_typename(OBJECT(dev))); + return; + } qdev_hot_removed = true; - if (dc->unplug(dev) < 0) { - error_set(errp, QERR_UNDEFINED_ERROR); - return; + if (dev->parent_bus && dev->parent_bus->hotplug_handler) { + hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp); + } else { + assert(dc->unplug != NULL); + if (dc->unplug(dev) < 0) { /* legacy handler */ + error_set(errp, QERR_UNDEFINED_ERROR); + } } } @@ -693,6 +703,11 @@ static void device_set_realized(Object *obj, bool value, Error **err) DeviceClass *dc = DEVICE_GET_CLASS(dev); Error *local_err = NULL; + if (dev->hotplugged && !dc->hotpluggable) { + error_set(err, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj)); + return; + } + if (value && !dev->realized) { if (!obj->parent && local_err == NULL) { static int unattached_count; @@ -708,6 +723,12 @@ static void device_set_realized(Object *obj, bool value, Error **err) dc->realize(dev, &local_err); } + if (dev->parent_bus && dev->parent_bus->hotplug_handler && + local_err == NULL) { + hotplug_handler_plug(dev->parent_bus->hotplug_handler, + dev, &local_err); + } + if (qdev_get_vmsd(dev) && local_err == NULL) { vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev, dev->instance_id_alias, @@ -733,6 +754,14 @@ static void device_set_realized(Object *obj, bool value, Error **err) dev->realized = value; } +static bool device_get_hotpluggable(Object *obj, Error **err) +{ + DeviceClass *dc = DEVICE_GET_CLASS(obj); + DeviceState *dev = DEVICE(obj); + + return dc->hotpluggable && dev->parent_bus->allow_hotplug; +} + static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -749,6 +778,8 @@ static void device_initfn(Object *obj) object_property_add_bool(obj, "realized", device_get_realized, device_set_realized, NULL); + object_property_add_bool(obj, "hotpluggable", + device_get_hotpluggable, NULL, NULL); class = object_get_class(OBJECT(dev)); do { @@ -785,6 +816,14 @@ static void device_class_base_init(ObjectClass *class, void *data) * so do not propagate them to the subclasses. */ klass->props = NULL; + + /* by default all devices were considered as hotpluggable, + * so with intent to check it in generic qdev_unplug() / + * device_set_realized() functions make every device + * hotpluggable. Devices that shouldn't be hotpluggable, + * should override it in their class_init() + */ + klass->hotpluggable = true; } static void device_unparent(Object *obj) @@ -870,6 +909,9 @@ static void qbus_initfn(Object *obj) BusState *bus = BUS(obj); QTAILQ_INIT(&bus->children); + object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, + TYPE_HOTPLUG_HANDLER, + (Object **)&bus->hotplug_handler, NULL); } static char *default_bus_get_fw_dev_path(DeviceState *dev) diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index e4c345fa82..3a8fc0bf8e 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2996,7 +2996,6 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_cirrus_vga_initfn; k->romfile = VGABIOS_CIRRUS_FILENAME; k->vendor_id = PCI_VENDOR_ID_CIRRUS; @@ -3006,6 +3005,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) dc->desc = "Cirrus CLGD 54xx VGA"; dc->vmsd = &vmstate_pci_cirrus_vga; dc->props = pci_vga_cirrus_properties; + dc->hotpluggable = false; } static const TypeInfo cirrus_vga_info = { diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 334c2719f8..1471cc093b 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -2303,7 +2303,6 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = qxl_init_primary; k->romfile = "vgabios-qxl.bin"; k->vendor_id = REDHAT_PCI_VENDOR_ID; @@ -2314,6 +2313,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data) dc->reset = qxl_reset_handler; dc->vmsd = &qxl_vmstate; dc->props = qxl_properties; + dc->hotpluggable = false; } static const TypeInfo qxl_primary_info = { diff --git a/hw/display/sm501.c b/hw/display/sm501.c index c75d6ac63c..0b5f993594 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -30,6 +30,7 @@ #include "hw/sysbus.h" #include "qemu/range.h" #include "ui/pixel_ops.h" +#include "exec/address-spaces.h" /* * Status: 2010/05/07 diff --git a/hw/display/sm501_template.h b/hw/display/sm501_template.h index 2d4a3d8b48..d4cea9e150 100644 --- a/hw/display/sm501_template.h +++ b/hw/display/sm501_template.h @@ -120,7 +120,7 @@ static void glue(draw_hwc_line_, PIXEL_NAME)(SM501State * s, int crt, /* get pixel value */ if (i % 4 == 0) { - bitset = ldub_phys(cursor_addr); + bitset = ldub_phys(&address_space_memory, cursor_addr); cursor_addr++; } v = bitset & 3; diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index b3a45c81da..f74fc43aa6 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -190,7 +190,6 @@ static void vga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_std_vga_initfn; k->romfile = "vgabios-stdvga.bin"; k->vendor_id = PCI_VENDOR_ID_QEMU; @@ -198,6 +197,7 @@ static void vga_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_DISPLAY_VGA; dc->vmsd = &vmstate_vga_pci; dc->props = vga_pci_properties; + dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index aba292ccde..334e71856e 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1296,7 +1296,6 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_vmsvga_initfn; k->romfile = "vgabios-vmware.bin"; k->vendor_id = PCI_VENDOR_ID_VMWARE; @@ -1307,6 +1306,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) dc->reset = vmsvga_reset; dc->vmsd = &vmstate_vmware_vga; dc->props = vga_vmware_properties; + dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index cb7bda9803..741dd20d31 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -8,6 +8,7 @@ */ #include "hw/sysbus.h" +#include "exec/address-spaces.h" #define PL080_MAX_CHANNELS 8 #define PL080_CONF_E 0x1 @@ -204,10 +205,10 @@ again: if (size == 0) { /* Transfer complete. */ if (ch->lli) { - ch->src = ldl_le_phys(ch->lli); - ch->dest = ldl_le_phys(ch->lli + 4); - ch->ctrl = ldl_le_phys(ch->lli + 12); - ch->lli = ldl_le_phys(ch->lli + 8); + ch->src = ldl_le_phys(&address_space_memory, ch->lli); + ch->dest = ldl_le_phys(&address_space_memory, ch->lli + 4); + ch->ctrl = ldl_le_phys(&address_space_memory, ch->lli + 12); + ch->lli = ldl_le_phys(&address_space_memory, ch->lli + 8); } else { ch->conf &= ~PL080_CCONF_E; } diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index a04409a273..723f66d8f2 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -24,6 +24,7 @@ #include "hw/sparc/sun4m.h" #include "hw/sysbus.h" +#include "exec/address-spaces.h" #include "trace.h" /* @@ -262,7 +263,7 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, hwaddr addr) iopte = s->regs[IOMMU_BASE] << 4; addr &= ~s->iostart; iopte += (addr >> (IOMMU_PAGE_SHIFT - 2)) & ~3; - ret = ldl_be_phys(iopte); + ret = ldl_be_phys(&address_space_memory, iopte); trace_sun4m_iommu_page_get_flags(pa, iopte, ret); return ret; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 50e83f3b46..b1a7ebb8e3 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -768,6 +768,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable); for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { + DeviceClass *dc; PCIDeviceClass *pc; PCIDevice *pdev = bus->devices[i]; @@ -776,8 +777,9 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) } pc = PCI_DEVICE_GET_CLASS(pdev); + dc = DEVICE_GET_CLASS(pdev); - if (pc->no_hotplug || pc->is_bridge) { + if (!dc->hotpluggable || pc->is_bridge) { int slot = PCI_SLOT(i); clear_bit(slot, slot_hotplug_enable); diff --git a/hw/i386/acpi-dsdt-hpet.dsl b/hw/i386/acpi-dsdt-hpet.dsl index dfde174317..44961b87a1 100644 --- a/hw/i386/acpi-dsdt-hpet.dsl +++ b/hw/i386/acpi-dsdt-hpet.dsl @@ -39,9 +39,6 @@ Scope(\_SB) { Return (0x0F) } Name(_CRS, ResourceTemplate() { -#if 0 /* This makes WinXP BSOD for not yet figured reasons. */ - IRQNoFlags() {2, 8} -#endif Memory32Fixed(ReadOnly, 0xFED00000, // Address Base 0x00000400, // Address Length diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 348b15f267..e715a3312d 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -835,8 +835,8 @@ static void load_linux(FWCfgState *fw_cfg, initrd_size = get_image_size(initrd_filename); if (initrd_size < 0) { - fprintf(stderr, "qemu: error reading initrd %s\n", - initrd_filename); + fprintf(stderr, "qemu: error reading initrd %s: %s\n", + initrd_filename, strerror(errno)); exit(1); } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index a327d71fb1..1acd2b2a20 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -793,6 +793,17 @@ static QEMUMachine xenfv_machine = { .max_cpus = HVM_MAX_VCPUS, .default_machine_opts = "accel=xen", .hot_add_cpu = pc_hot_add_cpu, + .compat_props = (GlobalProperty[]) { + /* xenfv has no fwcfg and so does not load acpi from QEMU. + * as such new acpi features don't work. + */ + { + .driver = "PIIX4_PM", + .property = "acpi-pci-hotplug-with-bridge-support", + .value = "off", + }, + { /* end of list */ } + }, }; #endif diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 9b5960b44e..0eda301ba9 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -241,13 +241,13 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_piix_ide_initfn; k->exit = pci_piix_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->hotpluggable = false; } static const TypeInfo piix3_ide_info = { @@ -280,13 +280,13 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = pci_piix_ide_initfn; k->exit = pci_piix_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB; k->class_id = PCI_CLASS_STORAGE_IDE; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->hotpluggable = false; } static const TypeInfo piix4_ide_info = { diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 3d3deb6298..361ae90b65 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -129,7 +129,8 @@ static void apic_sync_vapic(APICCommonState *s, int sync_type) } vapic_state.irr = vector & 0xff; - cpu_physical_memory_write_rom(s->vapic_paddr + start, + cpu_physical_memory_write_rom(&address_space_memory, + s->vapic_paddr + start, ((void *)&vapic_state) + start, length); } } diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 1c4a1143af..93eaa6b2fa 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -66,7 +66,7 @@ void gic_update(GICState *s) best_prio = 0x100; best_irq = 1023; for (irq = 0; irq < s->num_irq; irq++) { - if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) { + if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm)) { if (GIC_GET_PRIORITY(irq, cpu) < best_prio) { best_prio = GIC_GET_PRIORITY(irq, cpu); best_irq = irq; @@ -89,14 +89,43 @@ void gic_set_pending_private(GICState *s, int cpu, int irq) { int cm = 1 << cpu; - if (GIC_TEST_PENDING(irq, cm)) + if (gic_test_pending(s, irq, cm)) { return; + } DPRINTF("Set %d pending cpu %d\n", irq, cpu); GIC_SET_PENDING(irq, cm); gic_update(s); } +static void gic_set_irq_11mpcore(GICState *s, int irq, int level, + int cm, int target) +{ + if (level) { + GIC_SET_LEVEL(irq, cm); + if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) { + DPRINTF("Set %d pending mask %x\n", irq, target); + GIC_SET_PENDING(irq, target); + } + } else { + GIC_CLEAR_LEVEL(irq, cm); + } +} + +static void gic_set_irq_generic(GICState *s, int irq, int level, + int cm, int target) +{ + if (level) { + GIC_SET_LEVEL(irq, cm); + DPRINTF("Set %d pending mask %x\n", irq, target); + if (GIC_TEST_EDGE_TRIGGER(irq)) { + GIC_SET_PENDING(irq, target); + } + } else { + GIC_CLEAR_LEVEL(irq, cm); + } +} + /* Process a change in an external IRQ input. */ static void gic_set_irq(void *opaque, int irq, int level) { @@ -122,19 +151,18 @@ static void gic_set_irq(void *opaque, int irq, int level) target = cm; } + assert(irq >= GIC_NR_SGIS); + if (level == GIC_TEST_LEVEL(irq, cm)) { return; } - if (level) { - GIC_SET_LEVEL(irq, cm); - if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) { - DPRINTF("Set %d pending mask %x\n", irq, target); - GIC_SET_PENDING(irq, target); - } + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + gic_set_irq_11mpcore(s, irq, level, cm, target); } else { - GIC_CLEAR_LEVEL(irq, cm); + gic_set_irq_generic(s, irq, level, cm, target); } + gic_update(s); } @@ -151,21 +179,48 @@ static void gic_set_running_irq(GICState *s, int cpu, int irq) uint32_t gic_acknowledge_irq(GICState *s, int cpu) { - int new_irq; + int ret, irq, src; int cm = 1 << cpu; - new_irq = s->current_pending[cpu]; - if (new_irq == 1023 - || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) { + irq = s->current_pending[cpu]; + if (irq == 1023 + || GIC_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) { DPRINTF("ACK no pending IRQ\n"); return 1023; } - s->last_active[new_irq][cpu] = s->running_irq[cpu]; - /* Clear pending flags for both level and edge triggered interrupts. - Level triggered IRQs will be reasserted once they become inactive. */ - GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm); - gic_set_running_irq(s, cpu, new_irq); - DPRINTF("ACK %d\n", new_irq); - return new_irq; + s->last_active[irq][cpu] = s->running_irq[cpu]; + + if (s->revision == REV_11MPCORE) { + /* Clear pending flags for both level and edge triggered interrupts. + * Level triggered IRQs will be reasserted once they become inactive. + */ + GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm); + ret = irq; + } else { + if (irq < GIC_NR_SGIS) { + /* Lookup the source CPU for the SGI and clear this in the + * sgi_pending map. Return the src and clear the overall pending + * state on this CPU if the SGI is not pending from any CPUs. + */ + assert(s->sgi_pending[irq][cpu] != 0); + src = ctz32(s->sgi_pending[irq][cpu]); + s->sgi_pending[irq][cpu] &= ~(1 << src); + if (s->sgi_pending[irq][cpu] == 0) { + GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm); + } + ret = irq | ((src & 0x7) << 10); + } else { + /* Clear pending state for both level and edge triggered + * interrupts. (level triggered interrupts with an active line + * remain pending, see gic_test_pending) + */ + GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm); + ret = irq; + } + } + + gic_set_running_irq(s, cpu, irq); + DPRINTF("ACK %d\n", irq); + return ret; } void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val) @@ -195,14 +250,18 @@ void gic_complete_irq(GICState *s, int cpu, int irq) } if (s->running_irq[cpu] == 1023) return; /* No active IRQ. */ - /* Mark level triggered interrupts as pending if they are still - raised. */ - if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm) - && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) { - DPRINTF("Set %d pending mask %x\n", irq, cm); - GIC_SET_PENDING(irq, cm); - update = 1; + + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + /* Mark level triggered interrupts as pending if they are still + raised. */ + if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm) + && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) { + DPRINTF("Set %d pending mask %x\n", irq, cm); + GIC_SET_PENDING(irq, cm); + update = 1; + } } + if (irq != s->running_irq[cpu]) { /* Complete an IRQ that is not currently running. */ int tmp = s->running_irq[cpu]; @@ -273,7 +332,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset) res = 0; mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK; for (i = 0; i < 8; i++) { - if (GIC_TEST_PENDING(irq + i, mask)) { + if (gic_test_pending(s, irq + i, mask)) { res |= (1 << i); } } @@ -323,6 +382,22 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset) if (GIC_TEST_EDGE_TRIGGER(irq + i)) res |= (2 << (i * 2)); } + } else if (offset < 0xf10) { + goto bad_reg; + } else if (offset < 0xf30) { + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + goto bad_reg; + } + + if (offset < 0xf20) { + /* GICD_CPENDSGIRn */ + irq = (offset - 0xf10); + } else { + irq = (offset - 0xf20); + /* GICD_SPENDSGIRn */ + } + + res = s->sgi_pending[irq][cpu]; } else if (offset < 0xfe0) { goto bad_reg; } else /* offset >= 0xfe0 */ { @@ -497,9 +572,31 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, GIC_CLEAR_EDGE_TRIGGER(irq + i); } } - } else { + } else if (offset < 0xf10) { /* 0xf00 is only handled for 32-bit writes. */ goto bad_reg; + } else if (offset < 0xf20) { + /* GICD_CPENDSGIRn */ + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + goto bad_reg; + } + irq = (offset - 0xf10); + + s->sgi_pending[irq][cpu] &= ~value; + if (s->sgi_pending[irq][cpu] == 0) { + GIC_CLEAR_PENDING(irq, 1 << cpu); + } + } else if (offset < 0xf30) { + /* GICD_SPENDSGIRn */ + if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) { + goto bad_reg; + } + irq = (offset - 0xf20); + + GIC_SET_PENDING(irq, 1 << cpu); + s->sgi_pending[irq][cpu] |= value; + } else { + goto bad_reg; } gic_update(s); return; @@ -523,6 +620,7 @@ static void gic_dist_writel(void *opaque, hwaddr offset, int cpu; int irq; int mask; + int target_cpu; cpu = gic_get_current_cpu(s); irq = value & 0x3ff; @@ -542,6 +640,12 @@ static void gic_dist_writel(void *opaque, hwaddr offset, break; } GIC_SET_PENDING(irq, mask); + target_cpu = ctz32(mask); + while (target_cpu < GIC_NCPU) { + s->sgi_pending[irq][target_cpu] |= (1 << cpu); + mask &= ~(1 << target_cpu); + target_cpu = ctz32(mask); + } gic_update(s); return; } @@ -565,14 +669,17 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset) case 0x04: /* Priority mask */ return s->priority_mask[cpu]; case 0x08: /* Binary Point */ - /* ??? Not implemented. */ - return 0; + return s->bpr[cpu]; case 0x0c: /* Acknowledge */ return gic_acknowledge_irq(s, cpu); case 0x14: /* Running Priority */ return s->running_priority[cpu]; case 0x18: /* Highest Pending Interrupt */ return s->current_pending[cpu]; + case 0x1c: /* Aliased Binary Point */ + return s->abpr[cpu]; + case 0xd0: case 0xd4: case 0xd8: case 0xdc: + return s->apr[(offset - 0xd0) / 4][cpu]; default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_read: Bad offset %x\n", (int)offset); @@ -591,10 +698,18 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value) s->priority_mask[cpu] = (value & 0xff); break; case 0x08: /* Binary Point */ - /* ??? Not implemented. */ + s->bpr[cpu] = (value & 0x7); break; case 0x10: /* End Of Interrupt */ return gic_complete_irq(s, cpu, value & 0x3ff); + case 0x1c: /* Aliased Binary Point */ + if (s->revision >= 2) { + s->abpr[cpu] = (value & 0x7); + } + break; + case 0xd0: case 0xd4: case 0xd8: case 0xdc: + qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n"); + break; default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_write: Bad offset %x\n", (int)offset); diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index e4fc65028a..6d884eca3b 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -58,8 +58,8 @@ static const VMStateDescription vmstate_gic_irq_state = { static const VMStateDescription vmstate_gic = { .name = "arm_gic", - .version_id = 4, - .minimum_version_id = 4, + .version_id = 7, + .minimum_version_id = 7, .pre_save = gic_pre_save, .post_load = gic_post_load, .fields = (VMStateField[]) { @@ -71,10 +71,14 @@ static const VMStateDescription vmstate_gic = { VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU), VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL), VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU), + VMSTATE_UINT8_2DARRAY(sgi_pending, GICState, GIC_NR_SGIS, GIC_NCPU), VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU), VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU), VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU), VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU), + VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU), + VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU), + VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU), VMSTATE_END_OF_LIST() } }; diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index 8c02d5888c..92a6f7a3ff 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -34,7 +34,6 @@ #define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0) #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm) #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm) -#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0) #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm) #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm) #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0) @@ -63,4 +62,19 @@ void gic_update(GICState *s); void gic_init_irqs_and_distributor(GICState *s, int num_irq); void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val); +static inline bool gic_test_pending(GICState *s, int irq, int cm) +{ + if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) { + return s->irq_state[irq].pending & cm; + } else { + /* Edge-triggered interrupts are marked pending on a rising edge, but + * level-triggered interrupts are either considered pending when the + * level is active or if software has explicitly written to + * GICD_ISPENDR to set the state pending. + */ + return (s->irq_state[irq].pending & cm) || + (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_LEVEL(irq, cm)); + } +} + #endif /* !QEMU_ARM_GIC_INTERNAL_H */ diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index def6fe3a0f..492cd22fcf 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -107,7 +107,6 @@ static void piix4_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = piix4_initfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0; @@ -119,6 +118,7 @@ static void piix4_class_init(ObjectClass *klass, void *data) * e.g. by mips_malta_init() */ dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; } static const TypeInfo piix4_info = { diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c index 1a87756246..37cbbfd592 100644 --- a/hw/microblaze/petalogix_ml605_mmu.c +++ b/hw/microblaze/petalogix_ml605_mmu.c @@ -75,7 +75,6 @@ static void petalogix_ml605_init(QEMUMachineInitArgs *args) { ram_addr_t ram_size = args->ram_size; - const char *cpu_model = args->cpu_model; MemoryRegion *address_space_mem = get_system_memory(); DeviceState *dev, *dma, *eth0; Object *ds, *cs; @@ -89,10 +88,8 @@ petalogix_ml605_init(QEMUMachineInitArgs *args) qemu_irq irq[32]; /* init CPUs */ - if (cpu_model == NULL) { - cpu_model = "microblaze"; - } - cpu = cpu_mb_init(cpu_model); + cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU)); + object_property_set_bool(OBJECT(cpu), true, "realized", &error_abort); /* Attach emulated BRAM through the LMB. */ memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram", diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index e42a5b04ab..d1cc23303a 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -31,6 +31,8 @@ #define XILINX_LOCK_KEY 0x767b #define XILINX_UNLOCK_KEY 0xdf0d +#define R_PSS_RST_CTRL_SOFT_RST 0x1 + typedef enum { ARM_PLL_CTRL, DDR_PLL_CTRL, @@ -399,6 +401,9 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, goto bad_reg; } s->reset[(offset - 0x200) / 4] = val; + if (offset == 0x200 && (val & R_PSS_RST_CTRL_SOFT_RST)) { + qemu_system_reset_request(); + } break; case 0x300: s->apu_ctrl = val; diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs index 951cca3a4b..75e80c2c48 100644 --- a/hw/net/Makefile.objs +++ b/hw/net/Makefile.objs @@ -18,6 +18,7 @@ common-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o common-obj-$(CONFIG_XGMAC) += xgmac.o common-obj-$(CONFIG_MIPSNET) += mipsnet.o common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o +common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o common-obj-$(CONFIG_CADENCE) += cadence_gem.o common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c new file mode 100644 index 0000000000..469f2f0ede --- /dev/null +++ b/hw/net/allwinner_emac.c @@ -0,0 +1,539 @@ +/* + * Emulation of Allwinner EMAC Fast Ethernet controller and + * Realtek RTL8201CP PHY + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * This model is based on reverse-engineering of Linux kernel driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + * + */ +#include "hw/sysbus.h" +#include "net/net.h" +#include "qemu/fifo8.h" +#include "hw/net/allwinner_emac.h" +#include <zlib.h> + +static uint8_t padding[60]; + +static void mii_set_link(RTL8201CPState *mii, bool link_ok) +{ + if (link_ok) { + mii->bmsr |= MII_BMSR_LINK_ST; + mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 | + MII_ANAR_CSMACD; + } else { + mii->bmsr &= ~MII_BMSR_LINK_ST; + mii->anlpar = MII_ANAR_TX; + } +} + +static void mii_reset(RTL8201CPState *mii, bool link_ok) +{ + mii->bmcr = MII_BMCR_FD | MII_BMCR_AUTOEN | MII_BMCR_SPEED; + mii->bmsr = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD | + MII_BMSR_10T_HD | MII_BMSR_MFPS | MII_BMSR_AUTONEG; + mii->anar = MII_ANAR_TXFD | MII_ANAR_TX | MII_ANAR_10FD | MII_ANAR_10 | + MII_ANAR_CSMACD; + mii->anlpar = MII_ANAR_TX; + + mii_set_link(mii, link_ok); +} + +static uint16_t RTL8201CP_mdio_read(AwEmacState *s, uint8_t addr, uint8_t reg) +{ + RTL8201CPState *mii = &s->mii; + uint16_t ret = 0xffff; + + if (addr == s->phy_addr) { + switch (reg) { + case MII_BMCR: + return mii->bmcr; + case MII_BMSR: + return mii->bmsr; + case MII_PHYID1: + return RTL8201CP_PHYID1; + case MII_PHYID2: + return RTL8201CP_PHYID2; + case MII_ANAR: + return mii->anar; + case MII_ANLPAR: + return mii->anlpar; + case MII_ANER: + case MII_NSR: + case MII_LBREMR: + case MII_REC: + case MII_SNRDR: + case MII_TEST: + qemu_log_mask(LOG_UNIMP, + "allwinner_emac: read from unimpl. mii reg 0x%x\n", + reg); + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "allwinner_emac: read from invalid mii reg 0x%x\n", + reg); + return 0; + } + } + return ret; +} + +static void RTL8201CP_mdio_write(AwEmacState *s, uint8_t addr, uint8_t reg, + uint16_t value) +{ + RTL8201CPState *mii = &s->mii; + NetClientState *nc; + + if (addr == s->phy_addr) { + switch (reg) { + case MII_BMCR: + if (value & MII_BMCR_RESET) { + nc = qemu_get_queue(s->nic); + mii_reset(mii, !nc->link_down); + } else { + mii->bmcr = value; + } + break; + case MII_ANAR: + mii->anar = value; + break; + case MII_BMSR: + case MII_PHYID1: + case MII_PHYID2: + case MII_ANLPAR: + case MII_ANER: + qemu_log_mask(LOG_GUEST_ERROR, + "allwinner_emac: write to read-only mii reg 0x%x\n", + reg); + break; + case MII_NSR: + case MII_LBREMR: + case MII_REC: + case MII_SNRDR: + case MII_TEST: + qemu_log_mask(LOG_UNIMP, + "allwinner_emac: write to unimpl. mii reg 0x%x\n", + reg); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "allwinner_emac: write to invalid mii reg 0x%x\n", + reg); + } + } +} + +static void aw_emac_update_irq(AwEmacState *s) +{ + qemu_set_irq(s->irq, (s->int_sta & s->int_ctl) != 0); +} + +static void aw_emac_tx_reset(AwEmacState *s, int chan) +{ + fifo8_reset(&s->tx_fifo[chan]); + s->tx_length[chan] = 0; +} + +static void aw_emac_rx_reset(AwEmacState *s) +{ + fifo8_reset(&s->rx_fifo); + s->rx_num_packets = 0; + s->rx_packet_size = 0; + s->rx_packet_pos = 0; +} + +static void fifo8_push_word(Fifo8 *fifo, uint32_t val) +{ + fifo8_push(fifo, val); + fifo8_push(fifo, val >> 8); + fifo8_push(fifo, val >> 16); + fifo8_push(fifo, val >> 24); +} + +static uint32_t fifo8_pop_word(Fifo8 *fifo) +{ + uint32_t ret; + + ret = fifo8_pop(fifo); + ret |= fifo8_pop(fifo) << 8; + ret |= fifo8_pop(fifo) << 16; + ret |= fifo8_pop(fifo) << 24; + + return ret; +} + +static int aw_emac_can_receive(NetClientState *nc) +{ + AwEmacState *s = qemu_get_nic_opaque(nc); + + /* + * To avoid packet drops, allow reception only when there is space + * for a full frame: 1522 + 8 (rx headers) + 2 (padding). + */ + return (s->ctl & EMAC_CTL_RX_EN) && (fifo8_num_free(&s->rx_fifo) >= 1532); +} + +static ssize_t aw_emac_receive(NetClientState *nc, const uint8_t *buf, + size_t size) +{ + AwEmacState *s = qemu_get_nic_opaque(nc); + Fifo8 *fifo = &s->rx_fifo; + size_t padded_size, total_size; + uint32_t crc; + + padded_size = size > 60 ? size : 60; + total_size = QEMU_ALIGN_UP(RX_HDR_SIZE + padded_size + CRC_SIZE, 4); + + if (!(s->ctl & EMAC_CTL_RX_EN) || (fifo8_num_free(fifo) < total_size)) { + return -1; + } + + fifo8_push_word(fifo, EMAC_UNDOCUMENTED_MAGIC); + fifo8_push_word(fifo, EMAC_RX_HEADER(padded_size + CRC_SIZE, + EMAC_RX_IO_DATA_STATUS_OK)); + fifo8_push_all(fifo, buf, size); + crc = crc32(~0, buf, size); + + if (padded_size != size) { + fifo8_push_all(fifo, padding, padded_size - size); + crc = crc32(crc, padding, padded_size - size); + } + + fifo8_push_word(fifo, crc); + fifo8_push_all(fifo, padding, QEMU_ALIGN_UP(padded_size, 4) - padded_size); + s->rx_num_packets++; + + s->int_sta |= EMAC_INT_RX; + aw_emac_update_irq(s); + + return size; +} + +static void aw_emac_cleanup(NetClientState *nc) +{ + AwEmacState *s = qemu_get_nic_opaque(nc); + + s->nic = NULL; +} + +static void aw_emac_reset(DeviceState *dev) +{ + AwEmacState *s = AW_EMAC(dev); + NetClientState *nc = qemu_get_queue(s->nic); + + s->ctl = 0; + s->tx_mode = 0; + s->int_ctl = 0; + s->int_sta = 0; + s->tx_channel = 0; + s->phy_target = 0; + + aw_emac_tx_reset(s, 0); + aw_emac_tx_reset(s, 1); + aw_emac_rx_reset(s); + + mii_reset(&s->mii, !nc->link_down); +} + +static uint64_t aw_emac_read(void *opaque, hwaddr offset, unsigned size) +{ + AwEmacState *s = opaque; + Fifo8 *fifo = &s->rx_fifo; + NetClientState *nc; + uint64_t ret; + + switch (offset) { + case EMAC_CTL_REG: + return s->ctl; + case EMAC_TX_MODE_REG: + return s->tx_mode; + case EMAC_TX_INS_REG: + return s->tx_channel; + case EMAC_RX_CTL_REG: + return s->rx_ctl; + case EMAC_RX_IO_DATA_REG: + if (!s->rx_num_packets) { + qemu_log_mask(LOG_GUEST_ERROR, + "Read IO data register when no packet available"); + return 0; + } + + ret = fifo8_pop_word(fifo); + + switch (s->rx_packet_pos) { + case 0: /* Word is magic header */ + s->rx_packet_pos += 4; + break; + case 4: /* Word is rx info header */ + s->rx_packet_pos += 4; + s->rx_packet_size = QEMU_ALIGN_UP(extract32(ret, 0, 16), 4); + break; + default: /* Word is packet data */ + s->rx_packet_pos += 4; + s->rx_packet_size -= 4; + + if (!s->rx_packet_size) { + s->rx_packet_pos = 0; + s->rx_num_packets--; + nc = qemu_get_queue(s->nic); + if (aw_emac_can_receive(nc)) { + qemu_flush_queued_packets(nc); + } + } + } + return ret; + case EMAC_RX_FBC_REG: + return s->rx_num_packets; + case EMAC_INT_CTL_REG: + return s->int_ctl; + case EMAC_INT_STA_REG: + return s->int_sta; + case EMAC_MAC_MRDD_REG: + return RTL8201CP_mdio_read(s, + extract32(s->phy_target, PHY_ADDR_SHIFT, 8), + extract32(s->phy_target, PHY_REG_SHIFT, 8)); + default: + qemu_log_mask(LOG_UNIMP, + "allwinner_emac: read access to unknown register 0x" + TARGET_FMT_plx "\n", offset); + ret = 0; + } + + return ret; +} + +static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + AwEmacState *s = opaque; + Fifo8 *fifo; + NetClientState *nc = qemu_get_queue(s->nic); + int chan; + + switch (offset) { + case EMAC_CTL_REG: + if (value & EMAC_CTL_RESET) { + aw_emac_reset(DEVICE(s)); + value &= ~EMAC_CTL_RESET; + } + s->ctl = value; + if (aw_emac_can_receive(nc)) { + qemu_flush_queued_packets(nc); + } + break; + case EMAC_TX_MODE_REG: + s->tx_mode = value; + break; + case EMAC_TX_CTL0_REG: + case EMAC_TX_CTL1_REG: + chan = (offset == EMAC_TX_CTL0_REG ? 0 : 1); + if ((value & 1) && (s->ctl & EMAC_CTL_TX_EN)) { + uint32_t len, ret; + const uint8_t *data; + + fifo = &s->tx_fifo[chan]; + len = s->tx_length[chan]; + + if (len > fifo8_num_used(fifo)) { + len = fifo8_num_used(fifo); + qemu_log_mask(LOG_GUEST_ERROR, + "allwinner_emac: TX length > fifo data length\n"); + } + if (len > 0) { + data = fifo8_pop_buf(fifo, len, &ret); + qemu_send_packet(nc, data, ret); + aw_emac_tx_reset(s, chan); + /* Raise TX interrupt */ + s->int_sta |= EMAC_INT_TX_CHAN(chan); + aw_emac_update_irq(s); + } + } + break; + case EMAC_TX_INS_REG: + s->tx_channel = value < NUM_TX_FIFOS ? value : 0; + break; + case EMAC_TX_PL0_REG: + case EMAC_TX_PL1_REG: + chan = (offset == EMAC_TX_PL0_REG ? 0 : 1); + if (value > TX_FIFO_SIZE) { + qemu_log_mask(LOG_GUEST_ERROR, + "allwinner_emac: invalid TX frame length %d\n", + (int)value); + value = TX_FIFO_SIZE; + } + s->tx_length[chan] = value; + break; + case EMAC_TX_IO_DATA_REG: + fifo = &s->tx_fifo[s->tx_channel]; + if (fifo8_num_free(fifo) < 4) { + qemu_log_mask(LOG_GUEST_ERROR, + "allwinner_emac: TX data overruns fifo\n"); + break; + } + fifo8_push_word(fifo, value); + break; + case EMAC_RX_CTL_REG: + s->rx_ctl = value; + break; + case EMAC_RX_FBC_REG: + if (value == 0) { + aw_emac_rx_reset(s); + } + break; + case EMAC_INT_CTL_REG: + s->int_ctl = value; + break; + case EMAC_INT_STA_REG: + s->int_sta &= ~value; + break; + case EMAC_MAC_MADR_REG: + s->phy_target = value; + break; + case EMAC_MAC_MWTD_REG: + RTL8201CP_mdio_write(s, extract32(s->phy_target, PHY_ADDR_SHIFT, 8), + extract32(s->phy_target, PHY_REG_SHIFT, 8), value); + break; + default: + qemu_log_mask(LOG_UNIMP, + "allwinner_emac: write access to unknown register 0x" + TARGET_FMT_plx "\n", offset); + } +} + +static void aw_emac_set_link(NetClientState *nc) +{ + AwEmacState *s = qemu_get_nic_opaque(nc); + + mii_set_link(&s->mii, !nc->link_down); +} + +static const MemoryRegionOps aw_emac_mem_ops = { + .read = aw_emac_read, + .write = aw_emac_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static NetClientInfo net_aw_emac_info = { + .type = NET_CLIENT_OPTIONS_KIND_NIC, + .size = sizeof(NICState), + .can_receive = aw_emac_can_receive, + .receive = aw_emac_receive, + .cleanup = aw_emac_cleanup, + .link_status_changed = aw_emac_set_link, +}; + +static void aw_emac_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + AwEmacState *s = AW_EMAC(obj); + + memory_region_init_io(&s->iomem, OBJECT(s), &aw_emac_mem_ops, s, + "aw_emac", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); +} + +static void aw_emac_realize(DeviceState *dev, Error **errp) +{ + AwEmacState *s = AW_EMAC(dev); + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf, + object_get_typename(OBJECT(dev)), dev->id, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + fifo8_create(&s->rx_fifo, RX_FIFO_SIZE); + fifo8_create(&s->tx_fifo[0], TX_FIFO_SIZE); + fifo8_create(&s->tx_fifo[1], TX_FIFO_SIZE); +} + +static Property aw_emac_properties[] = { + DEFINE_NIC_PROPERTIES(AwEmacState, conf), + DEFINE_PROP_UINT8("phy-addr", AwEmacState, phy_addr, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription vmstate_mii = { + .name = "rtl8201cp", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT16(bmcr, RTL8201CPState), + VMSTATE_UINT16(bmsr, RTL8201CPState), + VMSTATE_UINT16(anar, RTL8201CPState), + VMSTATE_UINT16(anlpar, RTL8201CPState), + VMSTATE_END_OF_LIST() + } +}; + +static int aw_emac_post_load(void *opaque, int version_id) +{ + AwEmacState *s = opaque; + + aw_emac_set_link(qemu_get_queue(s->nic)); + + return 0; +} + +static const VMStateDescription vmstate_aw_emac = { + .name = "allwinner_emac", + .version_id = 1, + .minimum_version_id = 1, + .post_load = aw_emac_post_load, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(mii, AwEmacState, 1, vmstate_mii, RTL8201CPState), + VMSTATE_UINT32(ctl, AwEmacState), + VMSTATE_UINT32(tx_mode, AwEmacState), + VMSTATE_UINT32(rx_ctl, AwEmacState), + VMSTATE_UINT32(int_ctl, AwEmacState), + VMSTATE_UINT32(int_sta, AwEmacState), + VMSTATE_UINT32(phy_target, AwEmacState), + VMSTATE_FIFO8(rx_fifo, AwEmacState), + VMSTATE_UINT32(rx_num_packets, AwEmacState), + VMSTATE_UINT32(rx_packet_size, AwEmacState), + VMSTATE_UINT32(rx_packet_pos, AwEmacState), + VMSTATE_STRUCT_ARRAY(tx_fifo, AwEmacState, NUM_TX_FIFOS, 1, + vmstate_fifo8, Fifo8), + VMSTATE_UINT32_ARRAY(tx_length, AwEmacState, NUM_TX_FIFOS), + VMSTATE_UINT32(tx_channel, AwEmacState), + VMSTATE_END_OF_LIST() + } +}; + +static void aw_emac_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aw_emac_realize; + dc->props = aw_emac_properties; + dc->reset = aw_emac_reset; + dc->vmsd = &vmstate_aw_emac; +} + +static const TypeInfo aw_emac_info = { + .name = TYPE_AW_EMAC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AwEmacState), + .instance_init = aw_emac_init, + .class_init = aw_emac_class_init, +}; + +static void aw_emac_register_types(void) +{ + type_register_static(&aw_emac_info); +} + +type_init(aw_emac_register_types) diff --git a/hw/net/vmware_utils.h b/hw/net/vmware_utils.h index 5307e2ccc9..1099df669d 100644 --- a/hw/net/vmware_utils.h +++ b/hw/net/vmware_utils.h @@ -65,7 +65,7 @@ vmw_shmem_set(hwaddr addr, uint8 val, int len) static inline uint32_t vmw_shmem_ld8(hwaddr addr) { - uint8_t res = ldub_phys(addr); + uint8_t res = ldub_phys(&address_space_memory, addr); VMW_SHPRN("SHMEM load8: %" PRIx64 " (value 0x%X)", addr, res); return res; } @@ -74,13 +74,13 @@ static inline void vmw_shmem_st8(hwaddr addr, uint8_t value) { VMW_SHPRN("SHMEM store8: %" PRIx64 " (value 0x%X)", addr, value); - stb_phys(addr, value); + stb_phys(&address_space_memory, addr, value); } static inline uint32_t vmw_shmem_ld16(hwaddr addr) { - uint16_t res = lduw_le_phys(addr); + uint16_t res = lduw_le_phys(&address_space_memory, addr); VMW_SHPRN("SHMEM load16: %" PRIx64 " (value 0x%X)", addr, res); return res; } @@ -89,13 +89,13 @@ static inline void vmw_shmem_st16(hwaddr addr, uint16_t value) { VMW_SHPRN("SHMEM store16: %" PRIx64 " (value 0x%X)", addr, value); - stw_le_phys(addr, value); + stw_le_phys(&address_space_memory, addr, value); } static inline uint32_t vmw_shmem_ld32(hwaddr addr) { - uint32_t res = ldl_le_phys(addr); + uint32_t res = ldl_le_phys(&address_space_memory, addr); VMW_SHPRN("SHMEM load32: %" PRIx64 " (value 0x%X)", addr, res); return res; } @@ -104,13 +104,13 @@ static inline void vmw_shmem_st32(hwaddr addr, uint32_t value) { VMW_SHPRN("SHMEM store32: %" PRIx64 " (value 0x%X)", addr, value); - stl_le_phys(addr, value); + stl_le_phys(&address_space_memory, addr, value); } static inline uint64_t vmw_shmem_ld64(hwaddr addr) { - uint64_t res = ldq_le_phys(addr); + uint64_t res = ldq_le_phys(&address_space_memory, addr); VMW_SHPRN("SHMEM load64: %" PRIx64 " (value %" PRIx64 ")", addr, res); return res; } @@ -119,7 +119,7 @@ static inline void vmw_shmem_st64(hwaddr addr, uint64_t value) { VMW_SHPRN("SHMEM store64: %" PRIx64 " (value %" PRIx64 ")", addr, value); - stq_le_phys(addr, value); + stq_le_phys(&address_space_memory, addr, value); } /* Macros for simplification of operations on array-style registers */ diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 440e187c46..e68145c52f 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -26,6 +26,7 @@ #include "hw/pci/slotid_cap.h" #include "exec/memory.h" #include "hw/pci/pci_bus.h" +#include "hw/hotplug.h" #define TYPE_PCI_BRIDGE_DEV "pci-bridge" #define PCI_BRIDGE_DEV(obj) \ @@ -136,6 +137,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + k->init = pci_bridge_dev_initfn; k->exit = pci_bridge_dev_exitfn; k->config_write = pci_bridge_dev_write_config; @@ -148,6 +151,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) dc->props = pci_bridge_dev_properties; dc->vmsd = &pci_bridge_dev_vmstate; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + hc->plug = shpc_device_hotplug_cb; + hc->unplug = shpc_device_hot_unplug_cb; } static const TypeInfo pci_bridge_dev_info = { @@ -155,6 +160,10 @@ static const TypeInfo pci_bridge_dev_info = { .parent = TYPE_PCI_BRIDGE, .instance_size = sizeof(PCIBridgeDev), .class_init = pci_bridge_dev_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void pci_bridge_dev_register(void) diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index e89d5c1dfa..ffdc853a62 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -628,7 +628,7 @@ static void piix3_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; - k->no_hotplug = 1; + dc->hotpluggable = false; k->init = piix3_initfn; k->config_write = piix3_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; @@ -656,7 +656,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; - k->no_hotplug = 1; + dc->hotpluggable = false; k->init = piix3_initfn; k->config_write = piix3_write_config_xen; k->vendor_id = PCI_VENDOR_ID_INTEL; @@ -682,7 +682,6 @@ static void i440fx_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->no_hotplug = 1; k->init = i440fx_initfn; k->config_write = i440fx_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; @@ -696,6 +695,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) * host-facing part, which can't be device_add'ed, yet. */ dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; } static const TypeInfo i440fx_info = { diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 042dc8f225..0c948e2c30 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -47,7 +47,7 @@ typedef struct PRePPCIState { PCIHostState parent_obj; MemoryRegion intack; - qemu_irq irq[4]; + qemu_irq irq[PCI_NUM_PINS]; PCIBus pci_bus; RavenPCIState pci_dev; } PREPPCIState; @@ -121,11 +121,11 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) isa_mem_base = 0xc0000000; - for (i = 0; i < 4; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { sysbus_init_irq(dev, &s->irq[i]); } - pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, 4); + pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, PCI_NUM_PINS); memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, s, "pci-conf-idx", 1); diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 2a04d18884..a4a3040d4d 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -291,7 +291,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector) "notify vector 0x%x" " address: 0x%"PRIx64" data: 0x%"PRIx32"\n", vector, msg.address, msg.data); - stl_le_phys(msg.address, msg.data); + stl_le_phys(&address_space_memory, msg.address, msg.data); } /* Normally called by pci_default_write_config(). */ diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 3430770f33..5c49bfc304 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -439,7 +439,7 @@ void msix_notify(PCIDevice *dev, unsigned vector) msg = msix_get_message(dev, vector); - stl_le_phys(msg.address, msg.data); + stl_le_phys(&address_space_memory, msg.address, msg.data); } void msix_reset(PCIDevice *dev) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 1221f32847..4e0701df38 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -35,6 +35,7 @@ #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "exec/address-spaces.h" +#include "hw/hotplug.h" //#define DEBUG_PCI #ifdef DEBUG_PCI @@ -346,13 +347,6 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); } -void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) -{ - bus->qbus.allow_hotplug = 1; - bus->hotplug = hotplug; - bus->hotplug_qdev = qdev; -} - PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, @@ -1761,11 +1755,7 @@ static int pci_qdev_init(DeviceState *qdev) pci_dev->devfn); if (pci_dev == NULL) return -1; - if (qdev->hotplugged && pc->no_hotplug) { - qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev))); - do_pci_unregister_device(pci_dev); - return -1; - } + if (pc->init) { rc = pc->init(pci_dev); if (rc != 0) { @@ -1782,34 +1772,9 @@ static int pci_qdev_init(DeviceState *qdev) } pci_add_option_rom(pci_dev, is_default_rom); - if (bus->hotplug) { - /* Let buses differentiate between hotplug and when device is - * enabled during qemu machine creation. */ - rc = bus->hotplug(bus->hotplug_qdev, pci_dev, - qdev->hotplugged ? PCI_HOTPLUG_ENABLED: - PCI_COLDPLUG_ENABLED); - if (rc != 0) { - int r = pci_unregister_device(&pci_dev->qdev); - assert(!r); - return rc; - } - } return 0; } -static int pci_unplug_device(DeviceState *qdev) -{ - PCIDevice *dev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - - if (pc->no_hotplug) { - qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); - return -1; - } - return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, - PCI_HOTPLUG_DISABLED); -} - PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, const char *name) { @@ -2280,7 +2245,6 @@ static void pci_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = pci_qdev_init; - k->unplug = pci_unplug_device; k->exit = pci_unregister_device; k->bus_type = TYPE_PCI_BUS; k->props = pci_props; diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index ca60cf2177..8ecd11eca2 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -26,6 +26,7 @@ #include "hw/pci/pci_bus.h" #include "hw/pci/pcie_regs.h" #include "qemu/range.h" +#include "qapi/qmp/qerror.h" //#define DEBUG_PCIE #ifdef DEBUG_PCIE @@ -216,28 +217,20 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event) hotplug_event_notify(dev); } -static int pcie_cap_slot_hotplug(DeviceState *qdev, - PCIDevice *pci_dev, PCIHotplugState state) +static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev, + DeviceState *dev, + uint8_t **exp_cap, Error **errp) { - PCIDevice *d = PCI_DEVICE(qdev); - uint8_t *exp_cap = d->config + d->exp.exp_cap; - uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA); - - /* Don't send event when device is enabled during qemu machine creation: - * it is present on boot, no hotplug event is necessary. We do send an - * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_PDS); - return 0; - } + PCIDevice *pci_dev = PCI_DEVICE(dev); + *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap; + uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA); PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state); if (sltsta & PCI_EXP_SLTSTA_EIS) { /* the slot is electromechanically locked. * This error is propagated up to qdev and then to HMP/QMP. */ - return -EBUSY; + error_setg_errno(errp, -EBUSY, "slot is electromechanically locked"); } /* TODO: multifunction hot-plug. @@ -245,18 +238,40 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev, * hot plugged/unplugged. */ assert(PCI_FUNC(pci_dev->devfn) == 0); +} - if (state == PCI_HOTPLUG_ENABLED) { +void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + uint8_t *exp_cap; + + pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp); + + /* Don't send event when device is enabled during qemu machine creation: + * it is present on boot, no hotplug event is necessary. We do send an + * event when the device is disabled later. */ + if (!dev->hotplugged) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); - pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); - } else { - object_unparent(OBJECT(pci_dev)); - pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_PDS); - pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC); + return; } - return 0; + + pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDS); + pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC); +} + +void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + uint8_t *exp_cap; + + pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp); + + object_unparent(OBJECT(dev)); + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDS); + pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC); } /* pci express slot for pci express root/downstream port @@ -305,8 +320,8 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot) dev->exp.hpev_notified = false; - pci_bus_hotplug(pci_bridge_get_sec_bus(PCI_BRIDGE(dev)), - pcie_cap_slot_hotplug, &dev->qdev); + qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))), + DEVICE(dev), NULL); } void pcie_cap_slot_reset(PCIDevice *dev) diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index 2adb0300f4..fa24877955 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -19,6 +19,7 @@ */ #include "hw/pci/pcie_port.h" +#include "hw/hotplug.h" void pcie_port_init_reg(PCIDevice *d) { @@ -149,8 +150,11 @@ static Property pcie_slot_props[] = { static void pcie_slot_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); dc->props = pcie_slot_props; + hc->plug = pcie_cap_slot_hotplug_cb; + hc->unplug = pcie_cap_slot_hot_unplug_cb; } static const TypeInfo pcie_slot_type_info = { @@ -159,6 +163,10 @@ static const TypeInfo pcie_slot_type_info = { .instance_size = sizeof(PCIESlot), .abstract = true, .class_init = pcie_slot_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void pcie_port_register_types(void) diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 576244b9f6..180faa7adb 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -7,6 +7,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" #include "hw/pci/msi.h" +#include "qapi/qmp/qerror.h" /* TODO: model power only and disabled slot states. */ /* TODO: handle SERR and wakeups */ @@ -490,65 +491,93 @@ static const MemoryRegionOps shpc_mmio_ops = { .max_access_size = 4, }, }; - -static int shpc_device_hotplug(DeviceState *qdev, PCIDevice *affected_dev, - PCIHotplugState hotplug_state) +static void shpc_device_hotplug_common(PCIDevice *affected_dev, int *slot, + SHPCDevice *shpc, Error **errp) { int pci_slot = PCI_SLOT(affected_dev->devfn); - uint8_t state; - uint8_t led; - PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev); - SHPCDevice *shpc = d->shpc; - int slot = SHPC_PCI_TO_IDX(pci_slot); - if (pci_slot < SHPC_IDX_TO_PCI(0) || slot >= shpc->nslots) { - error_report("Unsupported PCI slot %d for standard hotplug " - "controller. Valid slots are between %d and %d.", - pci_slot, SHPC_IDX_TO_PCI(0), - SHPC_IDX_TO_PCI(shpc->nslots) - 1); - return -1; + *slot = SHPC_PCI_TO_IDX(pci_slot); + + if (pci_slot < SHPC_IDX_TO_PCI(0) || *slot >= shpc->nslots) { + error_setg(errp, "Unsupported PCI slot %d for standard hotplug " + "controller. Valid slots are between %d and %d.", + pci_slot, SHPC_IDX_TO_PCI(0), + SHPC_IDX_TO_PCI(shpc->nslots) - 1); + return; + } +} + +void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + Error *local_err = NULL; + PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev); + SHPCDevice *shpc = pci_hotplug_dev->shpc; + int slot; + + shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } + /* Don't send event when device is enabled during qemu machine creation: * it is present on boot, no hotplug event is necessary. We do send an * event when the device is disabled later. */ - if (hotplug_state == PCI_COLDPLUG_ENABLED) { + if (!dev->hotplugged) { shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN); shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W, SHPC_SLOT_STATUS_PRSNT_MASK); - return 0; + return; } - if (hotplug_state == PCI_HOTPLUG_DISABLED) { - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON; - state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK); - led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK); - if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) { - shpc_free_devices_in_slot(shpc, slot); - shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN); - shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY, - SHPC_SLOT_STATUS_PRSNT_MASK); - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= - SHPC_SLOT_EVENT_MRL | - SHPC_SLOT_EVENT_PRESENCE; - } + + /* This could be a cancellation of the previous removal. + * We check MRL state to figure out. */ + if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) { + shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN); + shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W, + SHPC_SLOT_STATUS_PRSNT_MASK); + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= + SHPC_SLOT_EVENT_BUTTON | + SHPC_SLOT_EVENT_MRL | + SHPC_SLOT_EVENT_PRESENCE; } else { - /* This could be a cancellation of the previous removal. - * We check MRL state to figure out. */ - if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) { - shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN); - shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W, - SHPC_SLOT_STATUS_PRSNT_MASK); - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= - SHPC_SLOT_EVENT_BUTTON | - SHPC_SLOT_EVENT_MRL | - SHPC_SLOT_EVENT_PRESENCE; - } else { - /* Press attention button to cancel removal */ - shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= - SHPC_SLOT_EVENT_BUTTON; - } + /* Press attention button to cancel removal */ + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= + SHPC_SLOT_EVENT_BUTTON; } shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66); - shpc_interrupt_update(d); - return 0; + shpc_interrupt_update(pci_hotplug_dev); +} + +void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + Error *local_err = NULL; + PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev); + SHPCDevice *shpc = pci_hotplug_dev->shpc; + uint8_t state; + uint8_t led; + int slot; + + shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, errp); + if (local_err) { + return; + } + + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON; + state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK); + led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK); + if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) { + shpc_free_devices_in_slot(shpc, slot); + shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN); + shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY, + SHPC_SLOT_STATUS_PRSNT_MASK); + shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= + SHPC_SLOT_EVENT_MRL | + SHPC_SLOT_EVENT_PRESENCE; + } + shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66); + shpc_interrupt_update(pci_hotplug_dev); } /* Initialize the SHPC structure in bridge's BAR. */ @@ -616,7 +645,8 @@ int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned offset) d, "shpc-mmio", SHPC_SIZEOF(d)); shpc_cap_update_dword(d); memory_region_add_subregion(bar, offset, &shpc->mmio); - pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev); + + qbus_set_hotplug_handler(BUS(sec_bus), DEVICE(d), NULL); d->cap_present |= QEMU_PCI_CAP_SHPC; return 0; diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 7a1cd5d89e..2dd5284532 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -8,7 +8,7 @@ obj-$(CONFIG_PSERIES) += spapr_pci.o obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o obj-y += ppc4xx_pci.o # PReP -obj-y += prep.o +obj-$(CONFIG_PREP) += prep.o # OldWorld PowerMac obj-y += mac_oldworld.o # NewWorld PowerMac diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 8109f92200..ca520e8859 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -44,6 +44,7 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, uint32_t flags) { + CPUState *cs = ENV_GET_CPU(env); ram_addr_t bdloc; int i, n; @@ -52,42 +53,42 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t); else bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t); - stl_be_phys(bdloc + 0x00, bd->bi_memstart); - stl_be_phys(bdloc + 0x04, bd->bi_memsize); - stl_be_phys(bdloc + 0x08, bd->bi_flashstart); - stl_be_phys(bdloc + 0x0C, bd->bi_flashsize); - stl_be_phys(bdloc + 0x10, bd->bi_flashoffset); - stl_be_phys(bdloc + 0x14, bd->bi_sramstart); - stl_be_phys(bdloc + 0x18, bd->bi_sramsize); - stl_be_phys(bdloc + 0x1C, bd->bi_bootflags); - stl_be_phys(bdloc + 0x20, bd->bi_ipaddr); + stl_be_phys(cs->as, bdloc + 0x00, bd->bi_memstart); + stl_be_phys(cs->as, bdloc + 0x04, bd->bi_memsize); + stl_be_phys(cs->as, bdloc + 0x08, bd->bi_flashstart); + stl_be_phys(cs->as, bdloc + 0x0C, bd->bi_flashsize); + stl_be_phys(cs->as, bdloc + 0x10, bd->bi_flashoffset); + stl_be_phys(cs->as, bdloc + 0x14, bd->bi_sramstart); + stl_be_phys(cs->as, bdloc + 0x18, bd->bi_sramsize); + stl_be_phys(cs->as, bdloc + 0x1C, bd->bi_bootflags); + stl_be_phys(cs->as, bdloc + 0x20, bd->bi_ipaddr); for (i = 0; i < 6; i++) { - stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]); + stb_phys(cs->as, bdloc + 0x24 + i, bd->bi_enetaddr[i]); } - stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed); - stl_be_phys(bdloc + 0x2C, bd->bi_intfreq); - stl_be_phys(bdloc + 0x30, bd->bi_busfreq); - stl_be_phys(bdloc + 0x34, bd->bi_baudrate); + stw_be_phys(cs->as, bdloc + 0x2A, bd->bi_ethspeed); + stl_be_phys(cs->as, bdloc + 0x2C, bd->bi_intfreq); + stl_be_phys(cs->as, bdloc + 0x30, bd->bi_busfreq); + stl_be_phys(cs->as, bdloc + 0x34, bd->bi_baudrate); for (i = 0; i < 4; i++) { - stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]); + stb_phys(cs->as, bdloc + 0x38 + i, bd->bi_s_version[i]); } for (i = 0; i < 32; i++) { - stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]); + stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]); } - stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq); - stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq); + stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_plb_busfreq); + stl_be_phys(cs->as, bdloc + 0x60, bd->bi_pci_busfreq); for (i = 0; i < 6; i++) { - stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]); + stb_phys(cs->as, bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]); } n = 0x6A; if (flags & 0x00000001) { for (i = 0; i < 6; i++) - stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]); + stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]); } - stl_be_phys(bdloc + n, bd->bi_opbfreq); + stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq); n += 4; for (i = 0; i < 2; i++) { - stl_be_phys(bdloc + n, bd->bi_iic_fast[i]); + stl_be_phys(cs->as, bdloc + n, bd->bi_iic_fast[i]); n += 4; } diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index aad0f69117..9f8538cd20 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -656,7 +656,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET]; portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep"); - portio_list_add(port_list, get_system_io(), 0x0); + portio_list_add(port_list, isa_address_space_io(isa), 0x0); /* PowerPC control and status register group */ #if 0 diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index f755a53923..3ffcc65f03 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -341,6 +341,7 @@ static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) { + CPUState *cs = ENV_GET_CPU(env); uint16_t size; uint8_t tmp; @@ -354,7 +355,7 @@ static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) } /* FIXME: bounds check the address */ - size = lduw_be_phys(vpa + 0x4); + size = lduw_be_phys(cs->as, vpa + 0x4); if (size < VPA_MIN_SIZE) { return H_PARAMETER; @@ -367,9 +368,9 @@ static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) env->vpa_addr = vpa; - tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET); + tmp = ldub_phys(cs->as, env->vpa_addr + VPA_SHARED_PROC_OFFSET); tmp |= VPA_SHARED_PROC_VAL; - stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp); + stb_phys(cs->as, env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp); return H_SUCCESS; } @@ -390,6 +391,7 @@ static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa) static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) { + CPUState *cs = ENV_GET_CPU(env); uint32_t size; if (addr == 0) { @@ -397,7 +399,7 @@ static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) return H_HARDWARE; } - size = ldl_be_phys(addr + 0x4); + size = ldl_be_phys(cs->as, addr + 0x4); if (size < 0x8) { return H_PARAMETER; } @@ -425,6 +427,7 @@ static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr) static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) { + CPUState *cs = ENV_GET_CPU(env); uint32_t size; if (addr == 0) { @@ -432,7 +435,7 @@ static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) return H_HARDWARE; } - size = ldl_be_phys(addr + 0x4); + size = ldl_be_phys(cs->as, addr + 0x4); if (size < 48) { return H_PARAMETER; @@ -532,21 +535,22 @@ static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUState *cs = CPU(cpu); target_ulong size = args[0]; target_ulong addr = args[1]; switch (size) { case 1: - args[0] = ldub_phys(addr); + args[0] = ldub_phys(cs->as, addr); return H_SUCCESS; case 2: - args[0] = lduw_phys(addr); + args[0] = lduw_phys(cs->as, addr); return H_SUCCESS; case 4: - args[0] = ldl_phys(addr); + args[0] = ldl_phys(cs->as, addr); return H_SUCCESS; case 8: - args[0] = ldq_phys(addr); + args[0] = ldq_phys(cs->as, addr); return H_SUCCESS; } return H_PARAMETER; @@ -555,22 +559,24 @@ static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUState *cs = CPU(cpu); + target_ulong size = args[0]; target_ulong addr = args[1]; target_ulong val = args[2]; switch (size) { case 1: - stb_phys(addr, val); + stb_phys(cs->as, addr, val); return H_SUCCESS; case 2: - stw_phys(addr, val); + stw_phys(cs->as, addr, val); return H_SUCCESS; case 4: - stl_phys(addr, val); + stl_phys(cs->as, addr, val); return H_SUCCESS; case 8: - stq_phys(addr, val); + stq_phys(cs->as, addr, val); return H_SUCCESS; } return H_PARAMETER; @@ -579,6 +585,8 @@ static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr, static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { + CPUState *cs = CPU(cpu); + target_ulong dst = args[0]; /* Destination address */ target_ulong src = args[1]; /* Source address */ target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */ @@ -605,16 +613,16 @@ static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr, while (count--) { switch (esize) { case 0: - tmp = ldub_phys(src); + tmp = ldub_phys(cs->as, src); break; case 1: - tmp = lduw_phys(src); + tmp = lduw_phys(cs->as, src); break; case 2: - tmp = ldl_phys(src); + tmp = ldl_phys(cs->as, src); break; case 3: - tmp = ldq_phys(src); + tmp = ldq_phys(cs->as, src); break; default: return H_PARAMETER; @@ -624,16 +632,16 @@ static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr, } switch (esize) { case 0: - stb_phys(dst, tmp); + stb_phys(cs->as, dst, tmp); break; case 1: - stw_phys(dst, tmp); + stw_phys(cs->as, dst, tmp); break; case 2: - stl_phys(dst, tmp); + stl_phys(cs->as, dst, tmp); break; case 3: - stq_phys(dst, tmp); + stq_phys(cs->as, dst, tmp); break; } dst = dst + step; diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 101da63d04..75b04b45af 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -11,6 +11,7 @@ #include <hw/qdev.h> #include "qemu/bitops.h" +#include "exec/address-spaces.h" #include "cpu.h" #include "ioinst.h" #include "css.h" @@ -667,18 +668,20 @@ static void css_update_chnmon(SubchDev *sch) /* Format 1, per-subchannel area. */ uint32_t count; - count = ldl_phys(sch->curr_status.mba); + count = ldl_phys(&address_space_memory, sch->curr_status.mba); count++; - stl_phys(sch->curr_status.mba, count); + stl_phys(&address_space_memory, sch->curr_status.mba, count); } else { /* Format 0, global area. */ uint32_t offset; uint16_t count; offset = sch->curr_status.pmcw.mbi << 5; - count = lduw_phys(channel_subsys->chnmon_area + offset); + count = lduw_phys(&address_space_memory, + channel_subsys->chnmon_area + offset); count++; - stw_phys(channel_subsys->chnmon_area + offset, count); + stw_phys(&address_space_memory, + channel_subsys->chnmon_area + offset, count); } } diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 46c5ff1898..e4fc35366b 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -77,10 +77,10 @@ void s390_virtio_reset_idx(VirtIOS390Device *dev) for (i = 0; i < num_vq; i++) { idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + VIRTIO_VRING_AVAIL_IDX_OFFS; - stw_phys(idx_addr, 0); + stw_phys(&address_space_memory, idx_addr, 0); idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + VIRTIO_VRING_USED_IDX_OFFS; - stw_phys(idx_addr, 0); + stw_phys(&address_space_memory, idx_addr, 0); } } @@ -324,7 +324,7 @@ static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) (vq * VIRTIO_VQCONFIG_LEN) + VIRTIO_VQCONFIG_OFFS_TOKEN; - return ldq_be_phys(token_off); + return ldq_be_phys(&address_space_memory, token_off); } static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev) @@ -359,15 +359,21 @@ void s390_virtio_device_sync(VirtIOS390Device *dev) virtio_reset(dev->vdev); /* Sync dev space */ - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id); + stb_phys(&address_space_memory, + dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, s390_virtio_device_num_vq(dev)); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len); + stb_phys(&address_space_memory, + dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, + s390_virtio_device_num_vq(dev)); + stb_phys(&address_space_memory, + dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len); + stb_phys(&address_space_memory, + dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len); num_vq = s390_virtio_device_num_vq(dev); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq); + stb_phys(&address_space_memory, + dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq); /* Sync virtqueues */ for (i = 0; i < num_vq; i++) { @@ -378,8 +384,11 @@ void s390_virtio_device_sync(VirtIOS390Device *dev) vring = s390_virtio_next_ring(bus); virtio_queue_set_addr(dev->vdev, i, vring); virtio_queue_set_vector(dev->vdev, i, i); - stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring); - stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i)); + stq_be_phys(&address_space_memory, + vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring); + stw_be_phys(&address_space_memory, + vq + VIRTIO_VQCONFIG_OFFS_NUM, + virtio_queue_get_num(dev->vdev, i)); } cur_offs = dev->dev_offs; @@ -387,7 +396,7 @@ void s390_virtio_device_sync(VirtIOS390Device *dev) cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; /* Sync feature bitmap */ - stl_le_phys(cur_offs, dev->host_features); + stl_le_phys(&address_space_memory, cur_offs, dev->host_features); dev->feat_offs = cur_offs + dev->feat_len; cur_offs += dev->feat_len * 2; @@ -405,11 +414,12 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev) VirtIODevice *vdev = dev->vdev; uint32_t features; - virtio_set_status(vdev, ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS)); + virtio_set_status(vdev, ldub_phys(&address_space_memory, + dev->dev_offs + VIRTIO_DEV_OFFS_STATUS)); /* Update guest supported feature bitmap */ - features = bswap32(ldl_be_phys(dev->feat_offs)); + features = bswap32(ldl_be_phys(&address_space_memory, dev->feat_offs)); virtio_set_features(vdev, features); } diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 7adf92af51..9eeda97920 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -91,7 +91,7 @@ static int s390_virtio_hcall_reset(const uint64_t *args) return -EINVAL; } virtio_reset(dev->vdev); - stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); + stb_phys(&address_space_memory, dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); s390_virtio_device_sync(dev); s390_virtio_reset_idx(dev); diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index bc8871249d..f6e0e3e4ae 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -262,11 +262,14 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - info.queue = ldq_phys(ccw.cda); - info.align = ldl_phys(ccw.cda + sizeof(info.queue)); - info.index = lduw_phys(ccw.cda + sizeof(info.queue) + info.queue = ldq_phys(&address_space_memory, ccw.cda); + info.align = ldl_phys(&address_space_memory, + ccw.cda + sizeof(info.queue)); + info.index = lduw_phys(&address_space_memory, + ccw.cda + sizeof(info.queue) + sizeof(info.align)); - info.num = lduw_phys(ccw.cda + sizeof(info.queue) + info.num = lduw_phys(&address_space_memory, + ccw.cda + sizeof(info.queue) + sizeof(info.align) + sizeof(info.index)); ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index, @@ -293,14 +296,15 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - features.index = ldub_phys(ccw.cda + sizeof(features.features)); + features.index = ldub_phys(&address_space_memory, + ccw.cda + sizeof(features.features)); if (features.index < ARRAY_SIZE(dev->host_features)) { features.features = dev->host_features[features.index]; } else { /* Return zeroes if the guest supports more feature bits. */ features.features = 0; } - stl_le_phys(ccw.cda, features.features); + stl_le_phys(&address_space_memory, ccw.cda, features.features); sch->curr_status.scsw.count = ccw.count - sizeof(features); ret = 0; } @@ -319,8 +323,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - features.index = ldub_phys(ccw.cda + sizeof(features.features)); - features.features = ldl_le_phys(ccw.cda); + features.index = ldub_phys(&address_space_memory, + ccw.cda + sizeof(features.features)); + features.features = ldl_le_phys(&address_space_memory, ccw.cda); if (features.index < ARRAY_SIZE(dev->host_features)) { virtio_bus_set_vdev_features(&dev->bus, features.features); vdev->guest_features = features.features; @@ -397,7 +402,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - status = ldub_phys(ccw.cda); + status = ldub_phys(&address_space_memory, ccw.cda); if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { virtio_ccw_stop_ioeventfd(dev); } @@ -426,7 +431,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - indicators = ldq_phys(ccw.cda); + indicators = ldq_phys(&address_space_memory, ccw.cda); dev->indicators = indicators; sch->curr_status.scsw.count = ccw.count - sizeof(indicators); ret = 0; @@ -446,7 +451,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - indicators = ldq_phys(ccw.cda); + indicators = ldq_phys(&address_space_memory, ccw.cda); dev->indicators2 = indicators; sch->curr_status.scsw.count = ccw.count - sizeof(indicators); ret = 0; @@ -466,10 +471,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - vq_config.index = lduw_phys(ccw.cda); + vq_config.index = lduw_phys(&address_space_memory, ccw.cda); vq_config.num_max = virtio_queue_get_num(vdev, vq_config.index); - stw_phys(ccw.cda + sizeof(vq_config.index), vq_config.num_max); + stw_phys(&address_space_memory, + ccw.cda + sizeof(vq_config.index), vq_config.num_max); sch->curr_status.scsw.count = ccw.count - sizeof(vq_config); ret = 0; } @@ -866,17 +872,17 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector) if (!dev->indicators) { return; } - indicators = ldq_phys(dev->indicators); + indicators = ldq_phys(&address_space_memory, dev->indicators); indicators |= 1ULL << vector; - stq_phys(dev->indicators, indicators); + stq_phys(&address_space_memory, dev->indicators, indicators); } else { if (!dev->indicators2) { return; } vector = 0; - indicators = ldq_phys(dev->indicators2); + indicators = ldq_phys(&address_space_memory, dev->indicators2); indicators |= 1ULL << vector; - stq_phys(dev->indicators2, indicators); + stq_phys(&address_space_memory, dev->indicators2, indicators); } css_conditional_io_interrupt(sch); diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 7c5a1a2b3a..59570e2b2b 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -144,12 +144,14 @@ static bool megasas_is_jbod(MegasasState *s) static void megasas_frame_set_cmd_status(unsigned long frame, uint8_t v) { - stb_phys(frame + offsetof(struct mfi_frame_header, cmd_status), v); + stb_phys(&address_space_memory, + frame + offsetof(struct mfi_frame_header, cmd_status), v); } static void megasas_frame_set_scsi_status(unsigned long frame, uint8_t v) { - stb_phys(frame + offsetof(struct mfi_frame_header, scsi_status), v); + stb_phys(&address_space_memory, + frame + offsetof(struct mfi_frame_header, scsi_status), v); } /* @@ -158,7 +160,8 @@ static void megasas_frame_set_scsi_status(unsigned long frame, uint8_t v) */ static uint64_t megasas_frame_get_context(unsigned long frame) { - return ldq_le_phys(frame + offsetof(struct mfi_frame_header, context)); + return ldq_le_phys(&address_space_memory, + frame + offsetof(struct mfi_frame_header, context)); } static bool megasas_frame_is_ieee_sgl(MegasasCmd *cmd) @@ -516,10 +519,12 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) tail = s->reply_queue_head; if (megasas_use_queue64(s)) { queue_offset = tail * sizeof(uint64_t); - stq_le_phys(s->reply_queue_pa + queue_offset, context); + stq_le_phys(&address_space_memory, + s->reply_queue_pa + queue_offset, context); } else { queue_offset = tail * sizeof(uint32_t); - stl_le_phys(s->reply_queue_pa + queue_offset, context); + stl_le_phys(&address_space_memory, + s->reply_queue_pa + queue_offset, context); } s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds); trace_megasas_qf_complete(context, tail, queue_offset, @@ -602,8 +607,8 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd) pa_lo = le32_to_cpu(initq->pi_addr_lo); pa_hi = le32_to_cpu(initq->pi_addr_hi); s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo; - s->reply_queue_head = ldl_le_phys(s->producer_pa); - s->reply_queue_tail = ldl_le_phys(s->consumer_pa); + s->reply_queue_head = ldl_le_phys(&address_space_memory, s->producer_pa); + s->reply_queue_tail = ldl_le_phys(&address_space_memory, s->consumer_pa); flags = le32_to_cpu(initq->flags); if (flags & MFI_QUEUE_FLAG_CONTEXT64) { s->flags |= MEGASAS_MASK_USE_QUEUE64; @@ -1949,7 +1954,8 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, if (s->producer_pa && megasas_intr_enabled(s)) { /* Update reply queue pointer */ trace_megasas_qf_update(s->reply_queue_head, s->busy); - stl_le_phys(s->producer_pa, s->reply_queue_head); + stl_le_phys(&address_space_memory, + s->producer_pa, s->reply_queue_head); if (!msix_enabled(pci_dev)) { trace_megasas_irq_lower(); pci_irq_deassert(pci_dev); diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 94b328f186..7d344b944e 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -43,9 +43,11 @@ (sizeof(PVSCSICmdDescSetupRings)/sizeof(uint32_t)) #define RS_GET_FIELD(rs_pa, field) \ - (ldl_le_phys(rs_pa + offsetof(struct PVSCSIRingsState, field))) + (ldl_le_phys(&address_space_memory, \ + rs_pa + offsetof(struct PVSCSIRingsState, field))) #define RS_SET_FIELD(rs_pa, field, val) \ - (stl_le_phys(rs_pa + offsetof(struct PVSCSIRingsState, field), val)) + (stl_le_phys(&address_space_memory, \ + rs_pa + offsetof(struct PVSCSIRingsState, field), val)) #define TYPE_PVSCSI "pvscsi" #define PVSCSI(obj) OBJECT_CHECK(PVSCSIState, (obj), TYPE_PVSCSI) diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c index 7b1de85835..eaeb7ede4e 100644 --- a/hw/sh4/r2d.c +++ b/hw/sh4/r2d.c @@ -318,8 +318,8 @@ static void r2d_init(QEMUMachineInitArgs *args) } /* initialization which should be done by firmware */ - stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */ - stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */ + stl_phys(&address_space_memory, SH7750_BCR1, 1<<3); /* cs3 SDRAM */ + stw_phys(&address_space_memory, SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */ reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */ } diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 94f79508d8..2957d90177 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -577,7 +577,8 @@ static void idreg_init(hwaddr addr) s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, addr); - cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data)); + cpu_physical_memory_write_rom(&address_space_memory, + addr, idreg_data, sizeof(idreg_data)); } #define MACIO_ID_REGISTER(obj) \ diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 2fbbeb1735..1264dfd46a 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -206,7 +206,8 @@ static void update_irq(struct HPETTimer *timer, int set) } } } else if (timer_fsb_route(timer)) { - stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff); + stl_le_phys(&address_space_memory, + timer->fsb >> 32, timer->fsb & 0xffffffff); } else if (timer->config & HPET_TN_TYPE_LEVEL) { s->isr |= mask; /* fold the ICH PIRQ# pin's internal inversion logic into hpet */ diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 0c985942f9..484a9bd059 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -123,7 +123,7 @@ static void ehci_class_init(ObjectClass *klass, void *data) k->init = usb_ehci_pci_initfn; k->class_id = PCI_CLASS_SERIAL_USB; k->config_write = usb_ehci_pci_write_config; - k->no_hotplug = 1; + dc->hotpluggable = false; dc->vmsd = &vmstate_ehci_pci; dc->props = ehci_pci_properties; } diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index e38cdebfec..3d35058b14 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1993,10 +1993,10 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; k->class_id = PCI_CLASS_SERIAL_USB; - k->no_hotplug = 1; set_bit(DEVICE_CATEGORY_USB, dc->categories); dc->desc = "Apple USB Controller"; dc->props = ohci_pci_properties; + dc->hotpluggable = false; } static const TypeInfo ohci_pci_info = { diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 238d1d2b5f..ad814b58d4 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1318,7 +1318,7 @@ static void uhci_class_init(ObjectClass *klass, void *data) k->device_id = info->device_id; k->revision = info->revision; k->class_id = PCI_CLASS_SERIAL_USB; - k->no_hotplug = 1; + dc->hotpluggable = false; dc->vmsd = &vmstate_uhci; dc->props = uhci_properties; set_bit(DEVICE_CATEGORY_USB, dc->categories); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index bafe08590b..0fa814ee09 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3798,6 +3798,7 @@ static void xhci_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_xhci; dc->props = xhci_properties; dc->reset = xhci_reset; + dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_USB, dc->categories); k->init = usb_xhci_initfn; k->vendor_id = PCI_VENDOR_ID_NEC; @@ -3805,7 +3806,6 @@ static void xhci_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_SERIAL_USB; k->revision = 0x03; k->is_express = 1; - k->no_hotplug = 1; } static const TypeInfo xhci_info = { diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index a001e668c4..aeabf3a459 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -14,6 +14,7 @@ #include <inttypes.h> #include "trace.h" +#include "exec/address-spaces.h" #include "qemu/error-report.h" #include "hw/virtio/virtio.h" #include "qemu/atomic.h" @@ -104,49 +105,49 @@ static inline uint64_t vring_desc_addr(hwaddr desc_pa, int i) { hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr); - return ldq_phys(pa); + return ldq_phys(&address_space_memory, pa); } static inline uint32_t vring_desc_len(hwaddr desc_pa, int i) { hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len); - return ldl_phys(pa); + return ldl_phys(&address_space_memory, pa); } static inline uint16_t vring_desc_flags(hwaddr desc_pa, int i) { hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags); - return lduw_phys(pa); + return lduw_phys(&address_space_memory, pa); } static inline uint16_t vring_desc_next(hwaddr desc_pa, int i) { hwaddr pa; pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next); - return lduw_phys(pa); + return lduw_phys(&address_space_memory, pa); } static inline uint16_t vring_avail_flags(VirtQueue *vq) { hwaddr pa; pa = vq->vring.avail + offsetof(VRingAvail, flags); - return lduw_phys(pa); + return lduw_phys(&address_space_memory, pa); } static inline uint16_t vring_avail_idx(VirtQueue *vq) { hwaddr pa; pa = vq->vring.avail + offsetof(VRingAvail, idx); - return lduw_phys(pa); + return lduw_phys(&address_space_memory, pa); } static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) { hwaddr pa; pa = vq->vring.avail + offsetof(VRingAvail, ring[i]); - return lduw_phys(pa); + return lduw_phys(&address_space_memory, pa); } static inline uint16_t vring_used_event(VirtQueue *vq) @@ -158,42 +159,44 @@ static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, ring[i].id); - stl_phys(pa, val); + stl_phys(&address_space_memory, pa, val); } static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, ring[i].len); - stl_phys(pa, val); + stl_phys(&address_space_memory, pa, val); } static uint16_t vring_used_idx(VirtQueue *vq) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, idx); - return lduw_phys(pa); + return lduw_phys(&address_space_memory, pa); } static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, idx); - stw_phys(pa, val); + stw_phys(&address_space_memory, pa, val); } static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, flags); - stw_phys(pa, lduw_phys(pa) | mask); + stw_phys(&address_space_memory, + pa, lduw_phys(&address_space_memory, pa) | mask); } static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, flags); - stw_phys(pa, lduw_phys(pa) & ~mask); + stw_phys(&address_space_memory, + pa, lduw_phys(&address_space_memory, pa) & ~mask); } static inline void vring_avail_event(VirtQueue *vq, uint16_t val) @@ -203,7 +206,7 @@ static inline void vring_avail_event(VirtQueue *vq, uint16_t val) return; } pa = vq->vring.used + offsetof(VRingUsed, ring[vq->vring.num]); - stw_phys(pa, val); + stw_phys(&address_space_memory, pa, val); } void virtio_queue_set_notification(VirtQueue *vq, int enable) |