aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-11-28 20:29:00 -0500
committerAlexander Graf <agraf@suse.de>2013-12-09 03:41:39 -0500
commit40fdd8c88c4a5e9b26bfbed2215ac661f24aef07 (patch)
tree89cbf59c364f0f310b28a0eb6a398eab1d388835 /arch/powerpc/kvm
parentc9dad7f9db4ed42de37d3f0ef2b2c0e10d5b6f92 (diff)
KVM: PPC: Book3S: PR: Make svcpu -> vcpu store preempt savvy
As soon as we get back to our "highmem" handler in virtual address space we may get preempted. Today the reason we can get preempted is that we replay interrupts and all the lazy logic thinks we have interrupts enabled. However, it's not hard to make the code interruptible and that way we can enable and handle interrupts even earlier. This fixes random guest crashes that happened with CONFIG_PREEMPT=y for me. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s_pr.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index fe14ca3dd171..5b9e9063cfaf 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -66,6 +66,7 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
66 struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); 66 struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
67 memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb)); 67 memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
68 svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max; 68 svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
69 svcpu->in_use = 0;
69 svcpu_put(svcpu); 70 svcpu_put(svcpu);
70#endif 71#endif
71 vcpu->cpu = smp_processor_id(); 72 vcpu->cpu = smp_processor_id();
@@ -78,6 +79,9 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
78{ 79{
79#ifdef CONFIG_PPC_BOOK3S_64 80#ifdef CONFIG_PPC_BOOK3S_64
80 struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); 81 struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
82 if (svcpu->in_use) {
83 kvmppc_copy_from_svcpu(vcpu, svcpu);
84 }
81 memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb)); 85 memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
82 to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max; 86 to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
83 svcpu_put(svcpu); 87 svcpu_put(svcpu);
@@ -110,12 +114,26 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
110 svcpu->ctr = vcpu->arch.ctr; 114 svcpu->ctr = vcpu->arch.ctr;
111 svcpu->lr = vcpu->arch.lr; 115 svcpu->lr = vcpu->arch.lr;
112 svcpu->pc = vcpu->arch.pc; 116 svcpu->pc = vcpu->arch.pc;
117 svcpu->in_use = true;
113} 118}
114 119
115/* Copy data touched by real-mode code from shadow vcpu back to vcpu */ 120/* Copy data touched by real-mode code from shadow vcpu back to vcpu */
116void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, 121void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
117 struct kvmppc_book3s_shadow_vcpu *svcpu) 122 struct kvmppc_book3s_shadow_vcpu *svcpu)
118{ 123{
124 /*
125 * vcpu_put would just call us again because in_use hasn't
126 * been updated yet.
127 */
128 preempt_disable();
129
130 /*
131 * Maybe we were already preempted and synced the svcpu from
132 * our preempt notifiers. Don't bother touching this svcpu then.
133 */
134 if (!svcpu->in_use)
135 goto out;
136
119 vcpu->arch.gpr[0] = svcpu->gpr[0]; 137 vcpu->arch.gpr[0] = svcpu->gpr[0];
120 vcpu->arch.gpr[1] = svcpu->gpr[1]; 138 vcpu->arch.gpr[1] = svcpu->gpr[1];
121 vcpu->arch.gpr[2] = svcpu->gpr[2]; 139 vcpu->arch.gpr[2] = svcpu->gpr[2];
@@ -139,6 +157,10 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
139 vcpu->arch.fault_dar = svcpu->fault_dar; 157 vcpu->arch.fault_dar = svcpu->fault_dar;
140 vcpu->arch.fault_dsisr = svcpu->fault_dsisr; 158 vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
141 vcpu->arch.last_inst = svcpu->last_inst; 159 vcpu->arch.last_inst = svcpu->last_inst;
160 svcpu->in_use = false;
161
162out:
163 preempt_enable();
142} 164}
143 165
144static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu) 166static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)