| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 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, &vcpu->arch.gprs[2] /* v0 */); | 
 | 53 | } |