diff --git a/libkvm/libkvm-powerpc.c b/libkvm/libkvm-powerpc.c --- a/libkvm/libkvm-powerpc.c +++ b/libkvm/libkvm-powerpc.c @@ -25,6 +25,7 @@ #include "kvm-powerpc.h" #include #include +#include int handle_dcr(struct kvm_run *run, kvm_context_t kvm) { @@ -110,3 +111,55 @@ int kvm_arch_run(struct kvm_run *run, kv } return ret; } + +int kvm_get_tlb(kvm_context_t kvm, int vcpu, struct kvm_tlb *tlb) +{ + int r = 0; + + r = ioctl(kvm->vcpu_fd[vcpu], KVM_GET_TLB, tlb); + if (r) { + fprintf(stderr,"%s failed (r='%d')\n",__func__,r); + } + + return r; +} + +int kvm_set_tlb(kvm_context_t kvm, int vcpu, struct kvm_tlb *tlb) +{ + int r = 0; + + r = ioctl(kvm->vcpu_fd[vcpu], KVM_SET_TLB, tlb); + if (r) { + fprintf(stderr,"%s - failed (r='%d')\n",__func__,r); + } + + return r; +} + +static void print_tlb(struct tlbe tlb[PPC44x_TLB_SIZE], char* name, char* flag) +{ + int i; + + fprintf(stderr,"%s:\n",name); + fprintf(stderr,"| %2s | %8s | %8s | %8s | %8s |\n","nr"," tid ", + "word0","word1","word2"); + for (i = 0; i < PPC44x_TLB_SIZE; i++) { + if (tlb[i].word0 & PPC44x_TLB_VALID) + fprintf(stderr,"%s%2d | %08X | %08X | %08X | %08X |\n", + flag,i, + tlb[i].tid, + tlb[i].word0, + tlb[i].word1, + tlb[i].word2); + } + fflush(stdout); +} + +void kvm_dump_tlb(kvm_context_t kvm, int vcpu) +{ + struct kvm_tlb tlb; + kvm_get_tlb(kvm, vcpu, &tlb); + + print_tlb(tlb.guest_tlb,"Guest TLB","G"); + print_tlb(tlb.shadow_tlb,"Shadow TLB","S"); +} diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h --- a/libkvm/libkvm.h +++ b/libkvm/libkvm.h @@ -556,4 +556,10 @@ int kvm_enable_vapic(kvm_context_t kvm, #endif +#if defined(__powerpc__) +int kvm_get_tlb(kvm_context_t kvm, int vcpu, struct kvm_tlb *tlb); +int kvm_set_tlb(kvm_context_t kvm, int vcpu, struct kvm_tlb *tlb); +void kvm_dump_tlb(kvm_context_t kvm, int vcpu); #endif + +#endif diff --git a/qemu/hw/ppc440_boards_kvm.c b/qemu/hw/ppc440_boards_kvm.c --- a/qemu/hw/ppc440_boards_kvm.c +++ b/qemu/hw/ppc440_boards_kvm.c @@ -124,7 +124,6 @@ void ppc440_init(CPUState *env, ppc_dcr_register(env, DCRN_CPR0_CFGDATA, cpr0, dcr_read_cpr0, NULL); } - static void bambooKVM_init(ram_addr_t ram_size, int vga_ram_size, const char *boot_device, DisplayState *ds, const char *kernel_filename, @@ -220,7 +219,9 @@ static void bambooKVM_init(ram_addr_t ra } } - /* XXX insert TLB entries */ + /* insert initial TLB entry state */ + kvm_ppc440_tlb_init(env); + /* set up initial stack pointer */ env->gpr[1] = (16<<20) - 8; env->gpr[4] = initrd_base; env->gpr[5] = initrd_size; diff --git a/qemu/qemu-kvm-powerpc.c b/qemu/qemu-kvm-powerpc.c --- a/qemu/qemu-kvm-powerpc.c +++ b/qemu/qemu-kvm-powerpc.c @@ -204,4 +204,27 @@ int handle_powerpc_dcr_write(uint32_t dc return 0; /* XXX ignore failed DCR ops */ } +void kvm_ppc440_tlb_init(CPUState *env) +{ + static struct kvm_tlb tlb; + struct tlbe *gtlbe = &(tlb.guest_tlb[0]); + + /* get/modify/write to preserve the shadow tlb state */ + kvm_get_tlb(kvm_context, env->cpu_index, &tlb); + + gtlbe->tid = 0; + gtlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; + gtlbe->word1 = 0; + gtlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR; + + gtlbe++; + gtlbe->tid = 0; + gtlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID; + gtlbe->word1 = 0xef600000; + gtlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR + | PPC44x_TLB_I | PPC44x_TLB_G; + + kvm_set_tlb(kvm_context, env->cpu_index, &tlb); +} + #endif diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h --- a/qemu/qemu-kvm.h +++ b/qemu/qemu-kvm.h @@ -51,6 +51,7 @@ int handle_tpr_access(void *opaque, int #ifdef TARGET_PPC int handle_powerpc_dcr_read(uint32_t dcrn, uint32_t *data); int handle_powerpc_dcr_write(uint32_t dcrn, uint32_t data); +void kvm_ppc440_tlb_init(CPUState *env); #endif #define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))