[PATCH 1/3] kvmppc: Some refactor for merging e500

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Liu Yu <yu.liu@xxxxxxxxxxxxx>

---
 arch/powerpc/include/asm/kvm_44x.h  |    9 +++++
 arch/powerpc/include/asm/kvm_host.h |    7 ----
 arch/powerpc/include/asm/kvm_ppc.h  |    5 +--
 arch/powerpc/kvm/44x.c              |   22 +++++++++++++-
 arch/powerpc/kvm/44x_tlb.c          |   29 +++++------------
 arch/powerpc/kvm/44x_tlb.h          |   19 +++++++++--
 arch/powerpc/kvm/booke.c            |   49 +++++++++----------------------
 arch/powerpc/kvm/booke.h            |    8 +++++
 arch/powerpc/kvm/booke_interrupts.S |   56 ++++------------------------------
 arch/powerpc/kvm/booke_interrupts.h |   54 +++++++++++++++++++++++++++++++++
 10 files changed, 139 insertions(+), 119 deletions(-)
 create mode 100644 arch/powerpc/kvm/booke_interrupts.h

diff --git a/arch/powerpc/include/asm/kvm_44x.h b/arch/powerpc/include/asm/kvm_44x.h
index 72e5939..afb24cc 100644
--- a/arch/powerpc/include/asm/kvm_44x.h
+++ b/arch/powerpc/include/asm/kvm_44x.h
@@ -25,6 +25,15 @@
 /* XXX Can't include mmu-44x.h because it redefines struct mm_context. */
 #define PPC44x_TLB_SIZE 64
 
+#define BOOKE_INTERRUPT_SIZE 16
+
+struct kvmppc_44x_tlbe {
+	u32 tid; /* Only the low 8 bits are used. */
+	u32 word0;
+	u32 word1;
+	u32 word2;
+};
+
 struct kvmppc_vcpu_44x {
 	/* Unmodified copy of the guest's TLB. */
 	struct kvmppc_44x_tlbe guest_tlb[PPC44x_TLB_SIZE];
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index a4a7d5e..2b1a31a 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -64,13 +64,6 @@ struct kvm_vcpu_stat {
 	u32 halt_wakeup;
 };
 
-struct kvmppc_44x_tlbe {
-	u32 tid; /* Only the low 8 bits are used. */
-	u32 word0;
-	u32 word1;
-	u32 word2;
-};
-
 struct kvm_arch {
 };
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 408a0ca..40cc0bf 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -52,13 +52,12 @@ extern int kvmppc_emulate_instruction(struct kvm_run *run,
 extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
 extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 
-extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
-                           u64 asid, u32 flags);
 extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
 extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid);
 
 /* Core-specific hooks */
 
+extern void kvmppc_core_mmu_map(struct kvm_vcpu *, u64, gfn_t, int);
 extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm,
                                                 unsigned int id);
 extern void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu);
@@ -86,7 +85,7 @@ extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs);
 extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt);
 
 
-extern int kvmppc_booke_init(void);
+extern int kvmppc_booke_init(unsigned long *, int);
 extern void kvmppc_booke_exit(void);
 
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 22054b1..6d72c9d 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -216,9 +216,29 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
 
 static int kvmppc_44x_init(void)
 {
+	unsigned long ivor[BOOKE_INTERRUPT_SIZE];
 	int r;
 
-	r = kvmppc_booke_init();
+	/* Copy our interrupt handlers to match host IVORs. That way we don't
+	 * have to swap the IVORs on every guest/host transition. */
+	ivor[0] = mfspr(SPRN_IVOR0);
+	ivor[1] = mfspr(SPRN_IVOR1);
+	ivor[2] = mfspr(SPRN_IVOR2);
+	ivor[3] = mfspr(SPRN_IVOR3);
+	ivor[4] = mfspr(SPRN_IVOR4);
+	ivor[5] = mfspr(SPRN_IVOR5);
+	ivor[6] = mfspr(SPRN_IVOR6);
+	ivor[7] = mfspr(SPRN_IVOR7);
+	ivor[8] = mfspr(SPRN_IVOR8);
+	ivor[9] = mfspr(SPRN_IVOR9);
+	ivor[10] = mfspr(SPRN_IVOR10);
+	ivor[11] = mfspr(SPRN_IVOR11);
+	ivor[12] = mfspr(SPRN_IVOR12);
+	ivor[13] = mfspr(SPRN_IVOR13);
+	ivor[14] = mfspr(SPRN_IVOR14);
+	ivor[15] = mfspr(SPRN_IVOR15);
+
+	r = kvmppc_booke_init(ivor, sizeof(ivor)/sizeof(ivor[0]));
 	if (r)
 		return r;
 
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 0f4296c..17daa56 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -118,30 +118,20 @@ int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
 	return -1;
 }
 
