aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2015-02-06 06:11:56 -0500
committerJames Hogan <james.hogan@imgtec.com>2015-03-27 17:25:05 -0400
commit98119ad53376885819d93dfb8737b6a9a61ca0ba (patch)
tree2378ba4c147d05f49ee694082899d220298a6f0f /arch/mips/kvm
parent8e6c94910320e8ff0f6a4f2fdd809f50289d2852 (diff)
MIPS: KVM: Handle MSA Disabled exceptions from guest
Guest user mode can generate a guest MSA Disabled exception on an MSA capable core by simply trying to execute an MSA instruction. Since this exception is unknown to KVM it will be passed on to the guest kernel. However guest Linux kernels prior to v3.15 do not set up an exception handler for the MSA Disabled exception as they don't support any MSA capable cores. This results in a guest OS panic. Since an older processor ID may be being emulated, and MSA support is not advertised to the guest, the correct behaviour is to generate a Reserved Instruction exception in the guest kernel so it can send the guest process an illegal instruction signal (SIGILL), as would happen with a non-MSA-capable core. Fix this as minimally as reasonably possible by preventing kvm_mips_check_privilege() from relaying MSA Disabled exceptions from guest user mode to the guest kernel, and handling the MSA Disabled exception by emulating a Reserved Instruction exception in the guest, via a new handle_msa_disabled() KVM callback. 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 Cc: <stable@vger.kernel.org> # v3.15+
Diffstat (limited to 'arch/mips/kvm')
-rw-r--r--arch/mips/kvm/emulate.c1
-rw-r--r--arch/mips/kvm/mips.c4
-rw-r--r--arch/mips/kvm/trap_emul.c28
3 files changed, 33 insertions, 0 deletions
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index fb3e8dfd1ff6..838d3a6a5b7d 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -2176,6 +2176,7 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
2176 case T_SYSCALL: 2176 case T_SYSCALL:
2177 case T_BREAK: 2177 case T_BREAK:
2178 case T_RES_INST: 2178 case T_RES_INST:
2179 case T_MSADIS:
2179 break; 2180 break;
2180 2181
2181 case T_COP_UNUSABLE: 2182 case T_COP_UNUSABLE:
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index c9eccf5df912..f5e7ddab02f7 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -1119,6 +1119,10 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
1119 ret = kvm_mips_callbacks->handle_break(vcpu); 1119 ret = kvm_mips_callbacks->handle_break(vcpu);
1120 break; 1120 break;
1121 1121
1122 case T_MSADIS:
1123 ret = kvm_mips_callbacks->handle_msa_disabled(vcpu);
1124 break;
1125
1122 default: 1126 default:
1123 kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n", 1127 kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n",
1124 exccode, opc, kvm_get_inst(opc, vcpu), badvaddr, 1128 exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index fd7257b70e65..4372cc86650c 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -330,6 +330,33 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
330 return ret; 330 return ret;
331} 331}
332 332
333static int kvm_trap_emul_handle_msa_disabled(struct kvm_vcpu *vcpu)
334{
335 struct kvm_run *run = vcpu->run;
336 uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc;
337 unsigned long cause = vcpu->arch.host_cp0_cause;
338 enum emulation_result er = EMULATE_DONE;
339 int ret = RESUME_GUEST;
340
341 /* No MSA supported in guest, guest reserved instruction exception */
342 er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
343
344 switch (er) {
345 case EMULATE_DONE:
346 ret = RESUME_GUEST;
347 break;
348
349 case EMULATE_FAIL:
350 run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
351 ret = RESUME_HOST;
352 break;
353
354 default:
355 BUG();
356 }
357 return ret;
358}
359
333static int kvm_trap_emul_vm_init(struct kvm *kvm) 360static int kvm_trap_emul_vm_init(struct kvm *kvm)
334{ 361{
335 return 0; 362 return 0;
@@ -470,6 +497,7 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
470 .handle_syscall = kvm_trap_emul_handle_syscall, 497 .handle_syscall = kvm_trap_emul_handle_syscall,
471 .handle_res_inst = kvm_trap_emul_handle_res_inst, 498 .handle_res_inst = kvm_trap_emul_handle_res_inst,
472 .handle_break = kvm_trap_emul_handle_break, 499 .handle_break = kvm_trap_emul_handle_break,
500 .handle_msa_disabled = kvm_trap_emul_handle_msa_disabled,
473 501
474 .vm_init = kvm_trap_emul_vm_init, 502 .vm_init = kvm_trap_emul_vm_init,
475 .vcpu_init = kvm_trap_emul_vcpu_init, 503 .vcpu_init = kvm_trap_emul_vcpu_init,