aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm/emulate.c
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2015-02-06 05:56:27 -0500
committerJames Hogan <james.hogan@imgtec.com>2015-03-27 17:25:16 -0400
commit1c0cd66adbac8aa339b9521eceb18b00d1b0699e (patch)
tree62a893856435ad26ac8724cb23c3e47b63d177bd /arch/mips/kvm/emulate.c
parent6cdc65e31d4f70561d71eeaf34a2a70ab68bf146 (diff)
MIPS: KVM: Add FP exception handling
Add guest exception handling for floating point exceptions and coprocessor 1 unusable exceptions. Floating point exceptions from the guest need passing to the guest kernel, so for these a guest FPE is emulated. Also, coprocessor 1 unusable exceptions are normally passed straight through to the guest (because no guest FPU was supported), but the hypervisor can now handle them if the guest has its FPU enabled by restoring the guest FPU context and enabling the FPU. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Gleb Natapov <gleb@kernel.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org
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 3511bb20fe0e..fbf169fb63df 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -2146,6 +2146,41 @@ enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause,
2146 return er; 2146 return er;
2147} 2147}
2148 2148
2149enum emulation_result kvm_mips_emulate_fpe_exc(unsigned long cause,
2150 uint32_t *opc,
2151 struct kvm_run *run,
2152 struct kvm_vcpu *vcpu)
2153{
2154 struct mips_coproc *cop0 = vcpu->arch.cop0;
2155 struct kvm_vcpu_arch *arch = &vcpu->arch;
2156 enum emulation_result er = EMULATE_DONE;
2157
2158 if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
2159 /* save old pc */
2160 kvm_write_c0_guest_epc(cop0, arch->pc);
2161 kvm_set_c0_guest_status(cop0, ST0_EXL);
2162
2163 if (cause & CAUSEF_BD)
2164 kvm_set_c0_guest_cause(cop0, CAUSEF_BD);
2165 else
2166 kvm_clear_c0_guest_cause(cop0, CAUSEF_BD);
2167
2168 kvm_debug("Delivering FPE @ pc %#lx\n", arch->pc);
2169
2170 kvm_change_c0_guest_cause(cop0, (0xff),
2171 (T_FPE << CAUSEB_EXCCODE));
2172
2173 /* Set PC to the exception entry point */
2174 arch->pc = KVM_GUEST_KSEG0 + 0x180;
2175
2176 } else {
2177 kvm_err("Trying to deliver FPE when EXL is already set\n");
2178 er = EMULATE_FAIL;
2179 }
2180
2181 return er;
2182}
2183
2149/* ll/sc, rdhwr, sync emulation */ 2184/* ll/sc, rdhwr, sync emulation */
2150 2185
2151#define OPCODE 0xfc000000 2186#define OPCODE 0xfc000000
@@ -2353,6 +2388,7 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
2353 case T_BREAK: 2388 case T_BREAK:
2354 case T_RES_INST: 2389 case T_RES_INST:
2355 case T_TRAP: 2390 case T_TRAP:
2391 case T_FPE:
2356 case T_MSADIS: 2392 case T_MSADIS:
2357 break; 2393 break;
2358 2394