18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
38c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
48c2ecf20Sopenharmony_ci * for more details.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * KVM/MIPS: Hypercall handling.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2015  Imagination Technologies Ltd.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/kvm_host.h>
138c2ecf20Sopenharmony_ci#include <linux/kvm_para.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define MAX_HYPCALL_ARGS	4
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cienum emulation_result kvm_mips_emul_hypcall(struct kvm_vcpu *vcpu,
188c2ecf20Sopenharmony_ci					    union mips_instruction inst)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	unsigned int code = (inst.co_format.code >> 5) & 0x3ff;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	kvm_debug("[%#lx] HYPCALL %#03x\n", vcpu->arch.pc, code);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	switch (code) {
258c2ecf20Sopenharmony_ci	case 0:
268c2ecf20Sopenharmony_ci		return EMULATE_HYPERCALL;
278c2ecf20Sopenharmony_ci	default:
288c2ecf20Sopenharmony_ci		return EMULATE_FAIL;
298c2ecf20Sopenharmony_ci	};
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int kvm_mips_hypercall(struct kvm_vcpu *vcpu, unsigned long num,
338c2ecf20Sopenharmony_ci			      const unsigned long *args, unsigned long *hret)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	/* Report unimplemented hypercall to guest */
368c2ecf20Sopenharmony_ci	*hret = -KVM_ENOSYS;
378c2ecf20Sopenharmony_ci	return RESUME_GUEST;
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ciint kvm_mips_handle_hypcall(struct kvm_vcpu *vcpu)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	unsigned long num, args[MAX_HYPCALL_ARGS];
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* read hypcall number and arguments */
458c2ecf20Sopenharmony_ci	num = vcpu->arch.gprs[2];	/* v0 */
468c2ecf20Sopenharmony_ci	args[0] = vcpu->arch.gprs[4];	/* a0 */
478c2ecf20Sopenharmony_ci	args[1] = vcpu->arch.gprs[5];	/* a1 */
488c2ecf20Sopenharmony_ci	args[2] = vcpu->arch.gprs[6];	/* a2 */
498c2ecf20Sopenharmony_ci	args[3] = vcpu->arch.gprs[7];	/* a3 */
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	return kvm_mips_hypercall(vcpu, num,
528c2ecf20Sopenharmony_ci				  args, &vcpu->arch.gprs[2] /* v0 */);
538c2ecf20Sopenharmony_ci}
54