-struct kvmppc_44x_tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu,
-                                               gva_t eaddr)
+int kvmppc_core_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
 {
 	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
 	unsigned int as = !!(vcpu->arch.msr & MSR_IS);
-	unsigned int index;
 
-	index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
-	if (index == -1)
-		return NULL;
-	return &vcpu_44x->guest_tlb[index];
+	return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
 }
 
-struct kvmppc_44x_tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu,
-                                               gva_t eaddr)
+int kvmppc_core_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
 {
 	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
 	unsigned int as = !!(vcpu->arch.msr & MSR_DS);
-	unsigned int index;
 
-	index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
-	if (index == -1)
-		return NULL;
-	return &vcpu_44x->guest_tlb[index];
+	return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
 }
 
 static int kvmppc_44x_tlbe_is_writable(struct kvmppc_44x_tlbe *tlbe)
@@ -173,14 +163,16 @@ void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i)
 
 /* Caller must ensure that the specified guest TLB entry is safe to insert into
  * the shadow TLB. */
-void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
-                    u32 flags)
+void kvmppc_core_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr,
+		gfn_t gfn, int index)
 {
 	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
 	struct page *new_page;
 	struct kvmppc_44x_tlbe *stlbe;
 	hpa_t hpaddr;
 	unsigned int victim;
+	u32 asid = &vcpu_44x->guest_tlb[index].tid;
+	u32 flags = &vcpu_44x->guest_tlb[index].word2;
 
 	/* Future optimization: don't overwrite the TLB entry containing the
 	 * current PC (or stack?). */
@@ -317,7 +309,6 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
 	u64 eaddr;
 	u64 raddr;
 	u64 asid;
-	u32 flags;
 	struct kvmppc_44x_tlbe *tlbe;
 	unsigned int index;
 
@@ -358,13 +349,11 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
 	if (tlbe_is_host_safe(vcpu, tlbe)) {
 		eaddr = get_tlb_eaddr(tlbe);
 		raddr = get_tlb_raddr(tlbe);
-		asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
-		flags = tlbe->word2 & 0xffff;
 
 		/* Create a 4KB mapping on the host. If the guest wanted a
 		 * large page, only the first 4KB is mapped here and the rest
 		 * are mapped on the fly. */
-		kvmppc_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, asid, flags);
+		kvmppc_core_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, index);
 	}
 
 	KVMTRACE_5D(GTLB_WRITE, vcpu, index,
diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h
index b1029af..60ce44b 100644
--- a/arch/powerpc/kvm/44x_tlb.h
+++ b/arch/powerpc/kvm/44x_tlb.h
@@ -22,19 +22,21 @@
 
 #include <linux/kvm_host.h>
 #include <asm/mmu-44x.h>
+#include <asm/kvm_44x.h>
 
+extern int kvmppc_core_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
+extern int kvmppc_core_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
 extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr,
                                 unsigned int pid, unsigned int as);
-extern struct kvmppc_44x_tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu,
-                                                      gva_t eaddr);
-extern struct kvmppc_44x_tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu,
-                                                      gva_t eaddr);
 extern void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i);
 
 extern int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb,
                                  u8 rc);
 extern int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws);
 
+#define kvmppc_core_deliver_itlb_miss(vcpu)
+#define kvmppc_core_deliver_dtlb_miss(vcpu)
+
 /* TLB helper functions */
 static inline unsigned int get_tlb_size(const struct kvmppc_44x_tlbe *tlbe)
 {
@@ -95,4 +97,13 @@ static inline gpa_t tlb_xlate(struct kvmppc_44x_tlbe *tlbe, gva_t eaddr)
 	return get_tlb_raddr(tlbe) | (eaddr & pgmask);
 }
 
