[PATCH 4/4] add e500 support for kvm

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

 



Any chance we could merge struct kvm_vcpu_arch for both 44x and e500?

Signed-off-by: Liu Yu <yu.liu@xxxxxxxxxxxxx>
---
 arch/powerpc/include/asm/kvm_asm.h  |    7 ++-
 arch/powerpc/include/asm/kvm_host.h |  112 +++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/asm-offsets.c   |    9 +++
 arch/powerpc/kvm/44x_tlb.h          |    4 +
 arch/powerpc/kvm/Kconfig            |    4 +-
 arch/powerpc/kvm/Makefile           |    7 ++
 arch/powerpc/kvm/booke_guest.c      |   14 ++++-
 arch/powerpc/kvm/booke_host.c       |   20 ++++--
 arch/powerpc/kvm/emulate.c          |   88 +++++++++++++++++++++++++++-
 arch/powerpc/kvm/powerpc.c          |    4 +
 arch/powerpc/kvm/powerpc.h          |    4 +
 11 files changed, 261 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index 2197764..7bf8b9a 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -42,7 +42,12 @@
 #define BOOKE_INTERRUPT_DTLB_MISS 13
 #define BOOKE_INTERRUPT_ITLB_MISS 14
 #define BOOKE_INTERRUPT_DEBUG 15
-#define BOOKE_MAX_INTERRUPT 15
+#define BOOKE_INTERRUPT_SPE_UNAVAIL 32
+#define BOOKE_INTERRUPT_SPE_FP_DATA 33
+#define BOOKE_INTERRUPT_SPE_FP_ROUND 34
+#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
+#define BOOKE_MAX_INTERRUPT 35
+#define BOOKE_INTERRUPT_NUM (BOOKE_MAX_INTERRUPT + 1)
 
 #define RESUME_FLAG_NV          (1<<0)  /* Reload guest nonvolatile state? */
 #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 34b52b7..d1b420b 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -64,6 +64,7 @@ struct kvm_vcpu_stat {
 	u32 halt_wakeup;
 };
 
+#ifdef CONFIG_44x
 struct tlbe {
 	u32 tid; /* Only the low 8 bits are used. */
 	u32 word0;
@@ -155,6 +156,117 @@ struct kvm_vcpu_arch {
 	struct timer_list dec_timer;
 	unsigned long pending_exceptions;
 };
+#endif /* CONFIG_44x */
+
+#ifdef CONFIG_E500
+struct kvm_arch {
+};
+
+struct tlb_array{
+	void *base;
+	int size;
+};
+
+#define E500_PID_NUM	3
+#define E500_TLB_NUM	2
+
+struct kvm_vcpu_arch {
+	/* Unmodified copy of the guest's TLB. */
+	struct tlb_array guest_tlb[E500_TLB_NUM];
+	/* TLB that's actually used when the guest is running. */
+	struct tlb_array shadow_tlb[E500_TLB_NUM];
+	/* Pages which are referenced in the shadow TLB. */
+	struct page **shadow_pages[E500_TLB_NUM];
+
+	/* Track which TLB entries we've modified in the current exit. */
+	u8 *shadow_tlb_mod;
+
+	u32 host_stack;
+	u32 host_pid[E500_PID_NUM];
+	u32 host_dbcr0;
+	u32 host_dbcr1;
+	u32 host_dbcr2;
+	u32 host_iac[4];
+	u32 host_msr;
+
+	u64 fpr[32];
+	u32 gpr[32];
+
+	u32 pc;
+	u32 cr;
+	u32 ctr;
+	u32 lr;
+	u32 xer;
+
+	u32 msr;
+	u32 mmucr;
+	u32 sprg0;
+	u32 sprg1;
+	u32 sprg2;
+	u32 sprg3;
+	u32 sprg4;
+	u32 sprg5;
+	u32 sprg6;
+	u32 sprg7;
+	u32 srr0;
+	u32 srr1;
+	u32 csrr0;
+	u32 csrr1;
+	u32 dsrr0;
+	u32 dsrr1;
+	u32 dear;
+	u32 esr;
+	u32 dec;
+	u32 decar;
+	u32 tbl;
+	u32 tbu;
+	u32 tcr;
+	u32 tsr;
+	u32 ivor[BOOKE_INTERRUPT_NUM];
+	u32 ivpr;
+	u32 pir;
+
+	u32 shadow_pid;
+	u32 swap_pid;
+
+	u32 pid_array[0];
+	u32 pid;
+	u32 pid1;
+	u32 pid2;
+
+	u32 pvr;
+	u32 ccr0;
+	u32 ccr1;
+	u32 dbcr0;
+	u32 dbcr1;
+
+	u32 mas0;
+	u32 mas1;
+	u32 mas2;
+	u32 mas3;
+	u32 mas4;
+	u32 mas5;
+	u32 mas6;
+	u32 mas7;
+	u32 l1csr1;
+	u32 dbsr;
+
+	u32 last_inst;
+	u32 fault_dear;
+	u32 fault_esr;
+	gpa_t paddr_accessed;
+
+	u8 io_gpr; /* GPR used as IO source/target */
+	u8 mmio_is_bigendian;
+	u8 dcr_needed;
+	u8 dcr_is_write;
+
+	u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */
+
+	struct timer_list dec_timer;
+	unsigned long pending_exceptions;
+};
+#endif /* CONFIG_E500 */
 
 struct kvm_guest_debug {
 	int enabled;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 52649da..3385fb6 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -352,12 +352,15 @@ int main(void)
 	DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
 
 #ifdef CONFIG_KVM
+# ifdef CONFIG_44x
 	DEFINE(TLBE_BYTES, sizeof(struct tlbe));
+# endif
 
 	DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
 	DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
 	DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb));
 	DEFINE(VCPU_SHADOW_MOD, offsetof(struct kvm_vcpu, arch.shadow_tlb_mod));
