diff options
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r-- | arch/powerpc/kvm/44x_tlb.c | 39 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke_guest.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke_interrupts.S | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/emulate.c | 2 |
4 files changed, 27 insertions, 18 deletions
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 06a5fcfc4d33..3594bbd1f618 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -170,7 +170,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, /* XXX what about AS? */ - stlbe->tid = asid & 0xff; + stlbe->tid = !(asid & 0xff); /* Force TS=1 for all guest mappings. */ /* For now we hardcode 4KB mappings, but it will be important to @@ -190,7 +190,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, gva_t eend, u32 asid) { - unsigned int pid = asid & 0xff; + unsigned int pid = !(asid & 0xff); int i; /* XXX Replace loop with fancy data structures. */ @@ -222,23 +222,30 @@ void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, up_write(¤t->mm->mmap_sem); } -/* Invalidate all mappings, so that when they fault back in they will get the - * proper permission bits. */ +/* Invalidate all mappings on the privilege switch after PID has been changed. + * The guest always runs with PID=1, so we must clear the entire TLB when + * switching address spaces. */ void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) { int i; - /* XXX Replace loop with fancy data structures. */ - down_write(¤t->mm->mmap_sem); - for (i = 0; i <= tlb_44x_hwater; i++) { - struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i]; - - kvmppc_44x_shadow_release(vcpu, i); - stlbe->word0 = 0; - kvmppc_tlbe_set_modified(vcpu, i); - KVMTRACE_5D(STLB_INVAL, vcpu, i, - stlbe->tid, stlbe->word0, stlbe->word1, - stlbe->word2, handler); + if (vcpu->arch.swap_pid) { + /* XXX Replace loop with fancy data structures. */ + down_write(¤t->mm->mmap_sem); + for (i = 0; i <= tlb_44x_hwater; i++) { + struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i]; + + /* Future optimization: clear only userspace mappings. */ + kvmppc_44x_shadow_release(vcpu, i); + stlbe->word0 = 0; + kvmppc_tlbe_set_modified(vcpu, i); + KVMTRACE_5D(STLB_INVAL, vcpu, i, + stlbe->tid, stlbe->word0, stlbe->word1, + stlbe->word2, handler); + } + up_write(¤t->mm->mmap_sem); + vcpu->arch.swap_pid = 0; } - up_write(¤t->mm->mmap_sem); + + vcpu->arch.shadow_pid = !usermode; } diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c index 3cca079975e1..7b2591e26bae 100644 --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -486,6 +486,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) vcpu->arch.msr = 0; vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */ + vcpu->arch.shadow_pid = 1; + /* Eye-catching number so we know if the guest takes an interrupt * before it's programmed its own IVPR. */ vcpu->arch.ivpr = 0x55550000; diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 564ea32ecbac..95e165baf85f 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -332,7 +332,7 @@ lightweight_exit: mfspr r3, SPRN_PID stw r3, VCPU_HOST_PID(r4) - lwz r3, VCPU_PID(r4) + lwz r3, VCPU_SHADOW_PID(r4) mtspr SPRN_PID, r3 /* Prevent all asynchronous TLB updates. */ diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index c3ed63b22210..0fce4fbdc20d 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -508,7 +508,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) case SPRN_MMUCR: vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break; case SPRN_PID: - vcpu->arch.pid = vcpu->arch.gpr[rs]; break; + kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break; case SPRN_CCR0: vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break; case SPRN_CCR1: |