+static inline gpa_t index_xlate(const struct kvm_vcpu *vcpu,
+		int index, gva_t eaddr)
+{
+	struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+	struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[index];
+
+	return tlb_xlate(gtlbe, eaddr);
+}
+
 #endif /* __KVM_POWERPC_TLB_H__ */
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ec59a67..d96f793 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -30,7 +30,6 @@
 #include <asm/cacheflush.h>
 
 #include "booke.h"
-#include "44x_tlb.h"
 
 unsigned long kvmppc_booke_handlers;
 
@@ -282,15 +281,16 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		break;
 
 	case BOOKE_INTERRUPT_DTLB_MISS: {
-		struct kvmppc_44x_tlbe *gtlbe;
+		int index;
 		unsigned long eaddr = vcpu->arch.fault_dear;
 		gfn_t gfn;
 
 		/* Check the guest TLB. */
-		gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
-		if (!gtlbe) {
+		index = kvmppc_core_dtlb_search(vcpu, eaddr);
+		if (index < 0) {
 			/* The guest didn't have a mapping for it. */
 			kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
+			kvmppc_core_deliver_dtlb_miss(vcpu);
 			vcpu->arch.dear = vcpu->arch.fault_dear;
 			vcpu->arch.esr = vcpu->arch.fault_esr;
 			vcpu->stat.dtlb_real_miss_exits++;
@@ -298,7 +298,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			break;
 		}
 
-		vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr);
+		vcpu->arch.paddr_accessed = index_xlate(vcpu, index, eaddr);
 		gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT;
 
 		if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
@@ -308,8 +308,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			 * b) the guest used a large mapping which we're faking
 			 * Either way, we need to satisfy the fault without
 			 * invoking the guest. */
-			kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
-			               gtlbe->word2);
+			kvmppc_core_mmu_map(vcpu, eaddr, gfn, index);
 			vcpu->stat.dtlb_virt_miss_exits++;
 			r = RESUME_GUEST;
 		} else {
@@ -323,24 +322,25 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	}
 
 	case BOOKE_INTERRUPT_ITLB_MISS: {
-		struct kvmppc_44x_tlbe *gtlbe;
+		int index;
 		unsigned long eaddr = vcpu->arch.pc;
 		gfn_t gfn;
 
 		r = RESUME_GUEST;
 
 		/* Check the guest TLB. */
-		gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
-		if (!gtlbe) {
+		index = kvmppc_core_itlb_search(vcpu, eaddr);
+		if (index < 0) {
 			/* The guest didn't have a mapping for it. */
 			kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
+			kvmppc_core_deliver_itlb_miss(vcpu);
 			vcpu->stat.itlb_real_miss_exits++;
 			break;
 		}
 
 		vcpu->stat.itlb_virt_miss_exits++;
 
-		gfn = tlb_xlate(gtlbe, eaddr) >> PAGE_SHIFT;
+		gfn = index_xlate(vcpu, index, eaddr) >> PAGE_SHIFT;
 
 		if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
 			/* The guest TLB had a mapping, but the shadow TLB
@@ -349,8 +349,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			 * b) the guest used a large mapping which we're faking
 			 * Either way, we need to satisfy the fault without
 			 * invoking the guest. */
-			kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
-			               gtlbe->word2);
+			kvmppc_core_mmu_map(vcpu, eaddr, gfn, index);
 		} else {
 			/* Guest mapped and leaped at non-RAM! */
 			kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK);
@@ -494,9 +493,8 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
 	return kvmppc_core_vcpu_translate(vcpu, tr);
 }
 