+	DEFINE(SIZEOF_TLB_ARRAY, sizeof(struct tlb_array));
 	DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
 	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
 	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
@@ -370,6 +373,12 @@ int main(void)
 	DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
 	DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
 	DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
+	DEFINE(VCPU_PID, offsetof(struct kvm_vcpu, arch.pid));
+	DEFINE(VCPU_MAS0, offsetof(struct kvm_vcpu, arch.mas0));
+	DEFINE(VCPU_MAS1, offsetof(struct kvm_vcpu, arch.mas1));
+	DEFINE(VCPU_MAS2, offsetof(struct kvm_vcpu, arch.mas2));
+	DEFINE(VCPU_MAS3, offsetof(struct kvm_vcpu, arch.mas3));
+	DEFINE(VCPU_MAS7, offsetof(struct kvm_vcpu, arch.mas7));
 
 	DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
 	DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h
index 7eeffe7..673d7d5 100644
--- a/arch/powerpc/kvm/44x_tlb.h
+++ b/arch/powerpc/kvm/44x_tlb.h
@@ -23,6 +23,10 @@
 #include <linux/kvm_host.h>
 #include <asm/mmu-44x.h>
 
+#define kvmppc_emul_tlbre(vcpu, val)	EMULATE_DONE
+#define kvmppc_emul_tlbivax(vcpu, val)	EMULATE_DONE
+#define kvmppc_tlb_init(vcpu)
+
 extern void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu);
 extern struct tlbe *kvmppc_tlb_search(struct kvm_vcpu *vcpu, gva_t eaddr,
                                 unsigned int pid, unsigned int as);
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 53aaa66..c812866 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -16,7 +16,7 @@ if VIRTUALIZATION
 
 config KVM
 	bool "Kernel-based Virtual Machine (KVM) support"
-	depends on 44x && EXPERIMENTAL
+	depends on (44x || E500) && EXPERIMENTAL
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
 	# We can only run on Book E hosts so far
@@ -32,7 +32,7 @@ config KVM
 
 config KVM_BOOKE_HOST
 	bool "KVM host support for Book E PowerPC processors"
-	depends on KVM && 44x
+	depends on KVM && (44x || E500)
 	---help---
 	  Provides host support for KVM on Book E PowerPC processors. Currently
 	  this works on 440 processors only.
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 2a5d439..55a5bc3 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -13,5 +13,12 @@ obj-$(CONFIG_KVM) += kvm.o
 
 AFLAGS_booke_interrupts.o := -I$(obj)
 
+ifeq ($(CONFIG_44x),y)
 kvm-booke-host-objs := booke_host.o booke_interrupts.o 44x_tlb.o
