Skip to content

Commit a6681be

Browse files
agrafbwhacks
authored andcommitted
KVM: PPC: Book3S PR: Fix svcpu copying with preemption enabled
commit 07ae538 upstream. When copying between the vcpu and svcpu, we may get scheduled away onto a different host CPU which in turn means our svcpu pointer may change. That means we need to atomically copy to and from the svcpu with preemption disabled, so that all code around it always sees a coherent state. Reported-by: Simon Guo <[email protected]> Fixes: 3d3319b ("KVM: PPC: Book3S: PR: Enable interrupts earlier") Signed-off-by: Alexander Graf <[email protected]> Signed-off-by: Paul Mackerras <[email protected]> Signed-off-by: Ben Hutchings <[email protected]>
1 parent e46406a commit a6681be

File tree

3 files changed

+12
-18
lines changed

3 files changed

+12
-18
lines changed

arch/powerpc/include/asm/kvm_book3s.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,8 @@ extern void kvmppc_hv_entry_trampoline(void);
190190
extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
191191
extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
192192
extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
193-
extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
194-
struct kvm_vcpu *vcpu);
195-
extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
196-
struct kvmppc_book3s_shadow_vcpu *svcpu);
193+
extern void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu);
194+
extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu);
197195

198196
static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
199197
{

arch/powerpc/kvm/book3s_interrupts.S

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ kvm_start_entry:
9696

9797
kvm_start_lightweight:
9898
/* Copy registers into shadow vcpu so we can access them in real mode */
99-
GET_SHADOW_VCPU(r3)
99+
mr r3, r4
100100
bl FUNC(kvmppc_copy_to_svcpu)
101101
nop
102102
REST_GPR(4, r1)
@@ -165,9 +165,7 @@ after_sprg3_load:
165165
stw r12, VCPU_TRAP(r3)
166166

167167
/* Transfer reg values from shadow vcpu back to vcpu struct */
168-
/* On 64-bit, interrupts are still off at this point */
169168

170-
GET_SHADOW_VCPU(r4)
171169
bl FUNC(kvmppc_copy_from_svcpu)
172170
nop
173171

arch/powerpc/kvm/book3s_pr.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
8282
#ifdef CONFIG_PPC_BOOK3S_64
8383
struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
8484
if (svcpu->in_use) {
85-
kvmppc_copy_from_svcpu(vcpu, svcpu);
85+
kvmppc_copy_from_svcpu(vcpu);
8686
}
8787
memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
8888
to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
@@ -95,9 +95,10 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
9595
}
9696

9797
/* Copy data needed by real-mode code from vcpu to shadow vcpu */
98-
void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
99-
struct kvm_vcpu *vcpu)
98+
void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu)
10099
{
100+
struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
101+
101102
svcpu->gpr[0] = vcpu->arch.gpr[0];
102103
svcpu->gpr[1] = vcpu->arch.gpr[1];
103104
svcpu->gpr[2] = vcpu->arch.gpr[2];
@@ -121,17 +122,14 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
121122
svcpu->shadow_fscr = vcpu->arch.shadow_fscr;
122123
#endif
123124
svcpu->in_use = true;
125+
126+
svcpu_put(svcpu);
124127
}
125128

126129
/* Copy data touched by real-mode code from shadow vcpu back to vcpu */
127-
void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
128-
struct kvmppc_book3s_shadow_vcpu *svcpu)
130+
void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu)
129131
{
130-
/*
131-
* vcpu_put would just call us again because in_use hasn't
132-
* been updated yet.
133-
*/
134-
preempt_disable();
132+
struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
135133

136134
/*
137135
* Maybe we were already preempted and synced the svcpu from
@@ -169,7 +167,7 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
169167
svcpu->in_use = false;
170168

171169
out:
172-
preempt_enable();
170+
svcpu_put(svcpu);
173171
}
174172

175173
static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)

0 commit comments

Comments
 (0)