diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/xlnx-versal.c | 2 | ||||
-rw-r--r-- | hw/misc/mos6522.c | 8 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 58 | ||||
-rw-r--r-- | hw/ppc/spapr_events.c | 1 | ||||
-rw-r--r-- | hw/ppc/spapr_irq.c | 17 | ||||
-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-- | hw/vfio/pci.c | 64 | ||||
-rw-r--r-- | hw/vfio/pci.h | 1 |
12 files changed, 121 insertions, 56 deletions
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 98163eb1aa..8b3d8d85b8 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -257,6 +257,8 @@ static void versal_unimp(Versal *s) MM_CRL, MM_CRL_SIZE); versal_unimp_area(s, "crf", &s->mr_ps, MM_FPD_CRF, MM_FPD_CRF_SIZE); + versal_unimp_area(s, "crp", &s->mr_ps, + MM_PMC_CRP, MM_PMC_CRP_SIZE); versal_unimp_area(s, "iou-scntr", &s->mr_ps, MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE); versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps, diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c index aa3bfe1afd..cecf0be59e 100644 --- a/hw/misc/mos6522.c +++ b/hw/misc/mos6522.c @@ -113,6 +113,10 @@ static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti, int64_t d, next_time; unsigned int counter; + if (ti->frequency == 0) { + return INT64_MAX; + } + /* current counter value */ d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time, ti->frequency, NANOSECONDS_PER_SECOND); @@ -149,10 +153,10 @@ static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti, if (!ti->timer) { return; } + ti->next_irq_time = get_next_irq_time(s, ti, current_time); if ((s->ier & T1_INT) == 0 || (s->acr & T1MODE) != T1MODE_CONT) { timer_del(ti->timer); } else { - ti->next_irq_time = get_next_irq_time(s, ti, current_time); timer_mod(ti->timer, ti->next_irq_time); } } @@ -163,10 +167,10 @@ static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti, if (!ti->timer) { return; } + ti->next_irq_time = get_next_irq_time(s, ti, current_time); if ((s->ier & T2_INT) == 0) { timer_del(ti->timer); } else { - ti->next_irq_time = get_next_irq_time(s, ti, current_time); timer_mod(ti->timer, ti->next_irq_time); } } 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/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 0e4c19523a..e355e000d0 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -358,6 +358,7 @@ static SpaprEventLogEntry *rtas_event_log_dequeue(SpaprMachineState *spapr, rtas_event_log_to_source(spapr, spapr_event_log_entry_type(entry)); + g_assert(source); if (source->mask & event_mask) { break; } diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 168044be85..d6bb7fd2d6 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -373,6 +373,14 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp) spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr, smc->nr_xirqs + SPAPR_XIRQ_BASE); + + /* + * Mostly we don't actually need this until reset, except that not + * having this set up can cause VFIO devices to issue a + * false-positive warning during realize(), because they don't yet + * have an in-kernel irq chip. + */ + spapr_irq_update_active_intc(spapr); } int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp) @@ -508,6 +516,12 @@ static void set_active_intc(SpaprMachineState *spapr, } spapr->active_intc = new_intc; + + /* + * We've changed the kernel irqchip, let VFIO devices know they + * need to readjust. + */ + kvm_irqchip_change_notify(); } void spapr_irq_update_active_intc(SpaprMachineState *spapr) @@ -522,7 +536,8 @@ void spapr_irq_update_active_intc(SpaprMachineState *spapr) * this. */ new_intc = SPAPR_INTC(spapr->xive); - } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) { + } else if (spapr->ov5_cas + && spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) { new_intc = SPAPR_INTC(spapr->xive); } else { new_intc = SPAPR_INTC(spapr->ics); 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/hw/vfio/pci.c b/hw/vfio/pci.c index 0c55883bba..2d40b396f2 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -216,30 +216,18 @@ static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev) #endif } -static void vfio_intx_update(PCIDevice *pdev) +static void vfio_intx_update(VFIOPCIDevice *vdev, PCIINTxRoute *route) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); - PCIINTxRoute route; Error *err = NULL; - if (vdev->interrupt != VFIO_INT_INTx) { - return; - } - - route = pci_device_route_intx_to_irq(&vdev->pdev, vdev->intx.pin); - - if (!pci_intx_route_changed(&vdev->intx.route, &route)) { - return; /* Nothing changed */ - } - trace_vfio_intx_update(vdev->vbasedev.name, - vdev->intx.route.irq, route.irq); + vdev->intx.route.irq, route->irq); vfio_intx_disable_kvm(vdev); - vdev->intx.route = route; + vdev->intx.route = *route; - if (route.mode != PCI_INTX_ENABLED) { + if (route->mode != PCI_INTX_ENABLED) { return; } @@ -252,6 +240,30 @@ static void vfio_intx_update(PCIDevice *pdev) vfio_intx_eoi(&vdev->vbasedev); } +static void vfio_intx_routing_notifier(PCIDevice *pdev) +{ + VFIOPCIDevice *vdev = PCI_VFIO(pdev); + PCIINTxRoute route; + + if (vdev->interrupt != VFIO_INT_INTx) { + return; + } + + route = pci_device_route_intx_to_irq(&vdev->pdev, vdev->intx.pin); + + if (pci_intx_route_changed(&vdev->intx.route, &route)) { + vfio_intx_update(vdev, &route); + } +} + +static void vfio_irqchip_change(Notifier *notify, void *data) +{ + VFIOPCIDevice *vdev = container_of(notify, VFIOPCIDevice, + irqchip_change_notifier); + + vfio_intx_update(vdev, &vdev->intx.route); +} + static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) { uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1); @@ -2967,31 +2979,34 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) { vdev->intx.mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, vfio_intx_mmap_enable, vdev); - pci_device_set_intx_routing_notifier(&vdev->pdev, vfio_intx_update); + pci_device_set_intx_routing_notifier(&vdev->pdev, + vfio_intx_routing_notifier); + vdev->irqchip_change_notifier.notify = vfio_irqchip_change; + kvm_irqchip_add_change_notifier(&vdev->irqchip_change_notifier); ret = vfio_intx_enable(vdev, errp); if (ret) { - goto out_teardown; + goto out_deregister; } } if (vdev->display != ON_OFF_AUTO_OFF) { ret = vfio_display_probe(vdev, errp); if (ret) { - goto out_teardown; + goto out_deregister; } } if (vdev->enable_ramfb && vdev->dpy == NULL) { error_setg(errp, "ramfb=on requires display=on"); - goto out_teardown; + goto out_deregister; } if (vdev->display_xres || vdev->display_yres) { if (vdev->dpy == NULL) { error_setg(errp, "xres and yres properties require display=on"); - goto out_teardown; + goto out_deregister; } if (vdev->dpy->edid_regs == NULL) { error_setg(errp, "xres and yres properties need edid support"); - goto out_teardown; + goto out_deregister; } } @@ -3015,8 +3030,10 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) return; -out_teardown: +out_deregister: pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); + kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier); +out_teardown: vfio_teardown_msi(vdev); vfio_bars_exit(vdev); error: @@ -3059,6 +3076,7 @@ static void vfio_exitfn(PCIDevice *pdev) vfio_unregister_req_notifier(vdev); vfio_unregister_err_notifier(vdev); pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); + kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier); vfio_disable_interrupts(vdev); if (vdev->intx.mmap_timer) { timer_free(vdev->intx.mmap_timer); diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index b329d50338..35626cd63e 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -169,6 +169,7 @@ typedef struct VFIOPCIDevice { bool enable_ramfb; VFIODisplay *dpy; Error *migration_blocker; + Notifier irqchip_change_notifier; } VFIOPCIDevice; uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); |