aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-03-24 16:48:17 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:16:49 -0400
commit3eeafd7da2b0293b512abe95c86843fc4ab42add (patch)
treeccbf875d5c4c069156ed2244acca157b475e8c89 /arch/powerpc
parent8a5416db832895b84b85ad0bcbb11d1cce0d3d37 (diff)
KVM: PPC: Ensure split mode works
On PowerPC we can go into MMU Split Mode. That means that either data relocation is on but instruction relocation is off or vice versa. That mode didn't work properly, as we weren't always flushing entries when going into a new split mode, potentially mapping different code or data that we're supposed to. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h9
-rw-r--r--arch/powerpc/kvm/book3s.c46
2 files changed, 29 insertions, 26 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index e6ea974df44e..14d0262ae00b 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -99,10 +99,11 @@ struct kvmppc_vcpu_book3s {
99#define CONTEXT_GUEST 1 99#define CONTEXT_GUEST 1
100#define CONTEXT_GUEST_END 2 100#define CONTEXT_GUEST_END 2
101 101
102#define VSID_REAL 0xfffffffffff00000 102#define VSID_REAL_DR 0x7ffffffffff00000
103#define VSID_REAL_DR 0xffffffffffe00000 103#define VSID_REAL_IR 0x7fffffffffe00000
104#define VSID_REAL_IR 0xffffffffffd00000 104#define VSID_SPLIT_MASK 0x7fffffffffe00000
105#define VSID_BAT 0xffffffffffc00000 105#define VSID_REAL 0x7fffffffffc00000
106#define VSID_BAT 0x7fffffffffb00000
106#define VSID_PR 0x8000000000000000 107#define VSID_PR 0x8000000000000000
107 108
108extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 ea, u64 ea_mask); 109extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 ea, u64 ea_mask);
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 8cab902771a2..ff5a42058257 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -134,6 +134,14 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
134 134
135 if (((vcpu->arch.msr & (MSR_IR|MSR_DR)) != (old_msr & (MSR_IR|MSR_DR))) || 135 if (((vcpu->arch.msr & (MSR_IR|MSR_DR)) != (old_msr & (MSR_IR|MSR_DR))) ||
136 (vcpu->arch.msr & MSR_PR) != (old_msr & MSR_PR)) { 136 (vcpu->arch.msr & MSR_PR) != (old_msr & MSR_PR)) {
137 bool dr = (vcpu->arch.msr & MSR_DR) ? true : false;
138 bool ir = (vcpu->arch.msr & MSR_IR) ? true : false;
139
140 /* Flush split mode PTEs */
141 if (dr != ir)
142 kvmppc_mmu_pte_vflush(vcpu, VSID_SPLIT_MASK,
143 VSID_SPLIT_MASK);
144
137 kvmppc_mmu_flush_segments(vcpu); 145 kvmppc_mmu_flush_segments(vcpu);
138 kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc); 146 kvmppc_mmu_map_segment(vcpu, vcpu->arch.pc);
139 } 147 }
@@ -396,15 +404,7 @@ static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
396 } else { 404 } else {
397 pte->eaddr = eaddr; 405 pte->eaddr = eaddr;
398 pte->raddr = eaddr & 0xffffffff; 406 pte->raddr = eaddr & 0xffffffff;
399 pte->vpage = eaddr >> 12; 407 pte->vpage = VSID_REAL | eaddr >> 12;
400 switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
401 case 0:
402 pte->vpage |= VSID_REAL;
403 case MSR_DR:
404 pte->vpage |= VSID_REAL_DR;
405 case MSR_IR:
406 pte->vpage |= VSID_REAL_IR;
407 }
408 pte->may_read = true; 408 pte->may_read = true;
409 pte->may_write = true; 409 pte->may_write = true;
410 pte->may_execute = true; 410 pte->may_execute = true;
@@ -513,12 +513,10 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
513 int page_found = 0; 513 int page_found = 0;
514 struct kvmppc_pte pte; 514 struct kvmppc_pte pte;
515 bool is_mmio = false; 515 bool is_mmio = false;
516 bool dr = (vcpu->arch.msr & MSR_DR) ? true : false;
517 bool ir = (vcpu->arch.msr & MSR_IR) ? true : false;
516 518
517 if ( vec == BOOK3S_INTERRUPT_DATA_STORAGE ) { 519 relocated = data ? dr : ir;
518 relocated = (vcpu->arch.msr & MSR_DR);
519 } else {
520 relocated = (vcpu->arch.msr & MSR_IR);
521 }
522 520
523 /* Resolve real address if translation turned on */ 521 /* Resolve real address if translation turned on */
524 if (relocated) { 522 if (relocated) {
@@ -530,14 +528,18 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
530 pte.raddr = eaddr & 0xffffffff; 528 pte.raddr = eaddr & 0xffffffff;
531 pte.eaddr = eaddr; 529 pte.eaddr = eaddr;
532 pte.vpage = eaddr >> 12; 530 pte.vpage = eaddr >> 12;
533 switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { 531 }
534 case 0: 532
535 pte.vpage |= VSID_REAL; 533 switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) {
536 case MSR_DR: 534 case 0:
537 pte.vpage |= VSID_REAL_DR; 535 pte.vpage |= VSID_REAL;
538 case MSR_IR: 536 break;
539 pte.vpage |= VSID_REAL_IR; 537 case MSR_DR:
540 } 538 pte.vpage |= VSID_REAL_DR;
539 break;
540 case MSR_IR:
541 pte.vpage |= VSID_REAL_IR;
542 break;
541 } 543 }
542 544
543 if (vcpu->arch.mmu.is_dcbz32(vcpu) && 545 if (vcpu->arch.mmu.is_dcbz32(vcpu) &&