-int kvmppc_booke_init(void)
+int kvmppc_booke_init(unsigned long ivor[], int size)
 {
-	unsigned long ivor[16];
 	unsigned long max_ivor = 0;
 	int i;
 
@@ -509,26 +507,7 @@ int kvmppc_booke_init(void)
 
 	/* XXX make sure our handlers are smaller than Linux's */
 
-	/* Copy our interrupt handlers to match host IVORs. That way we don't
-	 * have to swap the IVORs on every guest/host transition. */
-	ivor[0] = mfspr(SPRN_IVOR0);
-	ivor[1] = mfspr(SPRN_IVOR1);
-	ivor[2] = mfspr(SPRN_IVOR2);
-	ivor[3] = mfspr(SPRN_IVOR3);
-	ivor[4] = mfspr(SPRN_IVOR4);
-	ivor[5] = mfspr(SPRN_IVOR5);
-	ivor[6] = mfspr(SPRN_IVOR6);
-	ivor[7] = mfspr(SPRN_IVOR7);
-	ivor[8] = mfspr(SPRN_IVOR8);
-	ivor[9] = mfspr(SPRN_IVOR9);
-	ivor[10] = mfspr(SPRN_IVOR10);
-	ivor[11] = mfspr(SPRN_IVOR11);
-	ivor[12] = mfspr(SPRN_IVOR12);
-	ivor[13] = mfspr(SPRN_IVOR13);
-	ivor[14] = mfspr(SPRN_IVOR14);
-	ivor[15] = mfspr(SPRN_IVOR15);
-
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < size; i++) {
 		if (ivor[i] > max_ivor)
 			max_ivor = ivor[i];
 
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index 48d905f..6e58bbe 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -54,4 +54,12 @@ static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
 		kvm_vcpu_block(vcpu);
 }
 
+#if defined(CONFIG_44x)
+# include "44x_tlb.h"
+#elif defined(CONFIG_FSL_BOOKE)
+# include "e500_tlb.h"
+#else
+# error "unsupported platform"
+#endif
+
 #endif /* __KVM_BOOKE_H__ */
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 8d6929b..f33aa86 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -20,10 +20,11 @@
 #include <asm/ppc_asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
-#include <asm/mmu-44x.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 
+#include "booke_interrupts.h"
+
 #define KVMPPC_MSR_MASK (MSR_CE|MSR_EE|MSR_PR|MSR_DE|MSR_ME|MSR_IS|MSR_DS)
 
 #define VCPU_GPR(n)     (VCPU_GPRS + (n * 4))
@@ -174,8 +175,8 @@ _GLOBAL(kvmppc_resume_host)
 	/* Restore host stack pointer and PID before IVPR, since the host
 	 * exception handlers use them. */
 	lwz	r1, VCPU_HOST_STACK(r4)
-	lwz	r3, VCPU_HOST_PID(r4)
-	mtspr	SPRN_PID, r3
+
+	LOAD_PID(VCPU_HOST_PID)
 
 	/* Restore host IVPR before re-enabling interrupts. We cheat and know
 	 * that Linux IVPR is always 0xc0000000. */
@@ -330,10 +331,8 @@ _GLOBAL(__kvmppc_vcpu_run)
 lightweight_exit:
 	stw	r2, HOST_R2(r1)
 
-	mfspr	r3, SPRN_PID
-	stw	r3, VCPU_HOST_PID(r4)
-	lwz	r3, VCPU_SHADOW_PID(r4)
-	mtspr	SPRN_PID, r3
+	SAVE_PID(VCPU_HOST_PID)
+	LOAD_PID(VCPU_SHADOW_PID)
 
 	/* Prevent all asynchronous TLB updates. */
 	mfmsr	r5
@@ -342,48 +341,7 @@ lightweight_exit:
 	andc	r6, r5, r6
 	mtmsr	r6
 
