]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.31/kvm-arm-arm64-reset-the-vcpu-without-preemption-and-.patch
Linux 4.14.108
[thirdparty/kernel/stable-queue.git] / releases / 4.19.31 / kvm-arm-arm64-reset-the-vcpu-without-preemption-and-.patch
1 From da07d7a812dfccf5c67ea59cba430c88e9229bc3 Mon Sep 17 00:00:00 2001
2 From: Christoffer Dall <christoffer.dall@arm.com>
3 Date: Thu, 20 Dec 2018 12:44:05 +0100
4 Subject: KVM: arm/arm64: Reset the VCPU without preemption and vcpu state
5 loaded
6
7 [ Upstream commit e761a927bc9a7ee6ceb7c4f63d5922dbced87f0d ]
8
9 We have two ways to reset a vcpu:
10 - either through VCPU_INIT
11 - or through a PSCI_ON call
12
13 The first one is easy to reason about. The second one is implemented
14 in a more bizarre way, as it is the vcpu that handles PSCI_ON that
15 resets the vcpu that is being powered-on. As we need to turn the logic
16 around and have the target vcpu to reset itself, we must take some
17 preliminary steps.
18
19 Resetting the VCPU state modifies the system register state in memory,
20 but this may interact with vcpu_load/vcpu_put if running with preemption
21 disabled, which in turn may lead to corrupted system register state.
22
23 Address this by disabling preemption and doing put/load if required
24 around the reset logic.
25
26 Reviewed-by: Andrew Jones <drjones@redhat.com>
27 Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
28 Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
29 Signed-off-by: Sasha Levin <sashal@kernel.org>
30 ---
31 arch/arm64/kvm/reset.c | 26 ++++++++++++++++++++++++--
32 1 file changed, 24 insertions(+), 2 deletions(-)
33
34 diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
35 index e37c78bbe1ca..644dd0050766 100644
36 --- a/arch/arm64/kvm/reset.c
37 +++ b/arch/arm64/kvm/reset.c
38 @@ -99,16 +99,33 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
39 * This function finds the right table above and sets the registers on
40 * the virtual CPU struct to their architecturally defined reset
41 * values.
42 + *
43 + * Note: This function can be called from two paths: The KVM_ARM_VCPU_INIT
44 + * ioctl or as part of handling a request issued by another VCPU in the PSCI
45 + * handling code. In the first case, the VCPU will not be loaded, and in the
46 + * second case the VCPU will be loaded. Because this function operates purely
47 + * on the memory-backed valus of system registers, we want to do a full put if
48 + * we were loaded (handling a request) and load the values back at the end of
49 + * the function. Otherwise we leave the state alone. In both cases, we
50 + * disable preemption around the vcpu reset as we would otherwise race with
51 + * preempt notifiers which also call put/load.
52 */
53 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
54 {
55 const struct kvm_regs *cpu_reset;
56 + int ret = -EINVAL;
57 + bool loaded;
58 +
59 + preempt_disable();
60 + loaded = (vcpu->cpu != -1);
61 + if (loaded)
62 + kvm_arch_vcpu_put(vcpu);
63
64 switch (vcpu->arch.target) {
65 default:
66 if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
67 if (!cpu_has_32bit_el1())
68 - return -EINVAL;
69 + goto out;
70 cpu_reset = &default_regs_reset32;
71 } else {
72 cpu_reset = &default_regs_reset;
73 @@ -131,5 +148,10 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
74 vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG;
75
76 /* Reset timer */
77 - return kvm_timer_vcpu_reset(vcpu);
78 + ret = kvm_timer_vcpu_reset(vcpu);
79 +out:
80 + if (loaded)
81 + kvm_arch_vcpu_load(vcpu, smp_processor_id());
82 + preempt_enable();
83 + return ret;
84 }
85 --
86 2.19.1
87