mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.2-20191126' into staging
ppc patch queue for 2019-11-26
Here's the first 4.2 hard freeze pull request from me. This has:
* A fix for some testcases that cause errors on older host kernels
(e.g. RHEL7), with our new default configuration of VSMT mode
* Changes to make VFIO devices interact properly with change of irq
chip caused by PAPR feature negotiation. This is more involved
than I would like, but it's a problem in real use cases and I
can't see an easier way to handle it.
* Fix an error with ms6522 counters for the g3beige machine
* Fix a coverity warning
# gpg: Signature made Tue 26 Nov 2019 05:52:16 GMT
# gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full]
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full]
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full]
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown]
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-4.2-20191126:
ppc/spapr_events: fix potential NULL pointer dereference in rtas_event_log_dequeue
mos6522: update counters when timer interrupts are off
spapr: Work around spurious warnings from vfio INTx initialization
spapr: Handle irq backend changes with VFIO PCI devices
vfio/pci: Respond to KVM irqchip change notifier
vfio/pci: Split vfio_intx_update()
kvm: Introduce KVM irqchip change notifier
pseries: fix migration-test and pxe-test
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -149,6 +149,9 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
KVM_CAP_LAST_INFO
|
||||
};
|
||||
|
||||
static NotifierList kvm_irqchip_change_notifiers =
|
||||
NOTIFIER_LIST_INITIALIZER(kvm_irqchip_change_notifiers);
|
||||
|
||||
#define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock)
|
||||
#define kvm_slots_unlock(kml) qemu_mutex_unlock(&(kml)->slots_lock)
|
||||
|
||||
@@ -1396,6 +1399,21 @@ void kvm_irqchip_release_virq(KVMState *s, int virq)
|
||||
trace_kvm_irqchip_release_virq(virq);
|
||||
}
|
||||
|
||||
void kvm_irqchip_add_change_notifier(Notifier *n)
|
||||
{
|
||||
notifier_list_add(&kvm_irqchip_change_notifiers, n);
|
||||
}
|
||||
|
||||
void kvm_irqchip_remove_change_notifier(Notifier *n)
|
||||
{
|
||||
notifier_remove(n);
|
||||
}
|
||||
|
||||
void kvm_irqchip_change_notify(void)
|
||||
{
|
||||
notifier_list_notify(&kvm_irqchip_change_notifiers, NULL);
|
||||
}
|
||||
|
||||
static unsigned int kvm_hash_msi(uint32_t data)
|
||||
{
|
||||
/* This is optimized for IA32 MSI layout. However, no other arch shall
|
||||
|
||||
@@ -138,6 +138,18 @@ void kvm_irqchip_commit_routes(KVMState *s)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_irqchip_add_change_notifier(Notifier *n)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_irqchip_remove_change_notifier(Notifier *n)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_irqchip_change_notify(void)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
|
||||
{
|
||||
return -ENOSYS;
|
||||
|
||||
+6
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+16
-1
@@ -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);
|
||||
|
||||
+41
-23
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -201,6 +201,7 @@ typedef struct KVMCapabilityInfo {
|
||||
struct KVMState;
|
||||
typedef struct KVMState KVMState;
|
||||
extern KVMState *kvm_state;
|
||||
typedef struct Notifier Notifier;
|
||||
|
||||
/* external API */
|
||||
|
||||
@@ -401,6 +402,10 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
|
||||
|
||||
void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin);
|
||||
|
||||
void kvm_irqchip_add_change_notifier(Notifier *n);
|
||||
void kvm_irqchip_remove_change_notifier(Notifier *n);
|
||||
void kvm_irqchip_change_notify(void);
|
||||
|
||||
void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
|
||||
|
||||
struct kvm_guest_debug;
|
||||
|
||||
@@ -614,7 +614,7 @@ static int test_migrate_start(QTestState **from, QTestState **to,
|
||||
end_address = S390_TEST_MEM_END;
|
||||
} else if (strcmp(arch, "ppc64") == 0) {
|
||||
extra_opts = use_shmem ? get_shmem_opts("256M", shmem_path) : NULL;
|
||||
cmd_src = g_strdup_printf("-machine accel=%s -m 256M -nodefaults"
|
||||
cmd_src = g_strdup_printf("-machine accel=%s,vsmt=8 -m 256M -nodefaults"
|
||||
" -name source,debug-threads=on"
|
||||
" -serial file:%s/src_serial"
|
||||
" -prom-env 'use-nvramrc?=true' -prom-env "
|
||||
@@ -623,7 +623,7 @@ static int test_migrate_start(QTestState **from, QTestState **to,
|
||||
"until' %s %s", accel, tmpfs, end_address,
|
||||
start_address, extra_opts ? extra_opts : "",
|
||||
opts_src);
|
||||
cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
|
||||
cmd_dst = g_strdup_printf("-machine accel=%s,vsmt=8 -m 256M"
|
||||
" -name target,debug-threads=on"
|
||||
" -serial file:%s/dest_serial"
|
||||
" -incoming %s %s %s",
|
||||
|
||||
+3
-3
@@ -46,15 +46,15 @@ static testdef_t x86_tests_slow[] = {
|
||||
|
||||
static testdef_t ppc64_tests[] = {
|
||||
{ "pseries", "spapr-vlan",
|
||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken" },
|
||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,vsmt=8" },
|
||||
{ "pseries", "virtio-net-pci",
|
||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken" },
|
||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,vsmt=8" },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static testdef_t ppc64_tests_slow[] = {
|
||||
{ "pseries", "e1000",
|
||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken" },
|
||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,vsmt=8" },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user