diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index f0a36199b..4a0e83741 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -78,6 +78,11 @@ int vmcall_vmexit_handler(struct vcpu *vcpu) ret = hcall_create_vcpu(vm, (uint16_t)param1, param2); break; + case HC_SET_VCPU_REGS: + /* param1: vmid */ + ret = hcall_set_vcpu_regs(vm, (uint16_t)param1, param2); + break; + case HC_ASSERT_IRQLINE: /* param1: vmid */ ret = hcall_assert_irqline(vm, (uint16_t)param1, param2); diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index bd8eb33d1..7fb190a6a 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -297,6 +297,40 @@ int32_t hcall_pulse_irqline(struct vm *vm, uint16_t vmid, uint64_t param) return ret; } +/** + *@pre Pointer vm shall point to VM0 + */ +int32_t hcall_set_vcpu_regs(struct vm *vm, uint16_t vmid, uint64_t param) +{ + struct vm *target_vm = get_vm_from_vmid(vmid); + struct acrn_set_vcpu_regs vcpu_regs; + struct vcpu *vcpu; + + if ((target_vm == NULL) || (param == 0U) || is_vm0(target_vm)) { + return -1; + } + + /* Only allow setup init ctx while target_vm is inactive */ + if (target_vm->state == VM_STARTED) { + return -1; + } + + if (copy_from_gpa(vm, &vcpu_regs, param, sizeof(vcpu_regs)) != 0) { + pr_err("%s: Unable copy param to vm\n", __func__); + return -1; + } + + vcpu = vcpu_from_vid(target_vm, vcpu_regs.vcpu_id); + if (vcpu == NULL) { + pr_err("%s: invalid vcpu_id for set_vcpu_regs\n", __func__); + return -1; + } + + set_vcpu_regs(vcpu, &(vcpu_regs.vcpu_regs)); + + return 0; +} + /** *@pre Pointer vm shall point to VM0 */ diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index 0020444fc..7de01098f 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -136,6 +136,22 @@ int32_t hcall_pause_vm(uint16_t vmid); */ int32_t hcall_create_vcpu(struct vm *vm, uint16_t vmid, uint64_t param); +/** + * @brief set vcpu regs + * + * Set the vcpu regs. It will set the vcpu init regs from DM. Now, + * it's only applied to BSP. AP always uses fixed init regs. + * The function will return -1 if the targat VM or BSP doesn't exist. + * + * @param vm Pointer to VM data structure + * @param vmid ID of the VM + * @param param guest physical address. This gpa points to + * struct acrn_vcpu_regs + * + * @return 0 on success, non-zero on error. + */ +int32_t hcall_set_vcpu_regs(struct vm *vm, uint16_t vmid, uint64_t param); + /** * @brief assert IRQ line * diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index ff38e2533..a28d4d53d 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -310,6 +310,22 @@ struct acrn_vcpu_regs { uint16_t reserved_16[4]; }; +/** + * @brief Info to set vcpu state + * + * the pamameter for HC_SET_VCPU_STATE + */ +struct acrn_set_vcpu_regs { + /** the virtual CPU ID for the VCPU to set state */ + uint16_t vcpu_id; + + /** reserved space to make cpu_state aligned to 8 bytes */ + uint16_t reserved0[3]; + + /** the structure to hold vcpu state */ + struct acrn_vcpu_regs vcpu_regs; +} __attribute__((aligned(8))); + /** * @brief Info to set ioreq buffer for a created VM * diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index a845391dc..078524275 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -37,6 +37,7 @@ #define HC_PAUSE_VM BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x03UL) #define HC_CREATE_VCPU BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x04UL) #define HC_RESET_VM BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x05UL) +#define HC_SET_VCPU_REGS BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x06UL) /* IRQ and Interrupts */ #define HC_ID_IRQ_BASE 0x20UL