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;
|
||||
|
||||
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
|
||||
*/
|
||||
@ -121,6 +129,8 @@ static void icp_kvm_reset(void *dev)
|
||||
static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
KVMEnabledICP *enabled_icp;
|
||||
unsigned long vcpu_id = kvm_arch_vcpu_id(cs);
|
||||
int ret;
|
||||
|
||||
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
|
||||
* KVM_CAP_IRQ_XICS capability again.
|
||||
*/
|
||||
if (icp->cap_irq_xics_enabled) {
|
||||
return;
|
||||
QLIST_FOREACH(enabled_icp, &kvm_enabled_icps, node) {
|
||||
if (enabled_icp->vcpu_id == vcpu_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd,
|
||||
kvm_arch_vcpu_id(cs));
|
||||
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd, vcpu_id);
|
||||
if (ret < 0) {
|
||||
error_report("Unable to connect CPU%ld to kernel XICS: %s",
|
||||
kvm_arch_vcpu_id(cs), strerror(errno));
|
||||
error_report("Unable to connect CPU%ld to kernel XICS: %s", vcpu_id,
|
||||
strerror(errno));
|
||||
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)
|
||||
|
@ -81,7 +81,6 @@ struct ICPState {
|
||||
uint8_t pending_priority;
|
||||
uint8_t mfrr;
|
||||
qemu_irq output;
|
||||
bool cap_irq_xics_enabled;
|
||||
|
||||
XICSFabric *xics;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user