| /* |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file "COPYING" in the main directory of this archive |
| * for more details. |
| * |
| * KVM/MIPS: Hypercall handling. |
| * |
| * Copyright (C) 2015 Imagination Technologies Ltd. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/kvm_host.h> |
| #include <linux/kvm_para.h> |
| |
| #define MAX_HYPCALL_ARGS 4 |
| |
| enum emulation_result kvm_mips_emul_hypcall(struct kvm_vcpu *vcpu, |
| union mips_instruction inst) |
| { |
| unsigned int code = (inst.co_format.code >> 5) & 0x3ff; |
| |
| kvm_debug("[%#lx] HYPCALL %#03x\n", vcpu->arch.pc, code); |
| |
| switch (code) { |
| case 0: |
| return EMULATE_HYPERCALL; |
| default: |
| return EMULATE_FAIL; |
| }; |
| } |
| |
| static int kvm_mips_hypercall(struct kvm_vcpu *vcpu, unsigned long num, |
| const unsigned long *args, unsigned long *hret) |
| { |
| /* Report unimplemented hypercall to guest */ |
| *hret = -KVM_ENOSYS; |
| return RESUME_GUEST; |
| } |
| |
| int kvm_mips_handle_hypcall(struct kvm_vcpu *vcpu) |
| { |
| unsigned long num, args[MAX_HYPCALL_ARGS]; |
| |
| /* read hypcall number and arguments */ |
| num = vcpu->arch.gprs[2]; /* v0 */ |
| args[0] = vcpu->arch.gprs[4]; /* a0 */ |
| args[1] = vcpu->arch.gprs[5]; /* a1 */ |
| args[2] = vcpu->arch.gprs[6]; /* a2 */ |
| args[3] = vcpu->arch.gprs[7]; /* a3 */ |
| |
| return kvm_mips_hypercall(vcpu, num, |
| args, &vcpu->arch.gprs[2] /* v0 */); |
| } |