summaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm/psci.c
diff options
context:
space:
mode:
authorChristoffer Dall <christoffer.dall@linaro.org>2013-11-20 02:43:19 +0100
committerChristoffer Dall <christoffer.dall@linaro.org>2013-12-21 18:55:17 +0100
commit478a8237f656d86d25b3e4e4bf3c48f590156294 (patch)
treea75bc587c1589389525727f3035f74cbab9c4ea3 /arch/arm/kvm/psci.c
parentKVM: Documentation: Fix typo for KVM_ARM_VCPU_INIT ioctl (diff)
downloadlinux-478a8237f656d86d25b3e4e4bf3c48f590156294.tar.xz
linux-478a8237f656d86d25b3e4e4bf3c48f590156294.zip
arm: KVM: Don't return PSCI_INVAL if waitqueue is inactive
The current KVM implementation of PSCI returns INVALID_PARAMETERS if the waitqueue for the corresponding CPU is not active. This does not seem correct, since KVM should not care what the specific thread is doing, for example, user space may not have called KVM_RUN on this VCPU yet or the thread may be busy looping to user space because it received a signal; this is really up to the user space implementation. Instead we should check specifically that the CPU is marked as being turned off, regardless of the VCPU thread state, and if it is, we shall simply clear the pause flag on the CPU and wake up the thread if it happens to be blocked for us. Further, the implementation seems to be racy when executing multiple VCPU threads. There really isn't a reasonable user space programming scheme to ensure all secondary CPUs have reached kvm_vcpu_first_run_init before turning on the boot CPU. Therefore, set the pause flag on the vcpu at VCPU init time (which can reasonably be expected to be completed for all CPUs by user space before running any VCPUs) and clear both this flag and the feature (in case the feature can somehow get set again in the future) and ping the waitqueue on turning on a VCPU using PSCI. Reported-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'arch/arm/kvm/psci.c')
-rw-r--r--arch/arm/kvm/psci.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 0881bf169fbc..448f60e8d23c 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -54,15 +54,15 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
}
}
- if (!vcpu)
+ /*
+ * Make sure the caller requested a valid CPU and that the CPU is
+ * turned off.
+ */
+ if (!vcpu || !vcpu->arch.pause)
return KVM_PSCI_RET_INVAL;
target_pc = *vcpu_reg(source_vcpu, 2);
- wq = kvm_arch_vcpu_wq(vcpu);
- if (!waitqueue_active(wq))
- return KVM_PSCI_RET_INVAL;
-
kvm_reset_vcpu(vcpu);
/* Gracefully handle Thumb2 entry point */
@@ -79,6 +79,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
vcpu->arch.pause = false;
smp_mb(); /* Make sure the above is visible */
+ wq = kvm_arch_vcpu_wq(vcpu);
wake_up_interruptible(wq);
return KVM_PSCI_RET_SUCCESS;