-	/* Load the guest mappings, leaving the host's "pinned" kernel mappings
-	 * in place. */
-	mfspr	r10, SPRN_MMUCR			/* Save host MMUCR. */
-	li	r5, PPC44x_TLB_SIZE
-	lis	r5, tlb_44x_hwater@ha
-	lwz	r5, tlb_44x_hwater@l(r5)
-	mtctr	r5
-	addi	r9, r4, -VCPU_TO_44X + VCPU44x_SHADOW_TLB
-	addi	r5, r4, -VCPU_TO_44X + VCPU44x_SHADOW_MOD
-	li	r3, 0
-1:
-	lbzx	r7, r3, r5
-	cmpwi	r7, 0
-	beq	3f
-
-	/* Load guest entry. */
-	mulli	r11, r3, TLBE_BYTES
-	add	r11, r11, r9
-	lwz	r7, 0(r11)
-	mtspr	SPRN_MMUCR, r7
-	lwz	r7, 4(r11)
-	tlbwe	r7, r3, PPC44x_TLB_PAGEID
-	lwz	r7, 8(r11)
-	tlbwe	r7, r3, PPC44x_TLB_XLAT
-	lwz	r7, 12(r11)
-	tlbwe	r7, r3, PPC44x_TLB_ATTRIB
-3:
-	addi	r3, r3, 1                       /* Increment index. */
-	bdnz	1b
-
-	mtspr	SPRN_MMUCR, r10			/* Restore host MMUCR. */
-
-	/* Clear bitmap of modified TLB entries */
-	li	r5, PPC44x_TLB_SIZE>>2
-	mtctr	r5
-	addi	r5, r4, -VCPU_TO_44X + VCPU44x_SHADOW_MOD - 4
-	li	r6, 0
-1:
-	stwu	r6, 4(r5)
-	bdnz	1b
-
-	iccci	0, 0 /* XXX hack */
+	LOAD_GUEST_TLB
 
 	/* Load some guest volatiles. */
 	lwz	r0, VCPU_GPR(r0)(r4)
diff --git a/arch/powerpc/kvm/booke_interrupts.h b/arch/powerpc/kvm/booke_interrupts.h
new file mode 100644
index 0000000..bbd10fd
--- /dev/null
+++ b/arch/powerpc/kvm/booke_interrupts.h
@@ -0,0 +1,54 @@
+#ifndef __KVMPPC_BOOKE_INTERRUPT_H__
+#define __KVMPPC_BOOKE_INTERRUPT_H__
+
+#ifdef CONFIG_44x
+#include <asm/mmu-44x.h>
+
+#define LOAD_PID(addr)			\
+	lwz     r3, addr(r4);		\
+	mtspr   SPRN_PID, r3;
+
+#define SAVE_PID(addr)			\
+	mfspr   r3, SPRN_PID;		\
+	stw     r3, addr(r4);
+
+	/* Load the guest mappings, leaving the host's "pinned" kernel mappings
+	 * in place. */
+#define LOAD_GUEST_TLB							\
+	mfspr	r10, SPRN_MMUCR			/* Save host MMUCR. */	\
+	li	r5, PPC44x_TLB_SIZE					\
+	lis	r5, tlb_44x_hwater@ha					\
+	lwz	r5, tlb_44x_hwater@l(r5)				\
+	mtctr	r5							\
+	addi	r9, r4, -VCPU_TO_44X + VCPU44x_SHADOW_TLB		\
+	addi	r5, r4, -VCPU_TO_44X + VCPU44x_SHADOW_MOD		\
+	li	r3, 0							\
+1:	lbzx	r7, r3, r5						\
+	cmpwi	r7, 0							\
+	beq	3f							\
+	/* Load guest entry. */						\
+	mulli	r11, r3, TLBE_BYTES					\
+	add	r11, r11, r9						\
+	lwz	r7, 0(r11)						\
+	mtspr	SPRN_MMUCR, r7						\
+	lwz	r7, 4(r11)						\
+	tlbwe	r7, r3, PPC44x_TLB_PAGEID				\
+	lwz	r7, 8(r11)						\
+	tlbwe	r7, r3, PPC44x_TLB_XLAT					\
+	lwz	r7, 12(r11)						\
+	tlbwe	r7, r3, PPC44x_TLB_ATTRIB				\
+3:	addi	r3, r3, 1                       /* Increment index. */	\
+	bdnz	1b							\
+	mtspr	SPRN_MMUCR, r10			/* Restore host MMUCR. */\
+	/* Clear bitmap of modified TLB entries */			\
+	li	r5, PPC44x_TLB_SIZE>>2					\
+	mtctr	r5							\
+	addi	r5, r4, -VCPU_TO_44X + VCPU44x_SHADOW_MOD - 4		\
+	li	r6, 0							\
+1:	stwu	r6, 4(r5)						\
+	bdnz	1b							\
+	iccci	0, 0 /* XXX hack */
+
+#endif
+
+#endif /* __KVMPPC_BOOKE_INTERRUPT_H__ */
-- 
1.5.4

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux