diff options
| -rw-r--r-- | hw/9pfs/9p.c | 6 | ||||
| -rw-r--r-- | hw/i386/intel_iommu.c | 40 | ||||
| -rw-r--r-- | hw/i386/intel_iommu_internal.h | 18 | ||||
| -rw-r--r-- | hw/input/virtio-input.c | 3 | ||||
| -rw-r--r-- | hw/net/virtio-net.c | 58 | ||||
| -rw-r--r-- | hw/riscv/boot.c | 7 | ||||
| -rw-r--r-- | hw/riscv/sifive_e.c | 2 | ||||
| -rw-r--r-- | hw/riscv/sifive_u.c | 3 | ||||
| -rw-r--r-- | hw/riscv/spike.c | 6 | ||||
| -rw-r--r-- | hw/riscv/virt.c | 8 | ||||
| -rw-r--r-- | include/hw/riscv/boot.h | 3 | ||||
| -rw-r--r-- | migration/savevm.c | 3 | ||||
| -rw-r--r-- | util/cutils.c | 8 |
13 files changed, 104 insertions, 61 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 37abcdb71e..520177f40c 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1834,8 +1834,10 @@ static int32_t coroutine_fn get_iounit(V9fsPDU *pdu, V9fsPath *path) * and as well as less than (client msize - P9_IOHDRSZ)) */ if (!v9fs_co_statfs(pdu, path, &stbuf)) { - iounit = stbuf.f_bsize; - iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize; + if (stbuf.f_bsize) { + iounit = stbuf.f_bsize; + iounit *= (s->msize - P9_IOHDRSZ) / stbuf.f_bsize; + } } if (!iounit) { iounit = s->msize - P9_IOHDRSZ; diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 14e4e6ad62..43c94b993b 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -910,19 +910,23 @@ static dma_addr_t vtd_get_iova_pgtbl_base(IntelIOMMUState *s, /* * Rsvd field masks for spte: - * Index [1] to [4] 4k pages - * Index [5] to [8] large pages + * vtd_spte_rsvd 4k pages + * vtd_spte_rsvd_large large pages */ -static uint64_t vtd_paging_entry_rsvd_field[9]; +static uint64_t vtd_spte_rsvd[5]; +static uint64_t vtd_spte_rsvd_large[5]; static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level) { - if (slpte & VTD_SL_PT_PAGE_SIZE_MASK) { - /* Maybe large page */ - return slpte & vtd_paging_entry_rsvd_field[level + 4]; - } else { - return slpte & vtd_paging_entry_rsvd_field[level]; + uint64_t rsvd_mask = vtd_spte_rsvd[level]; + + if ((level == VTD_SL_PD_LEVEL || level == VTD_SL_PDP_LEVEL) && + (slpte & VTD_SL_PT_PAGE_SIZE_MASK)) { + /* large page */ + rsvd_mask = vtd_spte_rsvd_large[level]; } + + return slpte & rsvd_mask; } /* Find the VTD address space associated with a given bus number */ @@ -3549,15 +3553,17 @@ static void vtd_init(IntelIOMMUState *s) /* * Rsvd field masks for spte */ - vtd_paging_entry_rsvd_field[0] = ~0ULL; - vtd_paging_entry_rsvd_field[1] = VTD_SPTE_PAGE_L1_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[2] = VTD_SPTE_PAGE_L2_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[3] = VTD_SPTE_PAGE_L3_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[4] = VTD_SPTE_PAGE_L4_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[5] = VTD_SPTE_LPAGE_L1_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[6] = VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[7] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits); - vtd_paging_entry_rsvd_field[8] = VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_bits); + vtd_spte_rsvd[0] = ~0ULL; + vtd_spte_rsvd[1] = VTD_SPTE_PAGE_L1_RSVD_MASK(s->aw_bits, + x86_iommu->dt_supported); + vtd_spte_rsvd[2] = VTD_SPTE_PAGE_L2_RSVD_MASK(s->aw_bits); + vtd_spte_rsvd[3] = VTD_SPTE_PAGE_L3_RSVD_MASK(s->aw_bits); + vtd_spte_rsvd[4] = VTD_SPTE_PAGE_L4_RSVD_MASK(s->aw_bits); + + vtd_spte_rsvd_large[2] = VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_bits, + x86_iommu->dt_supported); + vtd_spte_rsvd_large[3] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits, + x86_iommu->dt_supported); if (x86_iommu_ir_supported(x86_iommu)) { s->ecap |= VTD_ECAP_IR | VTD_ECAP_MHMV; diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index c1235a7063..edcf9fc9bb 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -387,7 +387,9 @@ typedef union VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 /* Rsvd field masks for spte */ -#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw) \ +#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw, dt_supported) \ + dt_supported ? \ + (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \ (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) #define VTD_SPTE_PAGE_L2_RSVD_MASK(aw) \ (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) @@ -395,14 +397,15 @@ typedef union VTDInvDesc VTDInvDesc; (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) #define VTD_SPTE_PAGE_L4_RSVD_MASK(aw) \ (0x880ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) -#define VTD_SPTE_LPAGE_L1_RSVD_MASK(aw) \ - (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) -#define VTD_SPTE_LPAGE_L2_RSVD_MASK(aw) \ + +#define VTD_SPTE_LPAGE_L2_RSVD_MASK(aw, dt_supported) \ + dt_supported ? \ + (0x1ff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \ (0x1ff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) -#define VTD_SPTE_LPAGE_L3_RSVD_MASK(aw) \ +#define VTD_SPTE_LPAGE_L3_RSVD_MASK(aw, dt_supported) \ + dt_supported ? \ + (0x3ffff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \ (0x3ffff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) -#define VTD_SPTE_LPAGE_L4_RSVD_MASK(aw) \ - (0x880ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) /* Information about page-selective IOTLB invalidate */ struct VTDIOTLBPageInvInfo { @@ -506,5 +509,6 @@ typedef struct VTDRootEntry VTDRootEntry; #define VTD_SL_W (1ULL << 1) #define VTD_SL_PT_BASE_ADDR_MASK(aw) (~(VTD_PAGE_SIZE - 1) & VTD_HAW_MASK(aw)) #define VTD_SL_IGN_COM 0xbff0000000000000ULL +#define VTD_SL_TM (1ULL << 62) #endif diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c index 51617a5885..ec54e46ad6 100644 --- a/hw/input/virtio-input.c +++ b/hw/input/virtio-input.c @@ -275,6 +275,7 @@ static void virtio_input_finalize(Object *obj) g_free(vinput->queue); } + static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) { VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); @@ -288,6 +289,8 @@ static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) return; } } + virtio_del_queue(vdev, 0); + virtio_del_queue(vdev, 1); virtio_cleanup(vdev); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 97a5113f7e..3c31471026 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -759,6 +759,10 @@ static void failover_add_primary(VirtIONet *n, Error **errp) { Error *err = NULL; + if (n->primary_dev) { + return; + } + n->primary_device_opts = qemu_opts_find(qemu_find_opts("device"), n->primary_device_id); if (n->primary_device_opts) { @@ -2801,25 +2805,33 @@ static bool failover_replug_primary(VirtIONet *n, Error **errp) n->primary_device_opts = qemu_opts_from_qdict( qemu_find_opts("device"), n->primary_device_dict, errp); - } - if (n->primary_device_opts) { - if (n->primary_dev) { - n->primary_bus = n->primary_dev->parent_bus; - } - qdev_set_parent_bus(n->primary_dev, n->primary_bus); - n->primary_should_be_hidden = false; - qemu_opt_set_bool(n->primary_device_opts, - "partially_hotplugged", true, errp); - hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev); - if (hotplug_ctrl) { - hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, errp); - hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp); + if (!n->primary_device_opts) { + error_setg(errp, "virtio_net: couldn't find primary device opts"); + goto out; } - if (!n->primary_dev) { + } + if (!n->primary_dev) { error_setg(errp, "virtio_net: couldn't find primary device"); - } + goto out; } - return *errp != NULL; + + n->primary_bus = n->primary_dev->parent_bus; + if (!n->primary_bus) { + error_setg(errp, "virtio_net: couldn't find primary bus"); + goto out; + } + qdev_set_parent_bus(n->primary_dev, n->primary_bus); + n->primary_should_be_hidden = false; + qemu_opt_set_bool(n->primary_device_opts, + "partially_hotplugged", true, errp); + hotplug_ctrl = qdev_get_hotplug_handler(n->primary_dev); + if (hotplug_ctrl) { + hotplug_handler_pre_plug(hotplug_ctrl, n->primary_dev, errp); + hotplug_handler_plug(hotplug_ctrl, n->primary_dev, errp); + } + +out: + return *errp == NULL; } static void virtio_net_handle_migration_primary(VirtIONet *n, @@ -2848,7 +2860,7 @@ static void virtio_net_handle_migration_primary(VirtIONet *n, warn_report("couldn't unplug primary device"); } } else if (migration_has_failed(s)) { - /* We already unplugged the device let's plugged it back */ + /* We already unplugged the device let's plug it back */ if (!failover_replug_primary(n, &err)) { if (err) { error_report_err(err); @@ -2868,9 +2880,12 @@ static int virtio_net_primary_should_be_hidden(DeviceListener *listener, QemuOpts *device_opts) { VirtIONet *n = container_of(listener, VirtIONet, primary_listener); - bool match_found; - bool hide; + bool match_found = false; + bool hide = false; + if (!device_opts) { + return -1; + } n->primary_device_dict = qemu_opts_to_qdict(device_opts, n->primary_device_dict); if (n->primary_device_dict) { @@ -2878,7 +2893,7 @@ static int virtio_net_primary_should_be_hidden(DeviceListener *listener, n->standby_id = g_strdup(qdict_get_try_str(n->primary_device_dict, "failover_pair_id")); } - if (device_opts && g_strcmp0(n->standby_id, n->netclient_name) == 0) { + if (g_strcmp0(n->standby_id, n->netclient_name) == 0) { match_found = true; } else { match_found = false; @@ -3124,6 +3139,9 @@ static bool primary_unplug_pending(void *opaque) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIONet *n = VIRTIO_NET(vdev); + if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_STANDBY)) { + return false; + } return n->primary_dev ? n->primary_dev->pending_deleted_event : false; } diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 7fee98d2f8..027303d2a3 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -114,12 +114,13 @@ target_ulong riscv_load_firmware(const char *firmware_filename, exit(1); } -target_ulong riscv_load_kernel(const char *kernel_filename) +target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb) { uint64_t kernel_entry, kernel_high; - if (load_elf(kernel_filename, NULL, NULL, NULL, - &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0) > 0) { + if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, + &kernel_entry, NULL, &kernel_high, 0, + EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { return kernel_entry; } diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 0f9d641a0e..8a6b0348df 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -111,7 +111,7 @@ static void riscv_sifive_e_init(MachineState *machine) memmap[SIFIVE_E_MROM].base, &address_space_memory); if (machine->kernel_filename) { - riscv_load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename, NULL); } } diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 9552abf4dd..0140e95732 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -344,7 +344,8 @@ static void riscv_sifive_u_init(MachineState *machine) memmap[SIFIVE_U_DRAM].base); if (machine->kernel_filename) { - uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename); + uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, + NULL); if (machine->initrd_filename) { hwaddr start; diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 8bbffbcd0f..8823681783 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -184,7 +184,7 @@ static void spike_board_init(MachineState *machine) mask_rom); if (machine->kernel_filename) { - riscv_load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename, htif_symbol_callback); } /* reset vector */ @@ -273,7 +273,7 @@ static void spike_v1_10_0_board_init(MachineState *machine) mask_rom); if (machine->kernel_filename) { - riscv_load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename, htif_symbol_callback); } /* reset vector */ @@ -359,7 +359,7 @@ static void spike_v1_09_1_board_init(MachineState *machine) mask_rom); if (machine->kernel_filename) { - riscv_load_kernel(machine->kernel_filename); + riscv_load_kernel(machine->kernel_filename, htif_symbol_callback); } /* reset vector */ diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 23f340df19..c44b865959 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -359,7 +359,10 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, nodename = g_strdup_printf("/test@%lx", (long)memmap[VIRT_TEST].base); qemu_fdt_add_subnode(fdt, nodename); - qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,test0"); + { + const char compat[] = "sifive,test1\0sifive,test0"; + qemu_fdt_setprop(fdt, nodename, "compatible", compat, sizeof(compat)); + } qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[VIRT_TEST].base, 0x0, memmap[VIRT_TEST].size); @@ -476,7 +479,8 @@ static void riscv_virt_board_init(MachineState *machine) memmap[VIRT_DRAM].base); if (machine->kernel_filename) { - uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename); + uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename, + NULL); if (machine->initrd_filename) { hwaddr start; diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 66075d0e57..df80051fbc 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -28,7 +28,8 @@ void riscv_find_and_load_firmware(MachineState *machine, char *riscv_find_firmware(const char *firmware_filename); target_ulong riscv_load_firmware(const char *firmware_filename, hwaddr firmware_load_addr); -target_ulong riscv_load_kernel(const char *kernel_filename); +target_ulong riscv_load_kernel(const char *kernel_filename, + symbol_fn_t sym_cb); hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size, uint64_t kernel_entry, hwaddr *start); diff --git a/migration/savevm.c b/migration/savevm.c index 966a9c3bdb..a71b930b91 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1119,7 +1119,8 @@ int qemu_savevm_nr_failover_devices(void) int n = 0; QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { - if (se->vmsd && se->vmsd->dev_unplug_pending) { + if (se->vmsd && se->vmsd->dev_unplug_pending && + se->vmsd->dev_unplug_pending(se->opaque)) { n++; } } diff --git a/util/cutils.c b/util/cutils.c index fd591cadf0..77acadc70a 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -239,10 +239,12 @@ static int do_strtosz(const char *nptr, const char **end, goto out; } /* - * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip - * through double (53 bits of precision). + * Values near UINT64_MAX overflow to 2**64 when converting to double + * precision. Compare against the maximum representable double precision + * value below 2**64, computed as "the next value after 2**64 (0x1p64) in + * the direction of 0". */ - if ((val * mul >= 0xfffffffffffffc00) || val < 0) { + if ((val * mul > nextafter(0x1p64, 0)) || val < 0) { retval = -ERANGE; goto out; } |