summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/aspeed.c4
-rw-r--r--hw/arm/boot.c2
-rw-r--r--hw/arm/mps2-tz.c4
-rw-r--r--hw/arm/virt.c5
-rw-r--r--hw/block/vhost-user-blk.c4
-rw-r--r--hw/block/virtio-blk.c39
-rw-r--r--hw/core/numa.c26
-rw-r--r--hw/core/reset.c17
-rw-r--r--hw/core/resettable.c3
-rw-r--r--hw/hppa/machine.c4
-rw-r--r--hw/hyperv/hyperv.c2
-rw-r--r--hw/i386/microvm.c4
-rw-r--r--hw/i386/pc.c6
-rw-r--r--hw/i386/x86.c2
-rw-r--r--hw/m68k/q800.c33
-rw-r--r--hw/m68k/virt.c20
-rw-r--r--hw/mem/nvdimm.c2
-rw-r--r--hw/mips/boston.c3
-rw-r--r--hw/mips/malta.c27
-rw-r--r--hw/net/virtio-net.c59
-rw-r--r--hw/net/xen_nic.c5
-rw-r--r--hw/openrisc/boot.c3
-rw-r--r--hw/ppc/pegasos2.c4
-rw-r--r--hw/ppc/pnv.c4
-rw-r--r--hw/ppc/spapr.c4
-rw-r--r--hw/riscv/boot.c3
-rw-r--r--hw/rx/rx-gdbsim.c3
-rw-r--r--hw/s390x/s390-virtio-ccw.c4
-rw-r--r--hw/timer/imx_epit.c9
-rw-r--r--hw/virtio/vhost-shadow-virtqueue.c39
-rw-r--r--hw/virtio/virtio-mem.c2
31 files changed, 251 insertions, 95 deletions
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index f8bc6d4a14..55f114ef72 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -1356,12 +1356,12 @@ static void aspeed_machine_bletchley_class_init(ObjectClass *oc, void *data)
aspeed_soc_num_cpus(amc->soc_name);
}
-static void fby35_reset(MachineState *state)
+static void fby35_reset(MachineState *state, ShutdownCause reason)
{
AspeedMachineState *bmc = ASPEED_MACHINE(state);
AspeedGPIOState *gpio = &bmc->soc.gpio;
- qemu_devices_reset();
+ qemu_devices_reset(reason);
/* Board ID: 7 (Class-1, 4 slots) */
object_property_set_bool(OBJECT(gpio), "gpioV4", true, &error_fatal);
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index b0b92af188..b106f31468 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -683,6 +683,8 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
* the DTB is copied again upon reset, even if addr points into RAM.
*/
rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
+ rom_ptr_for_as(as, addr, size));
g_free(fdt);
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 394192b9b2..284c09c91d 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -1239,7 +1239,7 @@ static void mps2_set_remap(Object *obj, const char *value, Error **errp)
}
}
-static void mps2_machine_reset(MachineState *machine)
+static void mps2_machine_reset(MachineState *machine, ShutdownCause reason)
{
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
@@ -1249,7 +1249,7 @@ static void mps2_machine_reset(MachineState *machine)
* reset see the correct mapping.
*/
remap_memory(mms, mms->remap);
- qemu_devices_reset();
+ qemu_devices_reset(reason);
}
static void mps2tz_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index cda9defe8f..b871350856 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1371,14 +1371,15 @@ static void create_smmu(const VirtMachineState *vms,
static void create_virtio_iommu_dt_bindings(VirtMachineState *vms)
{
- const char compat[] = "virtio,pci-iommu";
+ const char compat[] = "virtio,pci-iommu\0pci1af4,1057";
uint16_t bdf = vms->virtio_iommu_bdf;
MachineState *ms = MACHINE(vms);
char *node;
vms->iommu_phandle = qemu_fdt_alloc_phandle(ms->fdt);
- node = g_strdup_printf("%s/virtio_iommu@%d", vms->pciehb_nodename, bdf);
+ node = g_strdup_printf("%s/virtio_iommu@%x,%x", vms->pciehb_nodename,
+ PCI_SLOT(bdf), PCI_FUNC(bdf));
qemu_fdt_add_subnode(ms->fdt, node);
qemu_fdt_setprop(ms->fdt, node, "compatible", compat, sizeof(compat));
qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg",
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 84902dde17..13bf5cc47a 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -97,6 +97,10 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
Error *local_err = NULL;
+ if (!dev->started) {
+ return 0;
+ }
+
ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
vdev->config_len, &local_err);
if (ret < 0) {
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 8131ec2dbc..f717550fdc 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -21,6 +21,7 @@
#include "hw/block/block.h"
#include "hw/qdev-properties.h"
#include "sysemu/blockdev.h"
+#include "sysemu/block-ram-registrar.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "hw/virtio/virtio-blk.h"
@@ -362,12 +363,14 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
}
}
-static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
+static inline void submit_requests(VirtIOBlock *s, MultiReqBuffer *mrb,
int start, int num_reqs, int niov)
{
+ BlockBackend *blk = s->blk;
QEMUIOVector *qiov = &mrb->reqs[start]->qiov;
int64_t sector_num = mrb->reqs[start]->sector_num;
bool is_write = mrb->is_write;
+ BdrvRequestFlags flags = 0;
if (num_reqs > 1) {
int i;
@@ -398,12 +401,18 @@ static inline void submit_requests(BlockBackend *blk, MultiReqBuffer *mrb,
num_reqs - 1);
}
+ if (blk_ram_registrar_ok(&s->blk_ram_registrar)) {
+ flags |= BDRV_REQ_REGISTERED_BUF;
+ }
+
if (is_write) {
- blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
- virtio_blk_rw_complete, mrb->reqs[start]);
+ blk_aio_pwritev(blk, sector_num << BDRV_SECTOR_BITS, qiov,
+ flags, virtio_blk_rw_complete,
+ mrb->reqs[start]);
} else {
- blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov, 0,
- virtio_blk_rw_complete, mrb->reqs[start]);
+ blk_aio_preadv(blk, sector_num << BDRV_SECTOR_BITS, qiov,
+ flags, virtio_blk_rw_complete,
+ mrb->reqs[start]);
}
}
@@ -425,14 +434,14 @@ static int multireq_compare(const void *a, const void *b)
}
}
-static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
+static void virtio_blk_submit_multireq(VirtIOBlock *s, MultiReqBuffer *mrb)
{
int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0;
uint32_t max_transfer;
int64_t sector_num = 0;
if (mrb->num_reqs == 1) {
- submit_requests(blk, mrb, 0, 1, -1);
+ submit_requests(s, mrb, 0, 1, -1);
mrb->num_reqs = 0;
return;
}
@@ -452,11 +461,11 @@ static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
* 3. merge would exceed maximum transfer length of backend device
*/
if (sector_num + nb_sectors != req->sector_num ||
- niov > blk_get_max_iov(blk) - req->qiov.niov ||
+ niov > blk_get_max_iov(s->blk) - req->qiov.niov ||
req->qiov.size > max_transfer ||
nb_sectors > (max_transfer -
req->qiov.size) / BDRV_SECTOR_SIZE) {
- submit_requests(blk, mrb, start, num_reqs, niov);
+ submit_requests(s, mrb, start, num_reqs, niov);
num_reqs = 0;
}
}
@@ -472,7 +481,7 @@ static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
num_reqs++;
}
- submit_requests(blk, mrb, start, num_reqs, niov);
+ submit_requests(s, mrb, start, num_reqs, niov);
mrb->num_reqs = 0;
}
@@ -487,7 +496,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
* Make sure all outstanding writes are posted to the backing device.
*/
if (mrb->is_write && mrb->num_reqs > 0) {
- virtio_blk_submit_multireq(s->blk, mrb);
+ virtio_blk_submit_multireq(s, mrb);
}
blk_aio_flush(s->blk, virtio_blk_flush_complete, req);
}
@@ -667,7 +676,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
if (mrb->num_reqs > 0 && (mrb->num_reqs == VIRTIO_BLK_MAX_MERGE_REQS ||
is_write != mrb->is_write ||
!s->conf.request_merging)) {
- virtio_blk_submit_multireq(s->blk, mrb);
+ virtio_blk_submit_multireq(s, mrb);
}
assert(mrb->num_reqs < VIRTIO_BLK_MAX_MERGE_REQS);
@@ -774,7 +783,7 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
} while (!virtio_queue_empty(vq));
if (mrb.num_reqs) {
- virtio_blk_submit_multireq(s->blk, &mrb);
+ virtio_blk_submit_multireq(s, &mrb);
}
blk_io_unplug(s->blk);
@@ -823,7 +832,7 @@ void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh)
}
if (mrb.num_reqs) {
- virtio_blk_submit_multireq(s->blk, &mrb);
+ virtio_blk_submit_multireq(s, &mrb);
}
if (is_bh) {
blk_dec_in_flight(s->conf.conf.blk);
@@ -1205,6 +1214,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
}
s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
+ blk_ram_registrar_init(&s->blk_ram_registrar, s->blk);
blk_set_dev_ops(s->blk, &virtio_block_ops, s);
blk_iostatus_enable(s->blk);
@@ -1230,6 +1240,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev)
virtio_del_queue(vdev, i);
}
qemu_coroutine_dec_pool_size(conf->num_queues * conf->queue_size / 2);
+ blk_ram_registrar_destroy(&s->blk_ram_registrar);
qemu_del_vm_change_state_handler(s->change);
blockdev_mark_auto_del(s->blk);
virtio_cleanup(vdev);
diff --git a/hw/core/numa.c b/hw/core/numa.c
index 26d8e5f616..ea24a5fa8c 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -822,6 +822,19 @@ static int ram_block_notify_add_single(RAMBlock *rb, void *opaque)
return 0;
}
+static int ram_block_notify_remove_single(RAMBlock *rb, void *opaque)
+{
+ const ram_addr_t max_size = qemu_ram_get_max_length(rb);
+ const ram_addr_t size = qemu_ram_get_used_length(rb);
+ void *host = qemu_ram_get_host_addr(rb);
+ RAMBlockNotifier *notifier = opaque;
+
+ if (host) {
+ notifier->ram_block_removed(notifier, host, size, max_size);
+ }
+ return 0;
+}
+
void ram_block_notifier_add(RAMBlockNotifier *n)
{
QLIST_INSERT_HEAD(&ram_list.ramblock_notifiers, n, next);
@@ -835,13 +848,18 @@ void ram_block_notifier_add(RAMBlockNotifier *n)
void ram_block_notifier_remove(RAMBlockNotifier *n)
{
QLIST_REMOVE(n, next);
+
+ if (n->ram_block_removed) {
+ qemu_ram_foreach_block(ram_block_notify_remove_single, n);
+ }
}
void ram_block_notify_add(void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;
+ RAMBlockNotifier *next;
- QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
+ QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_added) {
notifier->ram_block_added(notifier, host, size, max_size);
}
@@ -851,8 +869,9 @@ void ram_block_notify_add(void *host, size_t size, size_t max_size)
void ram_block_notify_remove(void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;
+ RAMBlockNotifier *next;
- QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
+ QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_removed) {
notifier->ram_block_removed(notifier, host, size, max_size);
}
@@ -862,8 +881,9 @@ void ram_block_notify_remove(void *host, size_t size, size_t max_size)
void ram_block_notify_resize(void *host, size_t old_size, size_t new_size)
{
RAMBlockNotifier *notifier;
+ RAMBlockNotifier *next;
- QLIST_FOREACH(notifier, &ram_list.ramblock_notifiers, next) {
+ QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_resized) {
notifier->ram_block_resized(notifier, host, old_size, new_size);
}
diff --git a/hw/core/reset.c b/hw/core/reset.c
index 36be82c491..d3263b613e 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -33,6 +33,7 @@ typedef struct QEMUResetEntry {
QTAILQ_ENTRY(QEMUResetEntry) entry;
QEMUResetHandler *func;
void *opaque;
+ bool skip_on_snapshot_load;
} QEMUResetEntry;
static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers =
@@ -47,6 +48,16 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque)
QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
}
+void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque)
+{
+ QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
+
+ re->func = func;
+ re->opaque = opaque;
+ re->skip_on_snapshot_load = true;
+ QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
+}
+
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
{
QEMUResetEntry *re;
@@ -60,12 +71,16 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
}
}
-void qemu_devices_reset(void)
+void qemu_devices_reset(ShutdownCause reason)
{
QEMUResetEntry *re, *nre;
/* reset all devices */
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
+ if (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
+ re->skip_on_snapshot_load) {
+ continue;
+ }
re->func(re->opaque);
}
}
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
index 96a99ce39e..c3df75c6ba 100644
--- a/hw/core/resettable.c
+++ b/hw/core/resettable.c
@@ -201,12 +201,11 @@ static void resettable_phase_exit(Object *obj, void *opaque, ResetType type)
resettable_child_foreach(rc, obj, resettable_phase_exit, NULL, type);
assert(s->count > 0);
- if (s->count == 1) {
+ if (--s->count == 0) {
trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
rc->phases.exit(obj);
}
- s->count = 0;
}
s->exit_phase_in_progress = false;
trace_resettable_phase_exit_end(obj, obj_typename, s->count);
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index e53d5f0fa7..19ea7c2c66 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -411,12 +411,12 @@ static void machine_hppa_init(MachineState *machine)
cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
}
-static void hppa_machine_reset(MachineState *ms)
+static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
{
unsigned int smp_cpus = ms->smp.cpus;
int i;
- qemu_devices_reset();
+ qemu_devices_reset(reason);
/* Start all CPUs at the firmware entry point.
* Monarch CPU will initialize firmware, secondary CPUs
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 4a1b59cb9d..57b402b956 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -157,7 +157,7 @@ void hyperv_synic_reset(CPUState *cs)
SynICState *synic = get_synic(cs);
if (synic) {
- device_legacy_reset(DEVICE(synic));
+ device_cold_reset(DEVICE(synic));
}
}
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 52f9aa9d8c..ffd1884100 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -467,7 +467,7 @@ static void microvm_machine_state_init(MachineState *machine)
microvm_devices_init(mms);
}
-static void microvm_machine_reset(MachineState *machine)
+static void microvm_machine_reset(MachineState *machine, ShutdownCause reason)
{
MicrovmMachineState *mms = MICROVM_MACHINE(machine);
CPUState *cs;
@@ -480,7 +480,7 @@ static void microvm_machine_reset(MachineState *machine)
mms->kernel_cmdline_fixed = true;
}
- qemu_devices_reset();
+ qemu_devices_reset(reason);
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 768982ae9a..3e86083db3 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1847,12 +1847,12 @@ static void pc_machine_initfn(Object *obj)
cxl_machine_init(obj, &pcms->cxl_devices_state);
}
-static void pc_machine_reset(MachineState *machine)
+static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
{
CPUState *cs;
X86CPU *cpu;
- qemu_devices_reset();
+ qemu_devices_reset(reason);
/* Reset APIC after devices have been reset to cancel
* any changes that qemu_devices_reset() might have done.
@@ -1867,7 +1867,7 @@ static void pc_machine_reset(MachineState *machine)
static void pc_machine_wakeup(MachineState *machine)
{
cpu_synchronize_all_states();
- pc_machine_reset(machine);
+ pc_machine_reset(machine, SHUTDOWN_CAUSE_NONE);
cpu_synchronize_all_post_reset();
}
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 1148f70c03..bd50a064a3 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -1111,7 +1111,7 @@ void x86_load_linux(X86MachineState *x86ms,
setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
- qemu_register_reset(reset_rng_seed, setup_data);
+ qemu_register_reset_nosnapshotload(reset_rng_seed, setup_data);
fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
setup_data, kernel, kernel_size, true);
} else {
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index e09e244ddc..9d52ca6613 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -321,27 +321,23 @@ static const TypeInfo glue_info = {
},
};
-typedef struct {
- M68kCPU *cpu;
- struct bi_record *rng_seed;
-} ResetInfo;
-
static void main_cpu_reset(void *opaque)
{
- ResetInfo *reset_info = opaque;
- M68kCPU *cpu = reset_info->cpu;
+ M68kCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
- if (reset_info->rng_seed) {
- qemu_guest_getrandom_nofail((void *)reset_info->rng_seed->data + 2,
- be16_to_cpu(*(uint16_t *)reset_info->rng_seed->data));
- }
-
cpu_reset(cs);
cpu->env.aregs[7] = ldl_phys(cs->as, 0);
cpu->env.pc = ldl_phys(cs->as, 4);
}
+static void rerandomize_rng_seed(void *opaque)
+{
+ struct bi_record *rng_seed = opaque;
+ qemu_guest_getrandom_nofail((void *)rng_seed->data + 2,
+ be16_to_cpu(*(uint16_t *)rng_seed->data));
+}
+
static uint8_t fake_mac_rom[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -397,7 +393,6 @@ static void q800_init(MachineState *machine)
NubusBus *nubus;
DeviceState *glue;
DriveInfo *dinfo;
- ResetInfo *reset_info;
uint8_t rng_seed[32];
linux_boot = (kernel_filename != NULL);
@@ -408,12 +403,9 @@ static void q800_init(MachineState *machine)
exit(1);
}
- reset_info = g_new0(ResetInfo, 1);
-
/* init CPUs */
cpu = M68K_CPU(cpu_create(machine->cpu_type));
- reset_info->cpu = cpu;
- qemu_register_reset(main_cpu_reset, reset_info);
+ qemu_register_reset(main_cpu_reset, cpu);
/* RAM */
memory_region_add_subregion(get_system_memory(), 0, machine->ram);
@@ -687,9 +679,10 @@ static void q800_init(MachineState *machine)
BOOTINFO0(param_ptr, BI_LAST);
rom_add_blob_fixed_as("bootinfo", param_blob, param_ptr - param_blob,
parameters_base, cs->as);
- reset_info->rng_seed = rom_ptr_for_as(cs->as, parameters_base,
- param_ptr - param_blob) +
- (param_rng_seed - param_blob);
+ qemu_register_reset_nosnapshotload(rerandomize_rng_seed,
+ rom_ptr_for_as(cs->as, parameters_base,
+ param_ptr - param_blob) +
+ (param_rng_seed - param_blob));
g_free(param_blob);
} else {
uint8_t *ptr;
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 89c4108eb5..da5eafd275 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -89,7 +89,6 @@ typedef struct {
M68kCPU *cpu;
hwaddr initial_pc;
hwaddr initial_stack;
- struct bi_record *rng_seed;
} ResetInfo;
static void main_cpu_reset(void *opaque)
@@ -98,16 +97,18 @@ static void main_cpu_reset(void *opaque)
M68kCPU *cpu = reset_info->cpu;
CPUState *cs = CPU(cpu);
- if (reset_info->rng_seed) {
- qemu_guest_getrandom_nofail((void *)reset_info->rng_seed->data + 2,
- be16_to_cpu(*(uint16_t *)reset_info->rng_seed->data));
- }
-
cpu_reset(cs);
cpu->env.aregs[7] = reset_info->initial_stack;
cpu->env.pc = reset_info->initial_pc;
}
+static void rerandomize_rng_seed(void *opaque)
+{
+ struct bi_record *rng_seed = opaque;
+ qemu_guest_getrandom_nofail((void *)rng_seed->data + 2,
+ be16_to_cpu(*(uint16_t *)rng_seed->data));
+}
+
static void virt_init(MachineState *machine)
{
M68kCPU *cpu = NULL;
@@ -289,9 +290,10 @@ static void virt_init(MachineState *machine)
BOOTINFO0(param_ptr, BI_LAST);
rom_add_blob_fixed_as("bootinfo", param_blob, param_ptr - param_blob,
parameters_base, cs->as);
- reset_info->rng_seed = rom_ptr_for_as(cs->as, parameters_base,
- param_ptr - param_blob) +
- (param_rng_seed - param_blob);
+ qemu_register_reset_nosnapshotload(rerandomize_rng_seed,
+ rom_ptr_for_as(cs->as, parameters_base,
+ param_ptr - param_blob) +
+ (param_rng_seed - param_blob));
g_free(param_blob);
}
}
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 7c7d777781..31080c22c9 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -149,7 +149,7 @@ static void nvdimm_prepare_memory_region(NVDIMMDevice *nvdimm, Error **errp)
if (!nvdimm->unarmed && memory_region_is_rom(mr)) {
HostMemoryBackend *hostmem = dimm->hostmem;
- error_setg(errp, "'unarmed' property must be off since memdev %s "
+ error_setg(errp, "'unarmed' property must be 'on' since memdev %s "
"is read-only",
object_get_canonical_path_component(OBJECT(hostmem)));
return;
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index d2ab9da1a0..cab63f43bf 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -41,6 +41,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "sysemu/runstate.h"
+#include "sysemu/reset.h"
#include <libfdt.h>
#include "qom/object.h"
@@ -810,6 +811,8 @@ static void boston_mach_init(MachineState *machine)
/* Calculate real fdt size after filter */
dt_size = fdt_totalsize(dtb_load_data);
rom_add_blob_fixed("dtb", dtb_load_data, dt_size, dtb_paddr);
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
+ rom_ptr(dtb_paddr, dt_size));
} else {
/* Try to load file as FIT */
fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index 0e932988e0..7c3ad0974b 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -26,6 +26,7 @@
#include "qemu/units.h"
#include "qemu/bitops.h"
#include "qemu/datadir.h"
+#include "qemu/guest-random.h"
#include "hw/clock.h"
#include "hw/southbridge/piix.h"
#include "hw/isa/superio.h"
@@ -1017,6 +1018,17 @@ static void G_GNUC_PRINTF(3, 4) prom_set(uint32_t *prom_buf, int index,
va_end(ap);
}
+static void reinitialize_rng_seed(void *opaque)
+{
+ char *rng_seed_hex = opaque;
+ uint8_t rng_seed[32];
+
+ qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+ for (size_t i = 0; i < sizeof(rng_seed); ++i) {
+ sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]);
+ }
+}
+
/* Kernel */
static uint64_t load_kernel(void)
{
@@ -1028,6 +1040,9 @@ static uint64_t load_kernel(void)
long prom_size;
int prom_index = 0;
uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
+ uint8_t rng_seed[32];
+ char rng_seed_hex[sizeof(rng_seed) * 2 + 1];
+ size_t rng_seed_prom_offset;
#if TARGET_BIG_ENDIAN
big_endian = 1;
@@ -1115,9 +1130,21 @@ static uint64_t load_kernel(void)
prom_set(prom_buf, prom_index++, "modetty0");
prom_set(prom_buf, prom_index++, "38400n8r");
+
+ qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+ for (size_t i = 0; i < sizeof(rng_seed); ++i) {
+ sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]);
+ }
+ prom_set(prom_buf, prom_index++, "rngseed");
+ rng_seed_prom_offset = prom_index * ENVP_ENTRY_SIZE +
+ sizeof(uint32_t) * ENVP_NB_ENTRIES;
+ prom_set(prom_buf, prom_index++, "%s", rng_seed_hex);
+
prom_set(prom_buf, prom_index++, NULL);
rom_add_blob_fixed("prom", prom_buf, prom_size, ENVP_PADDR);
+ qemu_register_reset_nosnapshotload(reinitialize_rng_seed,
+ rom_ptr(ENVP_PADDR, prom_size) + rng_seed_prom_offset);
g_free(prom_buf);
return kernel_entry;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index e9f696b4cf..b6903aea54 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2526,6 +2526,7 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
VirtIONet *n = qemu_get_nic_opaque(nc);
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
VirtIODevice *vdev = VIRTIO_DEVICE(n);
+ int ret;
virtqueue_push(q->tx_vq, q->async_tx.elem, 0);
virtio_notify(vdev, q->tx_vq);
@@ -2534,7 +2535,22 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
q->async_tx.elem = NULL;
virtio_queue_set_notification(q->tx_vq, 1);
- virtio_net_flush_tx(q);
+ ret = virtio_net_flush_tx(q);
+ if (ret >= n->tx_burst) {
+ /*
+ * the flush has been stopped by tx_burst
+ * we will not receive notification for the
+ * remainining part, so re-schedule
+ */
+ virtio_queue_set_notification(q->tx_vq, 0);
+ if (q->tx_bh) {
+ qemu_bh_schedule(q->tx_bh);
+ } else {
+ timer_mod(q->tx_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
+ }
+ q->tx_waiting = 1;
+ }
}
/* TX */
@@ -2633,6 +2649,8 @@ drop:
return num_packets;
}
+static void virtio_net_tx_timer(void *opaque);
+
static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIONet *n = VIRTIO_NET(vdev);
@@ -2650,15 +2668,13 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
}
if (q->tx_waiting) {
- virtio_queue_set_notification(vq, 1);
+ /* We already have queued packets, immediately flush */
timer_del(q->tx_timer);
- q->tx_waiting = 0;
- if (virtio_net_flush_tx(q) == -EINVAL) {
- return;
- }
+ virtio_net_tx_timer(q);
} else {
+ /* re-arm timer to flush it (and more) on next tick */
timer_mod(q->tx_timer,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
q->tx_waiting = 1;
virtio_queue_set_notification(vq, 0);
}
@@ -2691,6 +2707,8 @@ static void virtio_net_tx_timer(void *opaque)
VirtIONetQueue *q = opaque;
VirtIONet *n = q->n;
VirtIODevice *vdev = VIRTIO_DEVICE(n);
+ int ret;
+
/* This happens when device was stopped but BH wasn't. */
if (!vdev->vm_running) {
/* Make sure tx waiting is set, so we'll run when restarted. */
@@ -2705,8 +2723,33 @@ static void virtio_net_tx_timer(void *opaque)
return;
}
+ ret = virtio_net_flush_tx(q);
+ if (ret == -EBUSY || ret == -EINVAL) {
+ return;
+ }
+ /*
+ * If we flush a full burst of packets, assume there are
+ * more coming and immediately rearm
+ */
+ if (ret >= n->tx_burst) {
+ q->tx_waiting = 1;
+ timer_mod(q->tx_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
+ return;
+ }
+ /*
+ * If less than a full burst, re-enable notification and flush
+ * anything that may have come in while we weren't looking. If
+ * we find something, assume the guest is still active and rearm
+ */
virtio_queue_set_notification(q->tx_vq, 1);
- virtio_net_flush_tx(q);
+ ret = virtio_net_flush_tx(q);
+ if (ret > 0) {
+ virtio_queue_set_notification(q->tx_vq, 0);
+ q->tx_waiting = 1;
+ timer_mod(q->tx_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
+ }
}
static void virtio_net_tx_bh(void *opaque)
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
index 5c815b4f0c..7d92c2d022 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -296,9 +296,8 @@ static int net_init(struct XenLegacyDevice *xendev)
netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
"xen", NULL, netdev);
- snprintf(qemu_get_queue(netdev->nic)->info_str,
- sizeof(qemu_get_queue(netdev->nic)->info_str),
- "nic: xenbus vif macaddr=%s", netdev->mac);
+ qemu_set_info_str(qemu_get_queue(netdev->nic),
+ "nic: xenbus vif macaddr=%s", netdev->mac);
/* fill info */
xenstore_write_be_int(&netdev->xendev, "feature-rx-copy", 1);
diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c
index 128ccbcba2..007e80cd5a 100644
--- a/hw/openrisc/boot.c
+++ b/hw/openrisc/boot.c
@@ -14,6 +14,7 @@
#include "hw/openrisc/boot.h"
#include "sysemu/device_tree.h"
#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
#include <libfdt.h>
@@ -111,6 +112,8 @@ uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start,
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
&address_space_memory);
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
+ rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));
return fdt_addr;
}
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index ecf682b148..bb4d008ba9 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -248,14 +248,14 @@ static void pegasos2_pci_config_write(Pegasos2MachineState *pm, int bus,
pegasos2_mv_reg_write(pm, pcicfg + 4, len, val);
}
-static void pegasos2_machine_reset(MachineState *machine)
+static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason)
{
Pegasos2MachineState *pm = PEGASOS2_MACHINE(machine);
void *fdt;
uint64_t d[2];
int sz;
- qemu_devices_reset();
+ qemu_devices_reset(reason);
if (!pm->vof) {
return; /* Firmware should set up machine so nothing to do */
}
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 40bb573d1a..3d01e26f84 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -643,13 +643,13 @@ static void pnv_powerdown_notify(Notifier *n, void *opaque)
}
}
-static void pnv_reset(MachineState *machine)
+static void pnv_reset(MachineState *machine, ShutdownCause reason)
{
PnvMachineState *pnv = PNV_MACHINE(machine);
IPMIBmc *bmc;
void *fdt;
- qemu_devices_reset();
+ qemu_devices_reset(reason);
/*
* The machine should provide by default an internal BMC simulator.
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index f79ac85ca1..66b414d2e9 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1623,7 +1623,7 @@ void spapr_check_mmu_mode(bool guest_radix)
}
}
-static void spapr_machine_reset(MachineState *machine)
+static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
{
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
PowerPCCPU *first_ppc_cpu;
@@ -1649,7 +1649,7 @@ static void spapr_machine_reset(MachineState *machine)
spapr_setup_hpt(spapr);
}
- qemu_devices_reset();
+ qemu_devices_reset(reason);
spapr_ovec_cleanup(spapr->ov5_cas);
spapr->ov5_cas = spapr_ovec_new();
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index e82bf27338..ebd351c840 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -30,6 +30,7 @@
#include "sysemu/device_tree.h"
#include "sysemu/qtest.h"
#include "sysemu/kvm.h"
+#include "sysemu/reset.h"
#include <libfdt.h>
@@ -241,6 +242,8 @@ uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
&address_space_memory);
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
+ rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));
return fdt_addr;
}
diff --git a/hw/rx/rx-gdbsim.c b/hw/rx/rx-gdbsim.c
index 8ffe1b8035..47c17026c7 100644
--- a/hw/rx/rx-gdbsim.c
+++ b/hw/rx/rx-gdbsim.c
@@ -25,6 +25,7 @@
#include "hw/rx/rx62n.h"
#include "sysemu/qtest.h"
#include "sysemu/device_tree.h"
+#include "sysemu/reset.h"
#include "hw/boards.h"
#include "qom/object.h"
@@ -148,6 +149,8 @@ static void rx_gdbsim_init(MachineState *machine)
dtb_offset = ROUND_DOWN(machine->ram_size - dtb_size, 16);
rom_add_blob_fixed("dtb", dtb, dtb_size,
SDRAM_BASE + dtb_offset);
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
+ rom_ptr(SDRAM_BASE + dtb_offset, dtb_size));
/* Set dtb address to R1 */
RX_CPU(first_cpu)->env.regs[1] = SDRAM_BASE + dtb_offset;
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1cc20d8717..806de32034 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -411,7 +411,7 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms)
s390_pv_prep_reset();
}
-static void s390_machine_reset(MachineState *machine)
+static void s390_machine_reset(MachineState *machine, ShutdownCause reason)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
enum s390_reset reset_type;
@@ -433,7 +433,7 @@ static void s390_machine_reset(MachineState *machine)
s390_machine_unprotect(ms);
}
- qemu_devices_reset();
+ qemu_devices_reset(reason);
s390_crypto_reset();
/* configure and start the ipl CPU only */
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 2bf8c754b2..ec0fa440d7 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -275,10 +275,15 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
/* If IOVW bit is set then set the timer value */
ptimer_set_count(s->timer_reload, s->lr);
}
-
+ /*
+ * Commit the change to s->timer_reload, so it can propagate. Otherwise
+ * the timer interrupt may not fire properly. The commit must happen
+ * before calling imx_epit_reload_compare_timer(), which reads
+ * s->timer_reload internally again.
+ */
+ ptimer_transaction_commit(s->timer_reload);
imx_epit_reload_compare_timer(s);
ptimer_transaction_commit(s->timer_cmp);
- ptimer_transaction_commit(s->timer_reload);
break;
case 3: /* CMP */
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 596d4434d2..5bd14cad96 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -33,6 +33,7 @@ bool vhost_svq_valid_features(uint64_t features, Error **errp)
++b) {
switch (b) {
case VIRTIO_F_ANY_LAYOUT:
+ case VIRTIO_RING_F_EVENT_IDX:
continue;
case VIRTIO_F_ACCESS_PLATFORM:
@@ -218,12 +219,22 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,
static void vhost_svq_kick(VhostShadowVirtqueue *svq)
{
+ bool needs_kick;
+
/*
* We need to expose the available array entries before checking the used
* flags
*/
smp_mb();
- if (svq->vring.used->flags & VRING_USED_F_NO_NOTIFY) {
+
+ if (virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ uint16_t avail_event = *(uint16_t *)(&svq->vring.used->ring[svq->vring.num]);
+ needs_kick = vring_need_event(avail_event, svq->shadow_avail_idx, svq->shadow_avail_idx - 1);
+ } else {
+ needs_kick = !(svq->vring.used->flags & VRING_USED_F_NO_NOTIFY);
+ }
+
+ if (!needs_kick) {
return;
}
@@ -369,15 +380,27 @@ static bool vhost_svq_more_used(VhostShadowVirtqueue *svq)
*/
static bool vhost_svq_enable_notification(VhostShadowVirtqueue *svq)
{
- svq->vring.avail->flags &= ~cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
- /* Make sure the flag is written before the read of used_idx */
+ if (virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ uint16_t *used_event = (uint16_t *)&svq->vring.avail->ring[svq->vring.num];
+ *used_event = svq->shadow_used_idx;
+ } else {
+ svq->vring.avail->flags &= ~cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
+ }
+
+ /* Make sure the event is enabled before the read of used_idx */
smp_mb();
return !vhost_svq_more_used(svq);
}
static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
{
- svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
+ /*
+ * No need to disable notification in the event idx case, since used event
+ * index is already an index too far away.
+ */
+ if (!virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_EVENT_IDX)) {
+ svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
+ }
}
static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
@@ -570,16 +593,16 @@ void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq,
size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq)
{
size_t desc_size = sizeof(vring_desc_t) * svq->vring.num;
- size_t avail_size = offsetof(vring_avail_t, ring) +
- sizeof(uint16_t) * svq->vring.num;
+ size_t avail_size = offsetof(vring_avail_t, ring[svq->vring.num]) +
+ sizeof(uint16_t);
return ROUND_UP(desc_size + avail_size, qemu_real_host_page_size());
}
size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq)
{
- size_t used_size = offsetof(vring_used_t, ring) +
- sizeof(vring_used_elem_t) * svq->vring.num;
+ size_t used_size = offsetof(vring_used_t, ring[svq->vring.num]) +
+ sizeof(uint16_t);
return ROUND_UP(used_size, qemu_real_host_page_size());
}
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 30d03e987a..ed170def48 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -467,7 +467,7 @@ static int virtio_mem_set_block_state(VirtIOMEM *vmem, uint64_t start_gpa,
int fd = memory_region_get_fd(&vmem->memdev->mr);
Error *local_err = NULL;
- os_mem_prealloc(fd, area, size, 1, &local_err);
+ qemu_prealloc_mem(fd, area, size, 1, NULL, &local_err);
if (local_err) {
static bool warned;