aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/44x_emulate.c9
-rw-r--r--arch/powerpc/kvm/44x_tlb.c31
2 files changed, 18 insertions, 22 deletions
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
index 9bc50cebf9ec..9ef79c78ede9 100644
--- a/arch/powerpc/kvm/44x_emulate.c
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -21,6 +21,7 @@
21#include <asm/dcr.h> 21#include <asm/dcr.h>
22#include <asm/dcr-regs.h> 22#include <asm/dcr-regs.h>
23#include <asm/disassemble.h> 23#include <asm/disassemble.h>
24#include <asm/kvm_44x.h>
24 25
25#include "booke.h" 26#include "booke.h"
26#include "44x_tlb.h" 27#include "44x_tlb.h"
@@ -38,14 +39,6 @@
38#define XOP_ICCCI 966 39#define XOP_ICCCI 966
39#define XOP_TLBWE 978 40#define XOP_TLBWE 978
40 41
41static inline void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
42{
43 if (vcpu->arch.pid != new_pid) {
44 vcpu->arch.pid = new_pid;
45 vcpu->arch.swap_pid = 1;
46 }
47}
48
49static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) 42static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
50{ 43{
51 vcpu->arch.pc = vcpu->arch.srr0; 44 vcpu->arch.pc = vcpu->arch.srr0;
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 6fadbd696021..ee2461860bcf 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -268,31 +268,34 @@ static void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
268 } 268 }
269} 269}
270 270
271/* Invalidate all mappings on the privilege switch after PID has been changed.
272 * The guest always runs with PID=1, so we must clear the entire TLB when
273 * switching address spaces. */
274void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) 271void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
275{ 272{
273 vcpu->arch.shadow_pid = !usermode;
274}
275
276void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
277{
276 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 278 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
277 int i; 279 int i;
278 280
279 if (vcpu->arch.swap_pid) { 281 if (unlikely(vcpu->arch.pid == new_pid))
280 /* XXX Replace loop with fancy data structures. */ 282 return;
281 for (i = 0; i <= tlb_44x_hwater; i++) { 283
282 struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i]; 284 vcpu->arch.pid = new_pid;
285
286 /* Guest userspace runs with TID=0 mappings and PID=0, to make sure it
287 * can't access guest kernel mappings (TID=1). When we switch to a new
288 * guest PID, which will also use host PID=0, we must discard the old guest
289 * userspace mappings. */
290 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_tlb); i++) {
291 struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
283 292
284 /* Future optimization: clear only userspace mappings. */ 293 if (get_tlb_tid(stlbe) == 0) {
285 kvmppc_44x_shadow_release(vcpu, i); 294 kvmppc_44x_shadow_release(vcpu, i);
286 stlbe->word0 = 0; 295 stlbe->word0 = 0;
287 kvmppc_tlbe_set_modified(vcpu, i); 296 kvmppc_tlbe_set_modified(vcpu, i);
288 KVMTRACE_5D(STLB_INVAL, vcpu, i,
289 stlbe->tid, stlbe->word0, stlbe->word1,
290 stlbe->word2, handler);
291 } 297 }
292 vcpu->arch.swap_pid = 0;
293 } 298 }
294
295 vcpu->arch.shadow_pid = !usermode;
296} 299}
297 300
298static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, 301static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,