1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. |
5 | * |
6 | * KVM/MIPS: Hypercall handling. |
7 | * |
8 | * Copyright (C) 2015 Imagination Technologies Ltd. |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/kvm_host.h> |
13 | #include <linux/kvm_para.h> |
14 | |
15 | #define MAX_HYPCALL_ARGS 4 |
16 | |
17 | enum emulation_result kvm_mips_emul_hypcall(struct kvm_vcpu *vcpu, |
18 | union mips_instruction inst) |
19 | { |
20 | unsigned int code = (inst.co_format.code >> 5) & 0x3ff; |
21 | |
22 | kvm_debug("[%#lx] HYPCALL %#03x\n" , vcpu->arch.pc, code); |
23 | |
24 | switch (code) { |
25 | case 0: |
26 | return EMULATE_HYPERCALL; |
27 | default: |
28 | return EMULATE_FAIL; |
29 | }; |
30 | } |
31 | |
32 | static int kvm_mips_hypercall(struct kvm_vcpu *vcpu, unsigned long num, |
33 | const unsigned long *args, unsigned long *hret) |
34 | { |
35 | /* Report unimplemented hypercall to guest */ |
36 | *hret = -KVM_ENOSYS; |
37 | return RESUME_GUEST; |
38 | } |
39 | |
40 | int kvm_mips_handle_hypcall(struct kvm_vcpu *vcpu) |
41 | { |
42 | unsigned long num, args[MAX_HYPCALL_ARGS]; |
43 | |
44 | /* read hypcall number and arguments */ |
45 | num = vcpu->arch.gprs[2]; /* v0 */ |
46 | args[0] = vcpu->arch.gprs[4]; /* a0 */ |
47 | args[1] = vcpu->arch.gprs[5]; /* a1 */ |
48 | args[2] = vcpu->arch.gprs[6]; /* a2 */ |
49 | args[3] = vcpu->arch.gprs[7]; /* a3 */ |
50 | |
51 | return kvm_mips_hypercall(vcpu, num, |
52 | args, hret: &vcpu->arch.gprs[2] /* v0 */); |
53 | } |
54 | |