diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "44x_tlb.h" @@ -29,6 +30,36 @@ #define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW) static unsigned int kvmppc_tlb_44x_pos; + +void kvmppc_dump_tlb(struct kvm_vcpu *vcpu) +{ + struct tlbe *tlbe; + int i; + + printk("vcpu %d TLB dump:\n", vcpu->vcpu_id); + printk("| %2s | %8s | %8s | %8s | %8s |\n", + "nr", " tid ", "word0", "word1", "word2"); + + for (i = 0; i < PPC44x_TLB_SIZE; i++) + { + tlbe = &vcpu->arch.guest_tlb[i]; + if (tlbe->word0 & PPC44x_TLB_VALID) + printk("G%2d | %08X | %08X | %08X | %08X |\n", + i, tlbe->tid, tlbe->word0, tlbe->word1, tlbe->word2); + } + + msleep(500); + + for (i = 0; i < PPC44x_TLB_SIZE; i++) + { + tlbe = &vcpu->arch.shadow_tlb[i]; + if (tlbe->word0 & PPC44x_TLB_VALID) + printk("S%2d | %08X | %08X | %08X | %08X |\n", + i, tlbe->tid, tlbe->word0, tlbe->word1, tlbe->word2); + } + + msleep(500); +} static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode) { diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h --- a/arch/powerpc/kvm/44x_tlb.h +++ b/arch/powerpc/kvm/44x_tlb.h @@ -27,6 +27,8 @@ extern int kvmppc_44x_tlb_index(struct k unsigned int pid, unsigned int as); extern struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr); extern struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr); + +extern void kvmppc_dump_tlb(struct kvm_vcpu *vcpu); /* TLB helper functions */ static inline unsigned int get_tlb_size(const struct tlbe *tlbe) diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -129,6 +129,7 @@ static int kvmppc_emul_tlbwe(struct kvm_ if (index > PPC44x_TLB_SIZE) { printk("%s: index %d\n", __func__, index); kvmppc_dump_vcpu(vcpu); + kvmppc_dump_tlb(vcpu); return EMULATE_FAIL; } @@ -138,6 +139,14 @@ static int kvmppc_emul_tlbwe(struct kvm_ #endif tlbe = &vcpu->arch.guest_tlb[index]; + + if ((get_tlb_eaddr(tlbe) >> 30) == 0xc) { + printk("evicting %02d: %08x %08x %08x %08x\n", index, + tlbe->tid, tlbe->word0, tlbe->word1, tlbe->word2); + kvmppc_dump_vcpu(vcpu); + WARN_ON(1); + } + /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */ if (tlbe->word0 & PPC44x_TLB_VALID) { @@ -250,6 +259,8 @@ int kvmppc_emulate_instruction(struct kv switch (get_op(inst)) { case 3: /* trap */ printk("trap!\n"); + kvmppc_dump_vcpu(vcpu); + kvmppc_dump_tlb(vcpu); kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); advance = 0; break; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -218,6 +218,7 @@ int kvmppc_handle_exit(struct kvm_run *r case BOOKE_INTERRUPT_MACHINE_CHECK: printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR)); kvmppc_dump_vcpu(vcpu); + kvmppc_dump_tlb(vcpu); r = RESUME_HOST; break; @@ -310,6 +311,12 @@ int kvmppc_handle_exit(struct kvm_run *r gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); if (!gtlbe) { /* The guest didn't have a mapping for it. */ + if ((eaddr >> 30) == 0xc) { + printk("Guest mapping f0r 0xc not found!\n"); + kvmppc_dump_vcpu(vcpu); + kvmppc_dump_tlb(vcpu); + } + kvmppc_queue_exception(vcpu, exit_nr); vcpu->arch.dear = vcpu->arch.fault_dear; vcpu->arch.esr = vcpu->arch.fault_esr; @@ -354,6 +361,12 @@ int kvmppc_handle_exit(struct kvm_run *r gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); if (!gtlbe) { /* The guest didn't have a mapping for it. */ + if ((eaddr >> 30) == 0xc) { + printk("Guest mapping f0r 0xc not found!\n"); + kvmppc_dump_vcpu(vcpu); + kvmppc_dump_tlb(vcpu); + } + kvmppc_queue_exception(vcpu, exit_nr); r = RESUME_GUEST; break;