aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm/emulate.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kvm/emulate.c')
-rw-r--r--arch/mips/kvm/emulate.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 838d3a6a5b7d..33e132dc7de8 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1970,6 +1970,41 @@ enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
1970 return er; 1970 return er;
1971} 1971}
1972 1972
1973enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause,
1974 uint32_t *opc,
1975 struct kvm_run *run,
1976 struct kvm_vcpu *vcpu)
1977{
1978 struct mips_coproc *cop0 = vcpu->arch.cop0;
1979 struct kvm_vcpu_arch *arch = &vcpu->arch;
1980 enum emulation_result er = EMULATE_DONE;
1981
1982 if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
1983 /* save old pc */
1984 kvm_write_c0_guest_epc(cop0, arch->pc);
1985 kvm_set_c0_guest_status(cop0, ST0_EXL);
1986
1987 if (cause & CAUSEF_BD)
1988 kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
1989 else
1990 kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
1991
1992 kvm_debug("Delivering TRAP @ pc %#lx\n", arch->pc);
1993
1994 kvm_change_c0_guest_cause(cop0, (0xff),
1995 (T_TRAP << CAUSEB_EXCCODE));
1996
1997 /* Set PC to the exception entry point */
1998 arch->pc = KVM_GUEST_KSEG0 + 0x180;
1999
2000 } else {
2001 kvm_err("Trying to deliver TRAP when EXL is already set\n");
2002 er = EMULATE_FAIL;
2003 }
2004
2005 return er;
2006}
2007
1973/* ll/sc, rdhwr, sync emulation */ 2008/* ll/sc, rdhwr, sync emulation */
1974 2009
1975#define OPCODE 0xfc000000 2010#define OPCODE 0xfc000000
@@ -2176,6 +2211,7 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
2176 case T_SYSCALL: 2211 case T_SYSCALL:
2177 case T_BREAK: 2212 case T_BREAK:
2178 case T_RES_INST: 2213 case T_RES_INST:
2214 case T_TRAP:
2179 case T_MSADIS: 2215 case T_MSADIS:
2180 break; 2216 break;
2181 2217