Signed-off-by: Liu Yu <[EMAIL PROTECTED]>
---
 arch/powerpc/kvm/e500_emulate.c |  359 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 359 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/kvm/e500_emulate.c

diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
new file mode 100644
index 0000000..defe1d9
--- /dev/null
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Yu Liu, <[EMAIL PROTECTED]>
+ *
+ * Description:
+ * This file is derived from arch/powerpc/kvm/44x_emulate.c,
+ * by Hollis Blanchard <[EMAIL PROTECTED]>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/kvm_ppc.h>
+#include <asm/disassemble.h>
+#include <asm/kvm_e500.h>
+
+#include "booke.h"
+#include "e500_tlb.h"
+
+#define OP_RFI      19
+
+#define XOP_RFI                50
+#define XOP_MFMSR      83
+#define XOP_WRTEE      131
+#define XOP_MTMSR      146
+#define XOP_WRTEEI     163
+#define XOP_TLBIVAX    786
+#define XOP_TLBSX      914
+#define XOP_TLBRE      946
+#define XOP_TLBWE      978
+
+static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.pc = vcpu->arch.srr0;
+       kvmppc_set_msr(vcpu, vcpu->arch.srr1);
+}
+
+int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
+                           unsigned int inst, int *advance)
+{
+       int emulated = EMULATE_DONE;
+       int ra;
+       int rb;
+       int rs;
+       int rt;
+
+       switch (get_op(inst)) {
+
+       case OP_RFI:
+               switch (get_xop(inst)) {
+               case XOP_RFI:
+                       kvmppc_emul_rfi(vcpu);
+                       *advance = 0;
+                       break;
+
+               default:
+                       emulated = EMULATE_FAIL;
+                       break;
+               }
+               break;
+
+       case 31:
+               switch (get_xop(inst)) {
+
+               case XOP_MFMSR:
+                       rt = get_rt(inst);
+                       vcpu->arch.gpr[rt] = vcpu->arch.msr;
+                       break;
+
+               case XOP_MTMSR:
+                       rs = get_rs(inst);
+                       kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
+                       break;
+
+               case XOP_WRTEE:
+                       rs = get_rs(inst);
+                       vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+                               | (vcpu->arch.gpr[rs] & MSR_EE);
+                       break;
+
+               case XOP_WRTEEI:
+                       vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+                               | (inst & MSR_EE);
+                       break;
+
+               case XOP_TLBRE:
+                       emulated = kvmppc_e500_emul_tlbre(vcpu);
+                       break;
+
+               case XOP_TLBWE:
+                       emulated = kvmppc_e500_emul_tlbwe(vcpu);
+                       break;
+
+               case XOP_TLBSX:
+                       rb = get_rb(inst);
+                       emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
+                       break;
+
+               case XOP_TLBIVAX:
+                       ra = get_ra(inst);
+                       rb = get_rb(inst);
+                       emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
+                       break;
+
+               default:
+                       emulated = EMULATE_FAIL;
+               }
+
+               break;
+
+       default:
+               emulated = EMULATE_FAIL;
+       }
+
+       return emulated;
+}
+
+int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+
+       switch (sprn) {
+       /* E500 */
+       case SPRN_PID:
+               vcpu_e500->pid[0] = vcpu->arch.pid = vcpu->arch.gpr[rs]; break;
+       case SPRN_PID1:
+               vcpu_e500->pid[1] = vcpu->arch.gpr[rs]; break;
+       case SPRN_PID2:
+               vcpu_e500->pid[2] = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS0:
+               vcpu_e500->mas0 = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS1:
+               vcpu_e500->mas1 = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS2:
+               vcpu_e500->mas2 = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS3:
+               vcpu_e500->mas3 = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS4:
+               vcpu_e500->mas4 = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS6:
+               vcpu_e500->mas6 = vcpu->arch.gpr[rs]; break;
+       case SPRN_MAS7:
+               vcpu_e500->mas7 = vcpu->arch.gpr[rs]; break;
+       case SPRN_L1CSR1:
+               vcpu_e500->l1csr1 = vcpu->arch.gpr[rs]; break;
+       case SPRN_HID0:
+               vcpu_e500->hid0 = vcpu->arch.gpr[rs]; break;
+       case SPRN_HID1:
+               vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break;
+
+       /* Book E */
+       case SPRN_DBSR:
+               vcpu->arch.dbsr &= ~vcpu->arch.gpr[rs]; break;
+       case SPRN_DEAR:
+               vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
+       case SPRN_ESR:
+               vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
+       case SPRN_DBCR0:
+               vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
+       case SPRN_DBCR1:
+               vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
+       case SPRN_TSR:
+               vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
+       case SPRN_TCR:
+               vcpu->arch.tcr = vcpu->arch.gpr[rs];
+               kvmppc_emulate_dec(vcpu);
+               break;
+
+       /* Note: SPRG4-7 are user-readable. These values are
+        * loaded into the real SPRGs when resuming the
+        * guest. */
+       case SPRN_SPRG4:
+               vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
+       case SPRN_SPRG5:
+               vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
+       case SPRN_SPRG6:
+               vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
+       case SPRN_SPRG7:
+               vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
+
+       case SPRN_IVPR:
+               vcpu->arch.ivpr = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR0:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR1:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = 
vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR2:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = 
vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR3:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = 
vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR4:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR5:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR6:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR7:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR8:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR9:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR10:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR11:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR12:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR13:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR14:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs];
+               break;
+       case SPRN_IVOR15:
+               vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs];
+               break;
+
+       default:
+               return EMULATE_FAIL;
+       }
+
+       return EMULATE_DONE;
+}
+
+int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+       struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+
+       switch (sprn) {
+       /* E500 */
+       case SPRN_PID:
+               vcpu->arch.gpr[rt] = vcpu_e500->pid[0]; break;
+       case SPRN_PID1:
+               vcpu->arch.gpr[rt] = vcpu_e500->pid[1]; break;
+       case SPRN_PID2:
+               vcpu->arch.gpr[rt] = vcpu_e500->pid[2]; break;
+       case SPRN_MAS0:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas0; break;
+       case SPRN_MAS1:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas1; break;
+       case SPRN_MAS2:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas2; break;
+       case SPRN_MAS3:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas3; break;
+       case SPRN_MAS4:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas4; break;
+       case SPRN_MAS6:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas6; break;
+       case SPRN_MAS7:
+               vcpu->arch.gpr[rt] = vcpu_e500->mas7; break;
+
+       case SPRN_TLB0CFG:
+               vcpu->arch.gpr[rt] = mfspr(SPRN_TLB0CFG);
+               vcpu->arch.gpr[rt] &= ~0xfffUL;
+               vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[0];
+               break;
+
+       case SPRN_TLB1CFG:
+               vcpu->arch.gpr[rt] = mfspr(SPRN_TLB1CFG);
+               vcpu->arch.gpr[rt] &= ~0xfffUL;
+               vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[1];
+               break;
+
+       case SPRN_L1CSR1:
+               vcpu->arch.gpr[rt] = vcpu_e500->l1csr1; break;
+       case SPRN_HID0:
+               vcpu->arch.gpr[rt] = vcpu_e500->hid0; break;
+       case SPRN_HID1:
+               vcpu->arch.gpr[rt] = vcpu_e500->hid1; break;
+
+       /* Book E */
+       case SPRN_PIR:
+               vcpu->arch.gpr[rt] = vcpu->arch.pir; break;
+       case SPRN_DBSR:
+               vcpu->arch.gpr[rt] = vcpu->arch.dbsr; break;
+       case SPRN_IVPR:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
+       case SPRN_DEAR:
+               vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
+       case SPRN_ESR:
+               vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
+       case SPRN_DBCR0:
+               vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
+       case SPRN_DBCR1:
+               vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
+
+       case SPRN_IVOR0:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
+               break;
+       case SPRN_IVOR1:
+               vcpu->arch.gpr[rt] = 
vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
+               break;
+       case SPRN_IVOR2:
+               vcpu->arch.gpr[rt] = 
vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
+               break;
+       case SPRN_IVOR3:
+               vcpu->arch.gpr[rt] = 
vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
+               break;
+       case SPRN_IVOR4:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
+               break;
+       case SPRN_IVOR5:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
+               break;
+       case SPRN_IVOR6:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
+               break;
+       case SPRN_IVOR7:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
+               break;
+       case SPRN_IVOR8:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
+               break;
+       case SPRN_IVOR9:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
+               break;
+       case SPRN_IVOR10:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
+               break;
+       case SPRN_IVOR11:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
+               break;
+       case SPRN_IVOR12:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
+               break;
+       case SPRN_IVOR13:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
+               break;
+       case SPRN_IVOR14:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
+               break;
+       case SPRN_IVOR15:
+               vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
+               break;
+
+       default:
+               return EMULATE_FAIL;
+       }
+
+       return EMULATE_DONE;
+}
+
-- 
1.5.4

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

Reply via email to