diff options
45 files changed, 559 insertions, 226 deletions
diff --git a/block.c b/block.c index e9380f6c58..1df13ac1c7 100644 --- a/block.c +++ b/block.c @@ -3744,11 +3744,17 @@ const char *bdrv_get_format_name(BlockDriverState *bs) return bs->drv ? bs->drv->format_name : NULL; } +static int qsort_strcmp(const void *a, const void *b) +{ + return strcmp(a, b); +} + void bdrv_iterate_format(void (*it)(void *opaque, const char *name), void *opaque) { BlockDriver *drv; int count = 0; + int i; const char **formats = NULL; QLIST_FOREACH(drv, &bdrv_drivers, list) { @@ -3762,10 +3768,16 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), if (!found) { formats = g_renew(const char *, formats, count + 1); formats[count++] = drv->format_name; - it(opaque, drv->format_name); } } } + + qsort(formats, count, sizeof(formats[0]), qsort_strcmp); + + for (i = 0; i < count; i++) { + it(opaque, formats[i]); + } + g_free(formats); } diff --git a/block/mirror.c b/block/mirror.c index 5e7a166b39..18b18e0353 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -157,7 +157,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) BlockDriverState *source = s->common.bs; int nb_sectors, sectors_per_chunk, nb_chunks; int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector; - uint64_t delay_ns; + uint64_t delay_ns = 0; MirrorOp *op; s->sector_num = hbitmap_iter_next(&s->hbi); @@ -247,8 +247,6 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s) next_chunk += added_chunks; if (!s->synced && s->common.speed) { delay_ns = ratelimit_calculate_delay(&s->limit, added_sectors); - } else { - delay_ns = 0; } } while (delay_ns == 0 && next_sector < end); diff --git a/cpus.c b/cpus.c index 2b5c0bd7c7..eb1ac8577b 100644 --- a/cpus.c +++ b/cpus.c @@ -40,6 +40,7 @@ #include "qemu/bitmap.h" #include "qemu/seqlock.h" #include "qapi-event.h" +#include "hw/nmi.h" #ifndef _WIN32 #include "qemu/compatfd.h" @@ -1536,22 +1537,8 @@ void qmp_inject_nmi(Error **errp) apic_deliver_nmi(cpu->apic_state); } } -#elif defined(TARGET_S390X) - CPUState *cs; - S390CPU *cpu; - - CPU_FOREACH(cs) { - cpu = S390_CPU(cs); - if (cpu->env.cpu_num == monitor_get_cpu_index()) { - if (s390_cpu_restart(S390_CPU(cs)) == -1) { - error_set(errp, QERR_UNSUPPORTED); - return; - } - break; - } - } #else - error_set(errp, QERR_UNSUPPORTED); + nmi_monitor_handle(monitor_get_cpu_index(), errp); #endif } diff --git a/hmp-commands.hx b/hmp-commands.hx index d0943b1ff3..f859f8d29f 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -832,19 +832,17 @@ The values that can be specified here depend on the machine type, but are the same that can be specified in the @code{-boot} command line option. ETEXI -#if defined(TARGET_I386) || defined(TARGET_S390X) { .name = "nmi", .args_type = "", .params = "", - .help = "inject an NMI on all guest's CPUs", + .help = "inject an NMI", .mhandler.cmd = hmp_inject_nmi, }, -#endif STEXI @item nmi @var{cpu} @findex nmi -Inject an NMI (x86) or RESTART (s390x) on the given CPU. +Inject an NMI on the default CPU (x86/s390) or all CPUs (ppc64). ETEXI diff --git a/hw/block/block.c b/hw/block/block.c index 33dd3f33b6..b6a6dc6baa 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -22,8 +22,9 @@ void blkconf_serial(BlockConf *conf, char **serial) } } -int blkconf_geometry(BlockConf *conf, int *ptrans, - unsigned cyls_max, unsigned heads_max, unsigned secs_max) +void blkconf_geometry(BlockConf *conf, int *ptrans, + unsigned cyls_max, unsigned heads_max, unsigned secs_max, + Error **errp) { DriveInfo *dinfo; @@ -46,17 +47,16 @@ int blkconf_geometry(BlockConf *conf, int *ptrans, } if (conf->cyls || conf->heads || conf->secs) { if (conf->cyls < 1 || conf->cyls > cyls_max) { - error_report("cyls must be between 1 and %u", cyls_max); - return -1; + error_setg(errp, "cyls must be between 1 and %u", cyls_max); + return; } if (conf->heads < 1 || conf->heads > heads_max) { - error_report("heads must be between 1 and %u", heads_max); - return -1; + error_setg(errp, "heads must be between 1 and %u", heads_max); + return; } if (conf->secs < 1 || conf->secs > secs_max) { - error_report("secs must be between 1 and %u", secs_max); - return -1; + error_setg(errp, "secs must be between 1 and %u", secs_max); + return; } } - return 0; } diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index d9167ce9a3..a7f28275f4 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -729,9 +729,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOBlock *s = VIRTIO_BLK(dev); VirtIOBlkConf *blk = &(s->blk); -#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE Error *err = NULL; -#endif static int virtio_blk_id; if (!blk->conf.bs) { @@ -745,8 +743,9 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) blkconf_serial(&blk->conf, &blk->serial); s->original_wce = bdrv_enable_write_cache(blk->conf.bs); - if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) { - error_setg(errp, "Error setting geometry"); + blkconf_geometry(&blk->conf, NULL, 65535, 255, 255, &err); + if (err) { + error_propagate(errp, err); return; } diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 5377d052e9..17845df3f0 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -4,6 +4,7 @@ common-obj-y += fw-path-provider.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o common-obj-y += hotplug.o +common-obj-y += nmi.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o diff --git a/hw/core/nmi.c b/hw/core/nmi.c new file mode 100644 index 0000000000..3dff020659 --- /dev/null +++ b/hw/core/nmi.c @@ -0,0 +1,84 @@ +/* + * NMI monitor handler class and helpers. + * + * Copyright IBM Corp., 2014 + * + * Author: Alexey Kardashevskiy <aik@ozlabs.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "hw/nmi.h" +#include "qapi/qmp/qerror.h" + +struct do_nmi_s { + int cpu_index; + Error *errp; + bool handled; +}; + +static void nmi_children(Object *o, struct do_nmi_s *ns); + +static int do_nmi(Object *o, void *opaque) +{ + struct do_nmi_s *ns = opaque; + NMIState *n = (NMIState *) object_dynamic_cast(o, TYPE_NMI); + + if (n) { + NMIClass *nc = NMI_GET_CLASS(n); + + ns->handled = true; + nc->nmi_monitor_handler(n, ns->cpu_index, &ns->errp); + if (ns->errp) { + return -1; + } + } + nmi_children(o, ns); + + return 0; +} + +static void nmi_children(Object *o, struct do_nmi_s *ns) +{ + object_child_foreach(o, do_nmi, ns); +} + +void nmi_monitor_handle(int cpu_index, Error **errp) +{ + struct do_nmi_s ns = { + .cpu_index = cpu_index, + .errp = NULL, + .handled = false + }; + + nmi_children(object_get_root(), &ns); + if (ns.handled) { + error_propagate(errp, ns.errp); + } else { + error_set(errp, QERR_UNSUPPORTED); + } +} + +static const TypeInfo nmi_info = { + .name = TYPE_NMI, + .parent = TYPE_INTERFACE, + .class_size = sizeof(NMIClass), +}; + +static void nmi_register_types(void) +{ + type_register_static(&nmi_info); +} + +type_init(nmi_register_types) diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 6e475e6970..b4a467116e 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -151,6 +151,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) { IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); IDEState *s = bus->ifs + dev->unit; + Error *err = NULL; if (dev->conf.discard_granularity == -1) { dev->conf.discard_granularity = 512; @@ -161,9 +162,13 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) } blkconf_serial(&dev->conf, &dev->serial); - if (kind != IDE_CD - && blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) { - return -1; + if (kind != IDE_CD) { + blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255, &err); + if (err) { + error_report("%s", error_get_pretty(err)); + error_free(err); + return -1; + } } if (ide_init_drive(s, dev->conf.bs, kind, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d01978f3dc..5cb452f234 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -55,6 +55,7 @@ #include "qemu/config-file.h" #include "qemu/error-report.h" #include "trace.h" +#include "hw/nmi.h" #include <libfdt.h> @@ -1576,10 +1577,28 @@ static void spapr_machine_initfn(Object *obj) spapr_get_kvm_type, spapr_set_kvm_type, NULL); } +static void ppc_cpu_do_nmi_on_cpu(void *arg) +{ + CPUState *cs = arg; + + cpu_synchronize_state(cs); + ppc_cpu_do_system_reset(cs); +} + +static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) +{ + CPUState *cs; + + CPU_FOREACH(cs) { + async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, cs); + } +} + static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); mc->name = "pseries"; mc->desc = "pSeries Logical Partition (PAPR compliant)"; @@ -1593,6 +1612,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->kvm_type = spapr_kvm_type; fwc->get_dev_path = spapr_get_fw_dev_path; + nc->nmi_monitor_handler = spapr_nmi; } static const TypeInfo spapr_machine_info = { @@ -1603,6 +1623,7 @@ static const TypeInfo spapr_machine_info = { .class_init = spapr_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_FW_PATH_PROVIDER }, + { TYPE_NMI }, { } }, }; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 42f5cec4c1..004b2c20c5 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -18,6 +18,8 @@ #include "css.h" #include "virtio-ccw.h" +#define TYPE_S390_CCW_MACHINE "s390-ccw-machine" + void io_subsystem_reset(void) { DeviceState *css, *sclp, *flic; @@ -134,24 +136,39 @@ static void ccw_init(MachineState *machine) s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); } -static QEMUMachine ccw_machine = { - .name = "s390-ccw-virtio", - .alias = "s390-ccw", - .desc = "VirtIO-ccw based S390 machine", - .init = ccw_init, - .block_default_type = IF_VIRTIO, - .no_cdrom = 1, - .no_floppy = 1, - .no_serial = 1, - .no_parallel = 1, - .no_sdcard = 1, - .use_sclp = 1, - .max_cpus = 255, +static void ccw_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); + + mc->name = "s390-ccw-virtio"; + mc->alias = "s390-ccw"; + mc->desc = "VirtIO-ccw based S390 machine"; + mc->init = ccw_init; + mc->block_default_type = IF_VIRTIO; + mc->no_cdrom = 1; + mc->no_floppy = 1; + mc->no_serial = 1; + mc->no_parallel = 1; + mc->no_sdcard = 1; + mc->use_sclp = 1, + mc->max_cpus = 255; + nc->nmi_monitor_handler = s390_nmi; +} + +static const TypeInfo ccw_machine_info = { + .name = TYPE_S390_CCW_MACHINE, + .parent = TYPE_MACHINE, + .class_init = ccw_machine_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_NMI }, + { } + }, }; -static void ccw_machine_init(void) +static void ccw_machine_register_types(void) { - qemu_register_machine(&ccw_machine); + type_register_static(&ccw_machine_info); } -machine_init(ccw_machine_init) +type_init(ccw_machine_register_types) diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 93c7acea72..1a75a1cf81 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -51,6 +51,7 @@ #define MAX_BLK_DEVS 10 #define ZIPL_FILENAME "s390-zipl.rom" +#define TYPE_S390_MACHINE "s390-machine" static VirtIOS390Bus *s390_bus; static S390CPU **ipi_states; @@ -279,25 +280,49 @@ static void s390_init(MachineState *machine) s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390"); } -static QEMUMachine s390_machine = { - .name = "s390-virtio", - .alias = "s390", - .desc = "VirtIO based S390 machine", - .init = s390_init, - .block_default_type = IF_VIRTIO, - .no_cdrom = 1, - .no_floppy = 1, - .no_serial = 1, - .no_parallel = 1, - .no_sdcard = 1, - .use_virtcon = 1, - .max_cpus = 255, - .is_default = 1, +void s390_nmi(NMIState *n, int cpu_index, Error **errp) +{ + CPUState *cs = qemu_get_cpu(cpu_index); + + if (s390_cpu_restart(S390_CPU(cs))) { + error_set(errp, QERR_UNSUPPORTED); + } +} + +static void s390_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); + + mc->name = "s390-virtio"; + mc->alias = "s390"; + mc->desc = "VirtIO based S390 machine"; + mc->init = s390_init; + mc->block_default_type = IF_VIRTIO; + mc->max_cpus = 255; + mc->no_serial = 1; + mc->no_parallel = 1; + mc->use_virtcon = 1; + mc->no_floppy = 1; + mc->no_cdrom = 1; + mc->no_sdcard = 1; + mc->is_default = 1; + nc->nmi_monitor_handler = s390_nmi; +} + +static const TypeInfo s390_machine_info = { + .name = TYPE_S390_MACHINE, + .parent = TYPE_MACHINE, + .class_init = s390_machine_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_NMI }, + { } + }, }; -static void s390_machine_init(void) +static void s390_machine_register_types(void) { - qemu_register_machine(&s390_machine); + type_register_static(&s390_machine_info); } -machine_init(s390_machine_init); +type_init(s390_machine_register_types) diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h index 5c405e7755..33847aefcf 100644 --- a/hw/s390x/s390-virtio.h +++ b/hw/s390x/s390-virtio.h @@ -12,6 +12,8 @@ #ifndef HW_S390_VIRTIO_H #define HW_S390_VIRTIO_H 1 +#include "hw/nmi.h" + #define KVM_S390_VIRTIO_NOTIFY 0 #define KVM_S390_VIRTIO_RESET 1 #define KVM_S390_VIRTIO_SET_STATUS 2 @@ -26,4 +28,5 @@ void s390_init_ipl_dev(const char *kernel_filename, const char *initrd_filename, const char *firmware); void s390_create_virtio_net(BusState *bus, const char *name); +void s390_nmi(NMIState *n, int cpu_index, Error **errp); #endif diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 513ea47e8a..d9b4c7ea3c 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -19,6 +19,7 @@ #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" #include "sysemu/dma.h" +#include "qemu/error-report.h" //#define DEBUG_LSI //#define DEBUG_LSI_REG diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 6f4462b483..954c6072bf 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -36,20 +36,19 @@ static const TypeInfo scsi_bus_info = { }; static int next_scsi_bus; -static int scsi_device_init(SCSIDevice *s) +static void scsi_device_realize(SCSIDevice *s, Error **errp) { SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); - if (sc->init) { - return sc->init(s); + if (sc->realize) { + sc->realize(s, errp); } - return 0; } -static void scsi_device_destroy(SCSIDevice *s) +static void scsi_device_unrealize(SCSIDevice *s, Error **errp) { SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); - if (sc->destroy) { - sc->destroy(s); + if (sc->unrealize) { + sc->unrealize(s, errp); } } @@ -143,24 +142,24 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state) } } -static int scsi_qdev_init(DeviceState *qdev) +static void scsi_qdev_realize(DeviceState *qdev, Error **errp) { SCSIDevice *dev = SCSI_DEVICE(qdev); SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); SCSIDevice *d; - int rc = -1; + Error *local_err = NULL; if (dev->channel > bus->info->max_channel) { - error_report("bad scsi channel id: %d", dev->channel); - goto err; + error_setg(errp, "bad scsi channel id: %d", dev->channel); + return; } if (dev->id != -1 && dev->id > bus->info->max_target) { - error_report("bad scsi device id: %d", dev->id); - goto err; + error_setg(errp, "bad scsi device id: %d", dev->id); + return; } if (dev->lun != -1 && dev->lun > bus->info->max_lun) { - error_report("bad scsi device lun: %d", dev->lun); - goto err; + error_setg(errp, "bad scsi device lun: %d", dev->lun); + return; } if (dev->id == -1) { @@ -172,8 +171,8 @@ static int scsi_qdev_init(DeviceState *qdev) d = scsi_device_find(bus, dev->channel, ++id, dev->lun); } while (d && d->lun == dev->lun && id < bus->info->max_target); if (d && d->lun == dev->lun) { - error_report("no free target"); - goto err; + error_setg(errp, "no free target"); + return; } dev->id = id; } else if (dev->lun == -1) { @@ -182,43 +181,41 @@ static int scsi_qdev_init(DeviceState *qdev) d = scsi_device_find(bus, dev->channel, dev->id, ++lun); } while (d && d->lun == lun && lun < bus->info->max_lun); if (d && d->lun == lun) { - error_report("no free lun"); - goto err; + error_setg(errp, "no free lun"); + return; } dev->lun = lun; } else { d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); assert(d); if (d->lun == dev->lun && dev != d) { - error_report("lun already used by '%s'", d->qdev.id); - goto err; + error_setg(errp, "lun already used by '%s'", d->qdev.id); + return; } } QTAILQ_INIT(&dev->requests); - rc = scsi_device_init(dev); - if (rc == 0) { - dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, - dev); + scsi_device_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } + dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, + dev); if (bus->info->hotplug) { bus->info->hotplug(bus, dev); } - -err: - return rc; } -static int scsi_qdev_exit(DeviceState *qdev) +static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) { SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->vmsentry) { qemu_del_vm_change_state_handler(dev->vmsentry); } - scsi_device_destroy(dev); - return 0; + scsi_device_unrealize(dev, errp); } /* handle legacy '-drive if=scsi,...' cmd line args */ @@ -273,6 +270,7 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp) scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL, &err); if (err != NULL) { + error_report("%s", error_get_pretty(err)); error_propagate(errp, err); break; } @@ -1992,11 +1990,11 @@ static void scsi_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); set_bit(DEVICE_CATEGORY_STORAGE, k->categories); - k->bus_type = TYPE_SCSI_BUS; - k->init = scsi_qdev_init; - k->unplug = scsi_qdev_unplug; - k->exit = scsi_qdev_exit; - k->props = scsi_props; + k->bus_type = TYPE_SCSI_BUS; + k->realize = scsi_qdev_realize; + k->unplug = scsi_qdev_unplug; + k->unrealize = scsi_qdev_unrealize; + k->props = scsi_props; } static const TypeInfo scsi_device_type_info = { diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index d55521dcf6..e34a54404b 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2151,7 +2151,7 @@ static void scsi_disk_reset(DeviceState *dev) s->tray_open = 0; } -static void scsi_destroy(SCSIDevice *dev) +static void scsi_unrealize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); @@ -2234,25 +2234,29 @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev) } } -static int scsi_initfn(SCSIDevice *dev) +static void scsi_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + Error *err = NULL; if (!s->qdev.conf.bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) && !bdrv_is_inserted(s->qdev.conf.bs)) { - error_report("Device needs media, but drive is empty"); - return -1; + error_setg(errp, "Device needs media, but drive is empty"); + return; } blkconf_serial(&s->qdev.conf, &s->serial); - if (dev->type == TYPE_DISK - && blkconf_geometry(&dev->conf, NULL, 65535, 255, 255) < 0) { - return -1; + if (dev->type == TYPE_DISK) { + blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, &err); + if (err) { + error_propagate(errp, err); + return; + } } if (s->qdev.conf.discard_granularity == -1) { @@ -2268,8 +2272,8 @@ static int scsi_initfn(SCSIDevice *dev) } if (bdrv_is_sg(s->qdev.conf.bs)) { - error_report("unwanted /dev/sg*"); - return -1; + error_setg(errp, "unwanted /dev/sg*"); + return; } if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && @@ -2282,10 +2286,9 @@ static int scsi_initfn(SCSIDevice *dev) bdrv_iostatus_enable(s->qdev.conf.bs); add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL); - return 0; } -static int scsi_hd_initfn(SCSIDevice *dev) +static void scsi_hd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); s->qdev.blocksize = s->qdev.conf.logical_block_size; @@ -2293,10 +2296,10 @@ static int scsi_hd_initfn(SCSIDevice *dev) if (!s->product) { s->product = g_strdup("QEMU HARDDISK"); } - return scsi_initfn(&s->qdev); + scsi_realize(&s->qdev, errp); } -static int scsi_cd_initfn(SCSIDevice *dev) +static void scsi_cd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); s->qdev.blocksize = 2048; @@ -2305,22 +2308,26 @@ static int scsi_cd_initfn(SCSIDevice *dev) if (!s->product) { s->product = g_strdup("QEMU CD-ROM"); } - return scsi_initfn(&s->qdev); + scsi_realize(&s->qdev, errp); } -static int scsi_disk_initfn(SCSIDevice *dev) +static void scsi_disk_realize(SCSIDevice *dev, Error **errp) { DriveInfo *dinfo; + Error *local_err = NULL; if (!dev->conf.bs) { - return scsi_initfn(dev); /* ... and die there */ + scsi_realize(dev, &local_err); + assert(local_err); + error_propagate(errp, local_err); + return; } dinfo = drive_get_by_blockdev(dev->conf.bs); if (dinfo->media_cd) { - return scsi_cd_initfn(dev); + scsi_cd_realize(dev, errp); } else { - return scsi_hd_initfn(dev); + scsi_hd_realize(dev, errp); } } @@ -2452,35 +2459,35 @@ static int get_device_type(SCSIDiskState *s) return 0; } -static int scsi_block_initfn(SCSIDevice *dev) +static void scsi_block_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); int sg_version; int rc; if (!s->qdev.conf.bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } /* check we are using a driver managing SG_IO (version 3 and after) */ rc = bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { - error_report("cannot get SG_IO version number: %s. " + error_setg(errp, "cannot get SG_IO version number: %s. " "Is this a SCSI device?", strerror(-rc)); - return -1; + return; } if (sg_version < 30000) { - error_report("scsi generic interface too old"); - return -1; + error_setg(errp, "scsi generic interface too old"); + return; } /* get device type from INQUIRY data */ rc = get_device_type(s); if (rc < 0) { - error_report("INQUIRY failed"); - return -1; + error_setg(errp, "INQUIRY failed"); + return; } /* Make a guess for the block size, we'll fix it when the guest sends. @@ -2498,7 +2505,7 @@ static int scsi_block_initfn(SCSIDevice *dev) */ s->features |= (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS); - return scsi_initfn(&s->qdev); + scsi_realize(&s->qdev, errp); } static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf) @@ -2621,8 +2628,8 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_hd_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_hd_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; @@ -2652,8 +2659,8 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_cd_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_cd_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; @@ -2682,8 +2689,8 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_block_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_block_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_block_new_request; sc->parse_cdb = scsi_block_parse_cdb; dc->fw_name = "disk"; @@ -2720,8 +2727,8 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_disk_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_disk_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 0b2ff90b90..20587b41c1 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -303,9 +303,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) SCSIDevice *s = r->req.dev; int ret; - DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag, - r->req.cmd.xfer, cmd[0]); - #ifdef DEBUG_SCSI { int i; @@ -386,49 +383,49 @@ static void scsi_generic_reset(DeviceState *dev) scsi_device_purge_requests(s, SENSE_CODE(RESET)); } -static void scsi_destroy(SCSIDevice *s) +static void scsi_unrealize(SCSIDevice *s, Error **errp) { scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE)); blockdev_mark_auto_del(s->conf.bs); } -static int scsi_generic_initfn(SCSIDevice *s) +static void scsi_generic_realize(SCSIDevice *s, Error **errp) { int rc; int sg_version; struct sg_scsi_id scsiid; if (!s->conf.bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { - error_report("Device doesn't support drive option werror"); - return -1; + error_setg(errp, "Device doesn't support drive option werror"); + return; } if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { - error_report("Device doesn't support drive option rerror"); - return -1; + error_setg(errp, "Device doesn't support drive option rerror"); + return; } /* check we are using a driver managing SG_IO (version 3 and after */ rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { - error_report("cannot get SG_IO version number: %s. " - "Is this a SCSI device?", - strerror(-rc)); - return -1; + error_setg(errp, "cannot get SG_IO version number: %s. " + "Is this a SCSI device?", + strerror(-rc)); + return; } if (sg_version < 30000) { - error_report("scsi generic interface too old"); - return -1; + error_setg(errp, "scsi generic interface too old"); + return; } /* get LUN of the /dev/sg? */ if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) { - error_report("SG_GET_SCSI_ID ioctl failed"); - return -1; + error_setg(errp, "SG_GET_SCSI_ID ioctl failed"); + return; } /* define device state */ @@ -460,7 +457,6 @@ static int scsi_generic_initfn(SCSIDevice *s) } DPRINTF("block size %d\n", s->blocksize); - return 0; } const SCSIReqOps scsi_generic_req_ops = { @@ -501,8 +497,8 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_generic_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_generic_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->parse_cdb = scsi_generic_parse_cdb; dc->fw_name = "disk"; diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 2dd92552e0..86aba8851d 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -699,6 +699,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp, virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); + if (s->conf.num_queues <= 0 || s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX) { + error_setg(errp, "Invalid number of queues (= %" PRId32 "), " + "must be a positive integer less than %d.", + s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX); + return; + } s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *)); s->sense_size = VIRTIO_SCSI_SENSE_SIZE; s->cdb_size = VIRTIO_SCSI_CDB_SIZE; diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 233fc70d67..4df650f450 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -792,6 +792,7 @@ static void rtc_reset(void *opaque) #ifdef TARGET_I386 if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { s->irq_coalesced = 0; + s->irq_reinject_on_ack_count = 0; } #endif } diff --git a/include/hw/block/block.h b/include/hw/block/block.h index 7c3d6c8178..3a0148848b 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -12,6 +12,7 @@ #define HW_BLOCK_COMMON_H #include "qemu-common.h" +#include "qapi/error.h" /* Configuration */ @@ -60,8 +61,9 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) /* Configuration helpers */ void blkconf_serial(BlockConf *conf, char **serial); -int blkconf_geometry(BlockConf *conf, int *trans, - unsigned cyls_max, unsigned heads_max, unsigned secs_max); +void blkconf_geometry(BlockConf *conf, int *trans, + unsigned cyls_max, unsigned heads_max, unsigned secs_max, + Error **errp); /* Hard disk geometry */ diff --git a/include/hw/nmi.h b/include/hw/nmi.h new file mode 100644 index 0000000000..b541772e1d --- /dev/null +++ b/include/hw/nmi.h @@ -0,0 +1,49 @@ +/* + * NMI monitor handler class and helpers definitions. + * + * Copyright IBM Corp., 2014 + * + * Author: Alexey Kardashevskiy <aik@ozlabs.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NMI_H +#define NMI_H 1 + +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_NMI "nmi" + +#define NMI_CLASS(klass) \ + OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI) +#define NMI_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI) +#define NMI(obj) \ + INTERFACE_CHECK(NMI, (obj), TYPE_NMI) + +typedef struct NMIState { + Object parent_obj; +} NMIState; + +typedef struct NMIClass { + InterfaceClass parent_class; + + void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp); +} NMIClass; + +void nmi_monitor_handle(int cpu_index, Error **errp); + +#endif /* NMI_H */ diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index a7a28e6bbd..2e3a8f987d 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -74,8 +74,8 @@ struct SCSIRequest { typedef struct SCSIDeviceClass { DeviceClass parent_class; - int (*init)(SCSIDevice *dev); - void (*destroy)(SCSIDevice *s); + void (*realize)(SCSIDevice *dev, Error **errp); + void (*unrealize)(SCSIDevice *dev, Error **errp); int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, void *hba_private); SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, diff --git a/kvm-all.c b/kvm-all.c index 1402f4f429..b240bf87a9 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1669,18 +1669,32 @@ void kvm_cpu_synchronize_state(CPUState *cpu) } } -void kvm_cpu_synchronize_post_reset(CPUState *cpu) +static void do_kvm_cpu_synchronize_post_reset(void *arg) { + CPUState *cpu = arg; + kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); cpu->kvm_vcpu_dirty = false; } -void kvm_cpu_synchronize_post_init(CPUState *cpu) +void kvm_cpu_synchronize_post_reset(CPUState *cpu) +{ + run_on_cpu(cpu, do_kvm_cpu_synchronize_post_reset, cpu); +} + +static void do_kvm_cpu_synchronize_post_init(void *arg) { + CPUState *cpu = arg; + kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); cpu->kvm_vcpu_dirty = false; } +void kvm_cpu_synchronize_post_init(CPUState *cpu) +{ + run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, cpu); +} + int kvm_cpu_exec(CPUState *cpu) { struct kvm_run *run = cpu->kvm_run; diff --git a/memory.c b/memory.c index 42317a216d..ef0be1c3aa 100644 --- a/memory.c +++ b/memory.c @@ -1309,6 +1309,10 @@ uint64_t memory_region_size(MemoryRegion *mr) const char *memory_region_name(const MemoryRegion *mr) { + if (!mr->name) { + ((MemoryRegion *)mr)->name = + object_get_canonical_path_component(OBJECT(mr)); + } return mr->name; } diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc index 0f2fc3a0af..e136516b4f 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc Binary files differdiff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 index 8917b558e6..2274bcf8b8 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 Binary files differdiff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 index cf72a59ee1..635fe7e626 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 Binary files differdiff --git a/qapi-schema.json b/qapi-schema.json index 341f417a5f..689b548abf 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1186,13 +1186,13 @@ ## # @inject-nmi: # -# Injects an Non-Maskable Interrupt into all guest's VCPUs. +# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64). # # Returns: If successful, nothing # # Since: 0.14.0 # -# Notes: Only x86 Virtual Machines support this command. +# Note: prior to 2.1, this command was only supported for x86 and s390 VMs ## { 'command': 'inject-nmi' } diff --git a/qemu-img.c b/qemu-img.c index c8434206b8..2052b14b84 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -32,7 +32,6 @@ #include "block/block_int.h" #include "block/qapi.h" #include <getopt.h> -#include <glib.h> #define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \ ", Copyright (c) 2004-2008 Fabrice Bellard\n" @@ -56,22 +55,9 @@ typedef enum OutputFormat { #define BDRV_O_FLAGS BDRV_O_CACHE_WB #define BDRV_DEFAULT_CACHE "writeback" -static gint compare_data(gconstpointer a, gconstpointer b, gpointer user) +static void format_print(void *opaque, const char *name) { - return g_strcmp0(a, b); -} - -static void print_format(gpointer data, gpointer user) -{ - printf(" %s", (char *)data); -} - -static void add_format_to_seq(void *opaque, const char *fmt_name) -{ - GSequence *seq = opaque; - - g_sequence_insert_sorted(seq, (gpointer)fmt_name, - compare_data, NULL); + printf(" %s", name); } static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...) @@ -157,15 +143,10 @@ static void QEMU_NORETURN help(void) " '-f' first image format\n" " '-F' second image format\n" " '-s' run in Strict mode - fail on different image size or sector allocation\n"; - GSequence *seq; printf("%s\nSupported formats:", help_msg); - seq = g_sequence_new(NULL); - bdrv_iterate_format(add_format_to_seq, seq); - g_sequence_foreach(seq, print_format, NULL); + bdrv_iterate_format(format_print, NULL); printf("\n"); - g_sequence_free(seq); - exit(EXIT_SUCCESS); } diff --git a/qmp-commands.hx b/qmp-commands.hx index 4be4765f27..7658d4bd24 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -477,7 +477,7 @@ SQMP inject-nmi ---------- -Inject an NMI on guest's CPUs. +Inject an NMI on the default CPU (x86/s390) or all CPUs (ppc64). Arguments: None. @@ -487,7 +487,6 @@ Example: <- { "return": {} } Note: inject-nmi fails when the guest doesn't support injecting. - Currently, only x86 (NMI) and s390x (RESTART) guests do. EQMP diff --git a/roms/openbios b/roms/openbios -Subproject a056ccbebaa802b22bed59e2e07ea78f256243c +Subproject d9e38ba2ffd2d2cdfa840ea9bc7dd4a64472f2c diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9d46e5a104..053e4320fc 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -206,9 +206,13 @@ our $UTF8 = qr { | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 }x; +# There are still some false positives, but this catches most +# common cases. our $typeTypedefs = qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t + [A-Z][A-Z\d_]*[a-z][A-Za-z\d_]* # camelcase + | [A-Z][A-Z\d_]*AIOCB # all uppercase + | [A-Z][A-Z\d_]*CPU # all uppercase + | QEMUBH # all uppercase )}; our $logFunctions = qr{(?x: diff --git a/scripts/qapi.py b/scripts/qapi.py index f2c6d1f840..77d46aa995 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -107,10 +107,10 @@ class QAPISchema: 'Expected a file name (string), got: %s' % include) include_path = os.path.join(self.input_dir, include) - if any(include_path == elem[1] - for elem in self.include_hist): - raise QAPIExprError(expr_info, "Inclusion loop for %s" - % include) + for elem in self.include_hist: + if include_path == elem[1]: + raise QAPIExprError(expr_info, "Inclusion loop for %s" + % include) # skip multiple include of the same file if include_path in previously_included: continue diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py index 5bfa1efc5c..d4b6dab9ca 100644 --- a/scripts/tracetool/backend/__init__.py +++ b/scripts/tracetool/backend/__init__.py @@ -102,7 +102,8 @@ class Wrapper: def __init__(self, backends, format): self._backends = [backend.replace("-", "_") for backend in backends] self._format = format.replace("-", "_") - assert all(exists(backend) for backend in self._backends) + for backend in self._backends: + assert exists(backend) assert tracetool.format.exists(self._format) def _run_function(self, name, *args, **kwargs): diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 217500c735..fa811a02d1 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -257,8 +257,8 @@ static const char *svm_feature_name[] = { }; static const char *cpuid_7_0_ebx_feature_name[] = { - "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep", - "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL, + "fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep", + "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL, NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -2588,6 +2588,16 @@ static void x86_cpu_reset(CPUState *s) env->xcr0 = 1; + /* + * SDM 11.11.5 requires: + * - IA32_MTRR_DEF_TYPE MSR.E = 0 + * - IA32_MTRR_PHYSMASKn.V = 0 + * All other bits are undefined. For simplification, zero it all. + */ + env->mtrr_deftype = 0; + memset(env->mtrr_var, 0, sizeof(env->mtrr_var)); + memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); + #if !defined(CONFIG_USER_ONLY) /* We hard-wire the BSP to the first CPU. */ if (s->cpu_index == 0) { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e634d83e86..3460b12139 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -337,6 +337,8 @@ #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) +#define MSR_MTRRphysIndex(addr) ((((addr) & ~1u) - 0x200) / 2) + #define MSR_MTRRfix64K_00000 0x250 #define MSR_MTRRfix16K_80000 0x258 #define MSR_MTRRfix16K_A0000 0x259 @@ -930,7 +932,7 @@ typedef struct CPUX86State { /* MTRRs */ uint64_t mtrr_fixed[11]; uint64_t mtrr_deftype; - MTRRVar mtrr_var[8]; + MTRRVar mtrr_var[MSR_MTRRcap_VCNT]; /* For KVM */ uint32_t mp_state; diff --git a/target-i386/helper.c b/target-i386/helper.c index 47b982b437..30cb0d0143 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -615,8 +615,8 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, if (!(pdpe & PG_PRESENT_MASK)) { goto do_fault; } - rsvd_mask |= PG_HI_USER_MASK | PG_NX_MASK; - if (pdpe & rsvd_mask) { + rsvd_mask |= PG_HI_USER_MASK; + if (pdpe & (rsvd_mask | PG_NX_MASK)) { goto do_fault_rsvd; } ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 097fe1188d..ddedc735ff 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -79,6 +79,7 @@ static int lm_capable_kernel; static bool has_msr_hv_hypercall; static bool has_msr_hv_vapic; static bool has_msr_hv_tsc; +static bool has_msr_mtrr; static bool has_msr_architectural_pmu; static uint32_t num_architectural_pmu_counters; @@ -739,6 +740,10 @@ int kvm_arch_init_vcpu(CPUState *cs) env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); } + if (env->features[FEAT_1_EDX] & CPUID_MTRR) { + has_msr_mtrr = true; + } + return 0; } @@ -1183,7 +1188,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) CPUX86State *env = &cpu->env; struct { struct kvm_msrs info; - struct kvm_msr_entry entries[100]; + struct kvm_msr_entry entries[150]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; int n = 0, i; @@ -1278,6 +1283,37 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_REFERENCE_TSC, env->msr_hv_tsc); } + if (has_msr_mtrr) { + kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix64K_00000, env->mtrr_fixed[0]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix16K_80000, env->mtrr_fixed[1]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]); + for (i = 0; i < MSR_MTRRcap_VCNT; i++) { + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRphysBase(i), env->mtrr_var[i].base); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRphysMask(i), env->mtrr_var[i].mask); + } + } /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see * kvm_put_msr_feature_control. */ @@ -1484,7 +1520,7 @@ static int kvm_get_msrs(X86CPU *cpu) CPUX86State *env = &cpu->env; struct { struct kvm_msrs info; - struct kvm_msr_entry entries[100]; + struct kvm_msr_entry entries[150]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; int ret, i, n; @@ -1572,6 +1608,24 @@ static int kvm_get_msrs(X86CPU *cpu) if (has_msr_hv_tsc) { msrs[n++].index = HV_X64_MSR_REFERENCE_TSC; } + if (has_msr_mtrr) { + msrs[n++].index = MSR_MTRRdefType; + msrs[n++].index = MSR_MTRRfix64K_00000; + msrs[n++].index = MSR_MTRRfix16K_80000; + msrs[n++].index = MSR_MTRRfix16K_A0000; + msrs[n++].index = MSR_MTRRfix4K_C0000; + msrs[n++].index = MSR_MTRRfix4K_C8000; + msrs[n++].index = MSR_MTRRfix4K_D0000; + msrs[n++].index = MSR_MTRRfix4K_D8000; + msrs[n++].index = MSR_MTRRfix4K_E0000; + msrs[n++].index = MSR_MTRRfix4K_E8000; + msrs[n++].index = MSR_MTRRfix4K_F0000; + msrs[n++].index = MSR_MTRRfix4K_F8000; + for (i = 0; i < MSR_MTRRcap_VCNT; i++) { + msrs[n++].index = MSR_MTRRphysBase(i); + msrs[n++].index = MSR_MTRRphysMask(i); + } + } msr_data.info.nmsrs = n; ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); @@ -1692,6 +1746,49 @@ static int kvm_get_msrs(X86CPU *cpu) case HV_X64_MSR_REFERENCE_TSC: env->msr_hv_tsc = msrs[i].data; break; + case MSR_MTRRdefType: + env->mtrr_deftype = msrs[i].data; + break; + case MSR_MTRRfix64K_00000: + env->mtrr_fixed[0] = msrs[i].data; + break; + case MSR_MTRRfix16K_80000: + env->mtrr_fixed[1] = msrs[i].data; + break; + case MSR_MTRRfix16K_A0000: + env->mtrr_fixed[2] = msrs[i].data; + break; + case MSR_MTRRfix4K_C0000: + env->mtrr_fixed[3] = msrs[i].data; + break; + case MSR_MTRRfix4K_C8000: + env->mtrr_fixed[4] = msrs[i].data; + break; + case MSR_MTRRfix4K_D0000: + env->mtrr_fixed[5] = msrs[i].data; + break; + case MSR_MTRRfix4K_D8000: + env->mtrr_fixed[6] = msrs[i].data; + break; + case MSR_MTRRfix4K_E0000: + env->mtrr_fixed[7] = msrs[i].data; + break; + case MSR_MTRRfix4K_E8000: + env->mtrr_fixed[8] = msrs[i].data; + break; + case MSR_MTRRfix4K_F0000: + env->mtrr_fixed[9] = msrs[i].data; + break; + case MSR_MTRRfix4K_F8000: + env->mtrr_fixed[10] = msrs[i].data; + break; + case MSR_MTRRphysBase(0) ... MSR_MTRRphysMask(MSR_MTRRcap_VCNT - 1): + if (index & 1) { + env->mtrr_var[MSR_MTRRphysIndex(index)].mask = msrs[i].data; + } else { + env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data; + } + break; } } diff --git a/target-i386/machine.c b/target-i386/machine.c index 16d2f6a809..fb890654b1 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -677,7 +677,7 @@ VMStateDescription vmstate_x86_cpu = { /* MTRRs */ VMSTATE_UINT64_ARRAY_V(env.mtrr_fixed, X86CPU, 11, 8), VMSTATE_UINT64_V(env.mtrr_deftype, X86CPU, 8), - VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, 8, 8), + VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, MSR_MTRRcap_VCNT, 8), /* KVM-related states */ VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9), VMSTATE_UINT32_V(env.mp_state, X86CPU, 9), diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index 0fee36f06a..a379f795bc 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -127,6 +127,7 @@ int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); #ifndef CONFIG_USER_ONLY +void ppc_cpu_do_system_reset(CPUState *cs); extern const struct VMStateDescription vmstate_ppc_cpu; typedef struct PPCTimebase { diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index be7159013f..922e86d54b 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -810,6 +810,14 @@ void ppc_hw_interrupt(CPUPPCState *env) } } } + +void ppc_cpu_do_system_reset(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); +} #endif /* !CONFIG_USER_ONLY */ #if defined(DEBUG_OP) diff --git a/tests/libqtest.c b/tests/libqtest.c index ed55686ce0..5e458e884e 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -165,6 +165,7 @@ QTestState *qtest_init(const char *extra_args) s->qemu_pid = fork(); if (s->qemu_pid == 0) { + setenv("QEMU_AUDIO_DRV", "none", true); command = g_strdup_printf("exec %s " "-qtest unix:%s,nowait " "-qtest-log %s " diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index d7b0f503af..a3f28209c8 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -149,13 +149,11 @@ QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty -QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed. QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty -QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed. QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized diff --git a/vl.c b/vl.c index b796c67e9d..95be92d6fe 100644 --- a/vl.c +++ b/vl.c @@ -4033,11 +4033,6 @@ int main(int argc, char **argv, char **envp) qemu_set_version(machine_class->hw_version); } - if (qemu_opts_foreach(qemu_find_opts("object"), - object_create, NULL, 0) != 0) { - exit(1); - } - /* Init CPU def lists, based on config * - Must be called after all the qemu_read_config_file() calls * - Must be called before list_cpus() @@ -4249,6 +4244,11 @@ int main(int argc, char **argv, char **envp) exit(0); } + if (qemu_opts_foreach(qemu_find_opts("object"), + object_create, NULL, 0) != 0) { + exit(1); + } + machine_opts = qemu_get_machine_opts(); if (qemu_opt_foreach(machine_opts, object_set_property, current_machine, 1) < 0) { diff --git a/xen-hvm.c b/xen-hvm.c index 91de2e230b..0d09940111 100644 --- a/xen-hvm.c +++ b/xen-hvm.c @@ -71,7 +71,7 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu) typedef struct XenPhysmap { hwaddr start_addr; ram_addr_t size; - char *name; + const char *name; hwaddr phys_offset; QLIST_ENTRY(XenPhysmap) list; @@ -291,6 +291,7 @@ static int xen_add_to_physmap(XenIOState *state, hwaddr pfn, start_gpfn; hwaddr phys_offset = memory_region_get_ram_addr(mr); char path[80], value[17]; + const char *mr_name; if (get_physmapping(state, start_addr, size)) { return 0; @@ -326,11 +327,13 @@ go_physmap: } } + mr_name = memory_region_name(mr); + physmap = g_malloc(sizeof (XenPhysmap)); physmap->start_addr = start_addr; physmap->size = size; - physmap->name = (char *)mr->name; + physmap->name = mr_name; physmap->phys_offset = phys_offset; QLIST_INSERT_HEAD(&state->physmap, physmap, list); @@ -354,11 +357,11 @@ go_physmap: if (!xs_write(state->xenstore, 0, path, value, strlen(value))) { return -1; } - if (mr->name) { + if (mr_name) { snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name", xen_domid, (uint64_t)phys_offset); - if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) { + if (!xs_write(state->xenstore, 0, path, mr_name, strlen(mr_name))) { return -1; } } |