diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index 4903a7803..434c12570 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -11,14 +11,9 @@ static spinlock_t vmm_hypercall_lock = { .head = 0U, .tail = 0U, }; -/* - * Pass return value to SOS by register rax. - * This function should always return 0 since we shouldn't - * deal with hypercall error in hypervisor. - */ -int32_t vmcall_vmexit_handler(struct acrn_vcpu *vcpu) + +static int32_t dispatch_hypercall(struct acrn_vcpu *vcpu) { - int32_t ret = -EACCES; struct acrn_vm *vm = vcpu->vm; /* hypercall ID from guest*/ uint64_t hypcall_id = vcpu_get_gpreg(vcpu, CPU_REG_R8); @@ -26,20 +21,8 @@ int32_t vmcall_vmexit_handler(struct acrn_vcpu *vcpu) uint64_t param1 = vcpu_get_gpreg(vcpu, CPU_REG_RDI); /* hypercall param2 from guest*/ uint64_t param2 = vcpu_get_gpreg(vcpu, CPU_REG_RSI); + int32_t ret; - if (!is_hypercall_from_ring0()) { - pr_err("hypercall is only allowed from RING-0!\n"); - goto out; - } - - if (!is_vm0(vm) && (hypcall_id != HC_WORLD_SWITCH) && - (hypcall_id != HC_INITIALIZE_TRUSTY) && - (hypcall_id != HC_SAVE_RESTORE_SWORLD_CTX)) { - pr_err("hypercall %d is only allowed from VM0!\n", hypcall_id); - goto out; - } - - /* Dispatch the hypercall handler */ switch (hypcall_id) { case HC_SOS_OFFLINE_CPU: spinlock_obtain(&vmm_hypercall_lock); @@ -194,7 +177,34 @@ int32_t vmcall_vmexit_handler(struct acrn_vcpu *vcpu) break; } -out: + return ret; +} + +/* + * Pass return value to SOS by register rax. + * This function should always return 0 since we shouldn't + * deal with hypercall error in hypervisor. + */ +int32_t vmcall_vmexit_handler(struct acrn_vcpu *vcpu) +{ + int32_t ret; + struct acrn_vm *vm = vcpu->vm; + /* hypercall ID from guest*/ + uint64_t hypcall_id = vcpu_get_gpreg(vcpu, CPU_REG_R8); + + if (!is_hypercall_from_ring0()) { + pr_err("hypercall is only allowed from RING-0!\n"); + ret = -EACCES; + } else if (!is_vm0(vm) && (hypcall_id != HC_WORLD_SWITCH) && + (hypcall_id != HC_INITIALIZE_TRUSTY) && + (hypcall_id != HC_SAVE_RESTORE_SWORLD_CTX)) { + pr_err("hypercall %d is only allowed from VM0!\n", hypcall_id); + ret = -EACCES; + } else { + /* Dispatch the hypercall handler */ + ret = dispatch_hypercall(vcpu); + } + vcpu_set_gpreg(vcpu, CPU_REG_RAX, (uint64_t)ret); TRACE_2L(TRACE_VMEXIT_VMCALL, vm->vm_id, hypcall_id);