root/arch/mips/kvm/hypcall.c
/*
 * 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 */);
}