Commit 6cead90c authored by Greg Kurz's avatar Greg Kurz Committed by David Gibson
Browse files

xics: Write source state to KVM at claim time



The pseries machine only uses LSIs to support legacy PCI devices. Every
PHB claims 4 LSIs at realize time. When using in-kernel XICS (or upcoming
in-kernel XIVE), QEMU synchronizes the state of all irqs, including these
LSIs, later on at machine reset.

In order to support PHB hotplug, we need a way to tell KVM about the LSIs
that doesn't require a machine reset. An easy way to do that is to always
inform KVM when an interrupt is claimed, which really isn't a performance
path.

Signed-off-by: default avatarGreg Kurz <groug@kaod.org>
Message-Id: <155059668360.1466090.5969630516627776426.stgit@bahia.lab.toulouse-stg.fr.ibm.com>
Reviewed-by: default avatarCédric Le Goater <clg@kaod.org>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 09d876ce
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -758,6 +758,10 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)

    ics->irqs[srcno].flags |=
        lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;

    if (kvm_irqchip_in_kernel()) {
        ics_set_kvm_state_one(ics, srcno);
    }
}

static void xics_register_types(void)
+43 −31
Original line number Diff line number Diff line
@@ -213,14 +213,11 @@ void ics_synchronize_state(ICSState *ics)
    ics_get_kvm_state(ics);
}

int ics_set_kvm_state(ICSState *ics)
int ics_set_kvm_state_one(ICSState *ics, int srcno)
{
    uint64_t state;
    int i;
    Error *local_err = NULL;

    for (i = 0; i < ics->nr_irqs; i++) {
        ICSIRQState *irq = &ics->irqs[i];
    ICSIRQState *irq = &ics->irqs[srcno];
    int ret;

    state = irq->server;
@@ -231,7 +228,7 @@ int ics_set_kvm_state(ICSState *ics)
        state |= KVM_XICS_MASKED;
    }

        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
    if (irq->flags & XICS_FLAGS_IRQ_LSI) {
        state |= KVM_XICS_LEVEL_SENSITIVE;
        if (irq->status & XICS_STATUS_ASSERTED) {
            state |= KVM_XICS_PENDING;
@@ -249,11 +246,26 @@ int ics_set_kvm_state(ICSState *ics)
    }

    ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
                                i + ics->offset, &state, true, &local_err);
                            srcno + ics->offset, &state, true, &local_err);
    if (local_err) {
        error_report_err(local_err);
        return ret;
    }

    return 0;
}

int ics_set_kvm_state(ICSState *ics)
{
    int i;

    for (i = 0; i < ics->nr_irqs; i++) {
        int ret;

        ret = ics_set_kvm_state_one(ics, i);
        if (ret) {
            return ret;
        }
    }

    return 0;
+1 −0
Original line number Diff line number Diff line
@@ -195,6 +195,7 @@ void icp_synchronize_state(ICPState *icp);
void icp_kvm_realize(DeviceState *dev, Error **errp);

void ics_get_kvm_state(ICSState *ics);
int ics_set_kvm_state_one(ICSState *ics, int srcno);
int ics_set_kvm_state(ICSState *ics);
void ics_synchronize_state(ICSState *ics);
void ics_kvm_set_irq(ICSState *ics, int srcno, int val);