diff options
author | Alexander Graf <agraf@suse.de> | 2010-03-24 21:48:32 +0100 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 12:17:14 +0300 |
commit | 9fb244a2c215d1e16ee92cb164b7b61c8dfa3909 (patch) | |
tree | c214f99be6740fe53d57a652b1b0fce6d7ba5d35 /arch/powerpc/kvm/book3s_64_emulate.c | |
parent | a2b07664f6cd14836ff84a77f48566673dca00bb (diff) |
KVM: PPC: Fix dcbz emulation
On most systems we need to emulate dcbz when running 32 bit guests. So
far we've been rather slack, not giving correct DSISR values to the guest.
This patch makes the emulation more accurate, introducing a difference
between "page not mapped" and "write protection fault". While at it, it
also speeds up dcbz emulation by an order of magnitude by using kmap.
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s_64_emulate.c')
-rw-r--r-- | arch/powerpc/kvm/book3s_64_emulate.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/arch/powerpc/kvm/book3s_64_emulate.c b/arch/powerpc/kvm/book3s_64_emulate.c index 1e5cf8d594e..bbd15906900 100644 --- a/arch/powerpc/kvm/book3s_64_emulate.c +++ b/arch/powerpc/kvm/book3s_64_emulate.c @@ -189,6 +189,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, ulong ra = 0; ulong addr, vaddr; u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + u32 dsisr; + int r; if (get_ra(inst)) ra = kvmppc_get_gpr(vcpu, get_ra(inst)); @@ -198,14 +200,23 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, addr &= 0xffffffff; vaddr = addr; - if (kvmppc_st(vcpu, &addr, 32, zeros, true)) { + r = kvmppc_st(vcpu, &addr, 32, zeros, true); + if ((r == -ENOENT) || (r == -EPERM)) { + *advance = 0; vcpu->arch.dear = vaddr; vcpu->arch.fault_dear = vaddr; - to_book3s(vcpu)->dsisr = DSISR_PROTFAULT | - DSISR_ISSTORE; + + dsisr = DSISR_ISSTORE; + if (r == -ENOENT) + dsisr |= DSISR_NOHPTE; + else if (r == -EPERM) + dsisr |= DSISR_PROTFAULT; + + to_book3s(vcpu)->dsisr = dsisr; + vcpu->arch.fault_dsisr = dsisr; + kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE); - kvmppc_mmu_pte_flush(vcpu, vaddr, ~0xFFFULL); } break; |