+endif
+
+ifeq ($(CONFIG_E500),y)
+kvm-booke-host-objs := booke_host.o booke_fsl_interrupts.o e500_tlb.o
+endif
+
 obj-$(CONFIG_KVM_BOOKE_HOST) += kvm-booke-host.o
diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c
index 4fca3be..830163a 100644
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke_guest.c
@@ -53,7 +53,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ NULL }
 };
 
-static const u32 interrupt_msr_mask[16] = {
+static const u32 interrupt_msr_mask[] = {
 	[BOOKE_INTERRUPT_CRITICAL]      = MSR_ME,
 	[BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
 	[BOOKE_INTERRUPT_DATA_STORAGE]  = MSR_CE|MSR_ME|MSR_DE,
@@ -70,6 +70,9 @@ static const u32 interrupt_msr_mask[16] = {
 	[BOOKE_INTERRUPT_DTLB_MISS]     = MSR_CE|MSR_ME|MSR_DE,
 	[BOOKE_INTERRUPT_ITLB_MISS]     = MSR_CE|MSR_ME|MSR_DE,
 	[BOOKE_INTERRUPT_DEBUG]         = MSR_ME,
+	[BOOKE_INTERRUPT_SPE_UNAVAIL]	= MSR_CE|MSR_ME|MSR_DE,
+	[BOOKE_INTERRUPT_SPE_FP_DATA]	= MSR_CE|MSR_ME|MSR_DE,
+	[BOOKE_INTERRUPT_SPE_FP_ROUND]	= MSR_CE|MSR_ME|MSR_DE
 };
 
 const unsigned char exception_priority[] = {
@@ -89,6 +92,9 @@ const unsigned char exception_priority[] = {
 	[BOOKE_INTERRUPT_EXTERNAL] = 13,
 	[BOOKE_INTERRUPT_FIT] = 14,
 	[BOOKE_INTERRUPT_DECREMENTER] = 15,
+	[BOOKE_INTERRUPT_SPE_UNAVAIL] = 16,
+	[BOOKE_INTERRUPT_SPE_FP_DATA] = 17,
+	[BOOKE_INTERRUPT_SPE_FP_ROUND] = 18
 };
 
 const unsigned char priority_exception[] = {
@@ -108,6 +114,9 @@ const unsigned char priority_exception[] = {
 	BOOKE_INTERRUPT_EXTERNAL,
 	BOOKE_INTERRUPT_FIT,
 	BOOKE_INTERRUPT_DECREMENTER,
+	BOOKE_INTERRUPT_SPE_UNAVAIL,
+	BOOKE_INTERRUPT_SPE_FP_DATA,
+	BOOKE_INTERRUPT_SPE_FP_ROUND
 };
 
 /* TODO: use vcpu_printf() */
@@ -280,6 +289,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		break;
 
 	case BOOKE_INTERRUPT_FP_UNAVAIL:
+	case BOOKE_INTERRUPT_SPE_UNAVAIL:
+	case BOOKE_INTERRUPT_SPE_FP_DATA:
+	case BOOKE_INTERRUPT_SPE_FP_ROUND:
 		kvmppc_queue_exception(vcpu, exit_nr);
 		r = RESUME_GUEST;
 		break;
diff --git a/arch/powerpc/kvm/booke_host.c b/arch/powerpc/kvm/booke_host.c
index b480341..c8edb98 100644
--- a/arch/powerpc/kvm/booke_host.c
+++ b/arch/powerpc/kvm/booke_host.c
@@ -27,9 +27,9 @@ unsigned long kvmppc_booke_handlers;
 
 static int kvmppc_booke_init(void)
 {
-	unsigned long ivor[16];
+	unsigned long ivor[BOOKE_INTERRUPT_NUM];
 	unsigned long max_ivor = 0;
-	int i;
+	int i, valid_ivor;
 
 	/* We install our own exception handlers by hijacking IVPR. IVPR must
 	 * be 16-bit aligned, so we need a 64KB allocation. */
@@ -42,6 +42,7 @@ static int kvmppc_booke_init(void)
 
 	/* Copy our interrupt handlers to match host IVORs. That way we don't
 	 * have to swap the IVORs on every guest/host transition. */
+	memset(ivor, 0, sizeof(ivor));
 	ivor[0] = mfspr(SPRN_IVOR0);
 	ivor[1] = mfspr(SPRN_IVOR1);
 	ivor[2] = mfspr(SPRN_IVOR2);
@@ -58,14 +59,21 @@ static int kvmppc_booke_init(void)
 	ivor[13] = mfspr(SPRN_IVOR13);
 	ivor[14] = mfspr(SPRN_IVOR14);
 	ivor[15] = mfspr(SPRN_IVOR15);
+	ivor[32] = mfspr(SPRN_IVOR32);
+	ivor[33] = mfspr(SPRN_IVOR33);
+	ivor[34] = mfspr(SPRN_IVOR34);
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0, valid_ivor = 0; i < BOOKE_INTERRUPT_NUM; i++) {
 		if (ivor[i] > max_ivor)
 			max_ivor = ivor[i];
 
-		memcpy((void *)kvmppc_booke_handlers + ivor[i],
-		       kvmppc_handlers_start + i * kvmppc_handler_len,
-		       kvmppc_handler_len);
+		if (ivor[i]) {
+			memcpy((void *)kvmppc_booke_handlers + ivor[i],
+				kvmppc_handlers_start +
+				valid_ivor * kvmppc_handler_len,
+				kvmppc_handler_len);
+			valid_ivor++;
+		}
 	}
 	flush_icache_range(kvmppc_booke_handlers,
 	                   kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 5d31fca..2243c1a 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -232,6 +232,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
 			case SPRN_PID:
 				vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
+			case SPRN_PID1:
+				vcpu->arch.gpr[rt] = vcpu->arch.pid1; break;
+			case SPRN_PID2:
+				vcpu->arch.gpr[rt] = vcpu->arch.pid2; break;
 			case SPRN_IVPR:
 				vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
 			case SPRN_CCR0:
@@ -248,6 +252,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
 			case SPRN_DBCR1:
 				vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
+			case SPRN_DBSR:
+				vcpu->arch.gpr[rt] = vcpu->arch.dbsr; break;
 
 			/* Note: mftb and TBRL/TBWL are user-accessible, so
 			 * the guest can always access the real TB anyways.
@@ -300,6 +306,45 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
 			case SPRN_IVOR15:
 				vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
+			case SPRN_IVOR32:
+				vcpu->arch.gpr[rt] = vcpu->arch.ivor[32]; break;
+			case SPRN_IVOR33:
+				vcpu->arch.gpr[rt] = vcpu->arch.ivor[33]; break;
+			case SPRN_IVOR34:
+				vcpu->arch.gpr[rt] = vcpu->arch.ivor[34]; break;
+			case SPRN_IVOR35:
+				vcpu->arch.gpr[rt] = vcpu->arch.ivor[35]; break;
+#ifdef CONFIG_E500
+			/* E500 MMU */
+			case SPRN_MAS0:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas0; break;
+			case SPRN_MAS1:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas1; break;
+			case SPRN_MAS2:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas2; break;
+			case SPRN_MAS3:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas3; break;
+			case SPRN_MAS4:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas4; break;
+			case SPRN_MAS6:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas6; break;
+			case SPRN_MAS7:
+				vcpu->arch.gpr[rt] = vcpu->arch.mas7; break;
+			case SPRN_TLB0CFG:
+				vcpu->arch.gpr[rt] = mfspr(SPRN_TLB0CFG);
+				vcpu->arch.gpr[rt] &= ~0xfffUL;
+				vcpu->arch.gpr[rt] |= vcpu->arch.guest_tlb[1].size;
+				break;
+
+			case SPRN_TLB1CFG:
+				vcpu->arch.gpr[rt] = mfspr(SPRN_TLB1CFG);
+				vcpu->arch.gpr[rt] &= ~0xfffUL;
+				vcpu->arch.gpr[rt] |= vcpu->arch.guest_tlb[1].size;
+				break;
+
+			case SPRN_L1CSR1:
+				vcpu->arch.gpr[rt] = vcpu->arch.l1csr1; break;
+#endif /* CONFIG_E500 */
 
 			default:
 				printk("mfspr: unknown spr %x\n", sprn);
@@ -310,8 +355,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 
 		case 407:                                       /* sthx */
 			rs = get_rs(inst);
-			ra = get_ra(inst);
-			rb = get_rb(inst);
 
 			emulated = kvmppc_handle_store(run, vcpu,
 			                               vcpu->arch.gpr[rs],
@@ -364,6 +407,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
 			case SPRN_PID:
 				kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break;
+			case SPRN_PID1:
+				vcpu->arch.pid1 = vcpu->arch.gpr[rs]; break;
+			case SPRN_PID2:
+				vcpu->arch.pid2 = vcpu->arch.gpr[rs]; break;
 			case SPRN_CCR0:
 				vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
 			case SPRN_CCR1:
@@ -376,6 +423,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
 			case SPRN_DBCR1:
 				vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
+			case SPRN_DBSR:
+				vcpu->arch.dbsr = vcpu->arch.gpr[rs]; break;
 
 			/* XXX We need to context-switch the timebase for
 			 * watchdog and FIT. */
@@ -450,6 +499,33 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 				vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
 			case SPRN_IVOR15:
 				vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
+			case SPRN_IVOR32:
+				vcpu->arch.ivor[32] = vcpu->arch.gpr[rs]; break;
+			case SPRN_IVOR33:
+				vcpu->arch.ivor[33] = vcpu->arch.gpr[rs]; break;
+			case SPRN_IVOR34:
+				vcpu->arch.ivor[34] = vcpu->arch.gpr[rs]; break;
+			case SPRN_IVOR35:
+				vcpu->arch.ivor[35] = vcpu->arch.gpr[rs]; break;
+#ifdef CONFIG_E500
+			/* E500 MMU */
+			case SPRN_MAS0:
+				vcpu->arch.mas0 = vcpu->arch.gpr[rs]; break;
+			case SPRN_MAS1:
+				vcpu->arch.mas1 = vcpu->arch.gpr[rs]; break;
+			case SPRN_MAS2:
+				vcpu->arch.mas2 = vcpu->arch.gpr[rs]; break;
+			case SPRN_MAS3:
+				vcpu->arch.mas3 = vcpu->arch.gpr[rs]; break;
+			case SPRN_MAS4:
+				vcpu->arch.mas4 = vcpu->arch.gpr[rs]; break;
+			case SPRN_MAS6:
+				vcpu->arch.mas6 = vcpu->arch.gpr[rs]; break;
+			case SPRN_MAS7:
+				vcpu->arch.mas7 = vcpu->arch.gpr[rs]; break;
+			case SPRN_L1CSR1:
+				vcpu->arch.l1csr1 = vcpu->arch.gpr[rs]; break;
+#endif /* CONFIG_E500 */
 
 			default:
 				printk("mtspr: unknown spr %x\n", sprn);
@@ -484,6 +560,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 			                               4, 0);
 			break;
 
+		case 786:					/* tlbivax */
+			emulated = kvmppc_emul_tlbivax(vcpu, inst);
+			break;
+
 		case 978:                                       /* tlbwe */
 			emulated = kvmppc_emul_tlbwe(vcpu, inst);
 			break;
@@ -492,6 +572,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 			emulated = kvmppc_emul_tlbsx(vcpu, inst);
 			break;
 
+		case 946:					/* tlbre */
+			emulated = kvmppc_emul_tlbre(vcpu, inst);
+			break;
+
 		case 790:                                       /* lhbrx */
 			rt = get_rt(inst);
 			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index d3bc29f..493ac93 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -29,6 +29,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
 
+#include "powerpc.h"
 
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
 {
@@ -102,6 +103,8 @@ void kvm_arch_check_processor_compat(void *rtn)
 
 	if (strcmp(cur_cpu_spec->platform, "ppc440") == 0)
 		r = 0;
+	else if (strcmp(cur_cpu_spec->cpu_name, "e500v2") == 0)
+		r = 0;
 	else
 		r = -ENOTSUPP;
 
@@ -230,6 +233,7 @@ static void kvmppc_decrementer_func(unsigned long data)
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+	kvmppc_tlb_init(vcpu);
 	setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func,
 	            (unsigned long)vcpu);
 
diff --git a/arch/powerpc/kvm/powerpc.h b/arch/powerpc/kvm/powerpc.h
index dd93461..3a7ac82 100644
--- a/arch/powerpc/kvm/powerpc.h
+++ b/arch/powerpc/kvm/powerpc.h
@@ -7,4 +7,8 @@
 #include "44x_tlb.h"
 #endif
 
+#ifdef CONFIG_E500
+#include "e500_tlb.h"
+#endif
+
 #endif /* __KVM_POWERPC_POWERPC_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