# HG changeset patch
# User Hollis Blanchard [EMAIL PROTECTED]
# Date 1221162418 18000
# Node ID 0f01a4354a6aac06b3fe7062e6d4ee538286c405
# Parent 34089016b7ff30a697fc67753353e893e7351daa
kvm: ppc: Move 440-specific TLB code into 44x_tlb.c
This will make it easier to provide implementations for other cores.
Signed-off-by: Hollis Blanchard [EMAIL PROTECTED]
---
4 files changed, 145 insertions(+), 143 deletions(-)
arch/powerpc/include/asm/kvm_ppc.h |4 -
arch/powerpc/kvm/44x_tlb.c | 138 +++-
arch/powerpc/kvm/booke_guest.c | 26 --
arch/powerpc/kvm/emulate.c | 120 +--
diff --git a/arch/powerpc/include/asm/kvm_ppc.h
b/arch/powerpc/include/asm/kvm_ppc.h
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -58,11 +58,11 @@ extern int kvmppc_emulate_instruction(st
extern int kvmppc_emulate_instruction(struct kvm_run *run,
struct kvm_vcpu *vcpu);
extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
+extern int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws);
+extern int kvmppc_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, u8
rc);
extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
u64 asid, u32 flags);
-extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
- gva_t eend, u32 asid);
extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid);
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
@@ -31,6 +31,34 @@
#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
static unsigned int kvmppc_tlb_44x_pos;
+
+#ifdef DEBUG
+void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_44x_tlbe *tlbe;
+ int i;
+
+ printk(vcpu %d TLB dump:\n, vcpu-vcpu_id);
+ printk(| %2s | %3s | %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 | %02X | %08X | %08X | %08X |\n,
+ i, tlbe-tid, tlbe-word0, tlbe-word1,
+ tlbe-word2);
+ }
+
+ for (i = 0; i PPC44x_TLB_SIZE; i++) {
+ tlbe = vcpu-arch.shadow_tlb[i];
+ if (tlbe-word0 PPC44x_TLB_VALID)
+ printk( S%2d | %02X | %08X | %08X | %08X |\n,
+ i, tlbe-tid, tlbe-word0, tlbe-word1,
+ tlbe-word2);
+ }
+}
+#endif
static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
{
@@ -185,8 +213,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcp
handler);
}
-void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
- gva_t eend, u32 asid)
+static void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
+ gva_t eend, u32 asid)
{
unsigned int pid = !(asid 0xff);
int i;
@@ -243,3 +271,109 @@ void kvmppc_mmu_priv_switch(struct kvm_v
vcpu-arch.shadow_pid = !usermode;
}
+
+static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
+ const struct tlbe *tlbe)
+{
+ gpa_t gpa;
+
+ if (!get_tlb_v(tlbe))
+ return 0;
+
+ /* Does it match current guest AS? */
+ /* XXX what about IS != DS? */
+ if (get_tlb_ts(tlbe) != !!(vcpu-arch.msr MSR_IS))
+ return 0;
+
+ gpa = get_tlb_raddr(tlbe);
+ if (!gfn_to_memslot(vcpu-kvm, gpa PAGE_SHIFT))
+ /* Mapping is not for RAM. */
+ return 0;
+
+ return 1;
+}
+
+int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
+{
+ u64 eaddr;
+ u64 raddr;
+ u64 asid;
+ u32 flags;
+ struct tlbe *tlbe;
+ unsigned int index;
+
+ index = vcpu-arch.gpr[ra];
+ if (index PPC44x_TLB_SIZE) {
+ printk(%s: index %d\n, __func__, index);
+ kvmppc_dump_vcpu(vcpu);
+ return EMULATE_FAIL;
+ }
+
+ tlbe = vcpu-arch.guest_tlb[index];
+
+ /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
+ if (tlbe-word0 PPC44x_TLB_VALID) {
+ eaddr = get_tlb_eaddr(tlbe);
+ asid = (tlbe-word0 PPC44x_TLB_TS) | tlbe-tid;
+ kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid);
+ }
+
+ switch (ws) {
+ case PPC44x_TLB_PAGEID:
+ tlbe-tid = vcpu-arch.mmucr 0xff;
+ tlbe-word0 = vcpu-arch.gpr[rs];
+ break;
+