xics_kvm: cache already enabled vCPU ids
Since commita45863bda9
("xics_kvm: Don't enable KVM_CAP_IRQ_XICS if already enabled"), we were able to re-hotplug a vCPU that had been hot- unplugged ealier, thanks to a boolean flag in ICPState that we set when enabling KVM_CAP_IRQ_XICS. This could work because the lifecycle of all ICPState objects was the same as the machine. Commit5bc8d26de2
("spapr: allocate the ICPState object from under sPAPRCPUCore") broke this assumption and now we always pass a freshly allocated ICPState object (ie, with the flag unset) to icp_kvm_cpu_setup(). This cause re-hotplug to fail with: Unable to connect CPU8 to kernel XICS: Device or resource busy Let's fix this by caching all the vCPU ids for which KVM_CAP_IRQ_XICS was enabled. This also drops the now useless boolean flag from ICPState. Reported-by: Laurent Vivier <lvivier@redhat.com> Signed-off-by: Greg Kurz <groug@kaod.org> Tested-by: Laurent Vivier <lvivier@redhat.com> Reviewed-by: Laurent Vivier <lvivier@redhat.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
06ec79e865
commit
de86eccc0c
@ -42,6 +42,14 @@
|
|||||||
|
|
||||||
static int kernel_xics_fd = -1;
|
static int kernel_xics_fd = -1;
|
||||||
|
|
||||||
|
typedef struct KVMEnabledICP {
|
||||||
|
unsigned long vcpu_id;
|
||||||
|
QLIST_ENTRY(KVMEnabledICP) node;
|
||||||
|
} KVMEnabledICP;
|
||||||
|
|
||||||
|
static QLIST_HEAD(, KVMEnabledICP)
|
||||||
|
kvm_enabled_icps = QLIST_HEAD_INITIALIZER(&kvm_enabled_icps);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ICP-KVM
|
* ICP-KVM
|
||||||
*/
|
*/
|
||||||
@ -121,6 +129,8 @@ static void icp_kvm_reset(void *dev)
|
|||||||
static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu)
|
static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
|
KVMEnabledICP *enabled_icp;
|
||||||
|
unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (kernel_xics_fd == -1) {
|
if (kernel_xics_fd == -1) {
|
||||||
@ -132,18 +142,21 @@ static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu)
|
|||||||
* which was hot-removed earlier we don't have to renable
|
* which was hot-removed earlier we don't have to renable
|
||||||
* KVM_CAP_IRQ_XICS capability again.
|
* KVM_CAP_IRQ_XICS capability again.
|
||||||
*/
|
*/
|
||||||
if (icp->cap_irq_xics_enabled) {
|
QLIST_FOREACH(enabled_icp, &kvm_enabled_icps, node) {
|
||||||
return;
|
if (enabled_icp->vcpu_id == vcpu_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd,
|
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd, vcpu_id);
|
||||||
kvm_arch_vcpu_id(cs));
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
error_report("Unable to connect CPU%ld to kernel XICS: %s", vcpu_id,
|
||||||
kvm_arch_vcpu_id(cs), strerror(errno));
|
strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
icp->cap_irq_xics_enabled = true;
|
enabled_icp = g_malloc(sizeof(*enabled_icp));
|
||||||
|
enabled_icp->vcpu_id = vcpu_id;
|
||||||
|
QLIST_INSERT_HEAD(&kvm_enabled_icps, enabled_icp, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void icp_kvm_realize(DeviceState *dev, Error **errp)
|
static void icp_kvm_realize(DeviceState *dev, Error **errp)
|
||||||
|
@ -81,7 +81,6 @@ struct ICPState {
|
|||||||
uint8_t pending_priority;
|
uint8_t pending_priority;
|
||||||
uint8_t mfrr;
|
uint8_t mfrr;
|
||||||
qemu_irq output;
|
qemu_irq output;
|
||||||
bool cap_irq_xics_enabled;
|
|
||||||
|
|
||||||
XICSFabric *xics;
|
XICSFabric *xics;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user