mirror of https://gitee.com/openkylin/qemu.git
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: Greg Kurz <groug@kaod.org> Message-Id: <155059668360.1466090.5969630516627776426.stgit@bahia.lab.toulouse-stg.fr.ibm.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
09d876ce2c
commit
6cead90c5c
|
@ -758,6 +758,10 @@ void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
|
||||||
|
|
||||||
ics->irqs[srcno].flags |=
|
ics->irqs[srcno].flags |=
|
||||||
lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
|
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)
|
static void xics_register_types(void)
|
||||||
|
|
|
@ -213,14 +213,11 @@ void ics_synchronize_state(ICSState *ics)
|
||||||
ics_get_kvm_state(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;
|
uint64_t state;
|
||||||
int i;
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
ICSIRQState *irq = &ics->irqs[srcno];
|
||||||
for (i = 0; i < ics->nr_irqs; i++) {
|
|
||||||
ICSIRQState *irq = &ics->irqs[i];
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
state = irq->server;
|
state = irq->server;
|
||||||
|
@ -231,7 +228,7 @@ int ics_set_kvm_state(ICSState *ics)
|
||||||
state |= KVM_XICS_MASKED;
|
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;
|
state |= KVM_XICS_LEVEL_SENSITIVE;
|
||||||
if (irq->status & XICS_STATUS_ASSERTED) {
|
if (irq->status & XICS_STATUS_ASSERTED) {
|
||||||
state |= KVM_XICS_PENDING;
|
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,
|
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) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
return ret;
|
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;
|
return 0;
|
||||||
|
|
|
@ -195,6 +195,7 @@ void icp_synchronize_state(ICPState *icp);
|
||||||
void icp_kvm_realize(DeviceState *dev, Error **errp);
|
void icp_kvm_realize(DeviceState *dev, Error **errp);
|
||||||
|
|
||||||
void ics_get_kvm_state(ICSState *ics);
|
void ics_get_kvm_state(ICSState *ics);
|
||||||
|
int ics_set_kvm_state_one(ICSState *ics, int srcno);
|
||||||
int ics_set_kvm_state(ICSState *ics);
|
int ics_set_kvm_state(ICSState *ics);
|
||||||
void ics_synchronize_state(ICSState *ics);
|
void ics_synchronize_state(ICSState *ics);
|
||||||
void ics_kvm_set_irq(ICSState *ics, int srcno, int val);
|
void ics_kvm_set_irq(ICSState *ics, int srcno, int val);
|
||||||
|
|
Loading…
Reference in New Issue