From 1d0d4d31859f6d7b4be432b89ac28b8482998d2b Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Thu, 5 Apr 2018 17:57:09 +0800 Subject: [PATCH] HV: add hypercall interface of get vcpu state data We can use this interface for VHM to pass per-cpu power state data to guest per its request. For now the vcpu power state is per-vm, this could be changed if per-cpu power state support is required in the future. Signed-off-by: Victor Sun Acked-by: Kevin Tian --- hypervisor/arch/x86/guest/vmcall.c | 4 ++ hypervisor/common/hypercall.c | 58 ++++++++++++++++++++++++ hypervisor/include/common/hypercall.h | 11 +++++ hypervisor/include/public/acrn_common.h | 20 ++++++++ hypervisor/include/public/acrn_hv_defs.h | 4 ++ 5 files changed, 97 insertions(+) diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index 72b6d0b74..993946814 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -142,6 +142,10 @@ int vmcall_handler(struct vcpu *vcpu) ret = hcall_initialize_trusty(vcpu, param1); break; + case HC_PM_GET_CPU_STATE: + ret = hcall_get_cpu_pm_state(vm, param1, param2); + break; + default: pr_err("op %d: Invalid hypercall\n", hypcall_id); ret = -1; diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 91c217da9..258ed13f8 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -37,6 +37,7 @@ #include #include #include +#include #define ACRN_DBG_HYCALL 6 @@ -664,6 +665,63 @@ int64_t hcall_setup_sbuf(struct vm *vm, uint64_t param) return sbuf_share_setup(ssp.pcpu_id, ssp.sbuf_id, hva); } +int64_t hcall_get_cpu_pm_state(struct vm *vm, uint64_t cmd, uint64_t param) +{ + int target_vm_id, target_vcpu_id; + struct vm *target_vm; + struct vcpu *target_vcpu; + + target_vm_id = (cmd & PMCMD_VMID_MASK) >> PMCMD_VMID_SHIFT; + target_vm = get_vm_from_vmid(target_vm_id); + + if (!target_vm) { + return -1; + } + + switch (cmd & PMCMD_TYPE_MASK) { + case PMCMD_GET_PX_CNT: { + + if (!target_vm->pm.px_cnt) { + return -1; + } + + if (copy_to_vm(vm, &(target_vm->pm.px_cnt), param)) { + pr_err("%s: Unable copy param to vm\n", __func__); + return -1; + } + return 0; + } + case PMCMD_GET_PX_DATA: { + int pn; + struct cpu_px_data *px_data; + + /* For now we put px data as per-vm, + * If it is stored as per-cpu in the future, + * we need to check PMCMD_VCPUID_MASK in cmd. + */ + if (!target_vm->pm.px_cnt) { + return -1; + } + + pn = (cmd & PMCMD_STATE_NUM_MASK) >> PMCMD_STATE_NUM_SHIFT; + if (pn >= target_vm->pm.px_cnt) { + return -1; + } + + px_data = target_vm->pm.px_data + pn; + if (copy_to_vm(vm, px_data, param)) { + pr_err("%s: Unable copy param to vm\n", __func__); + return -1; + } + + return 0; + } + default: + return -1; + + } +} + static void fire_vhm_interrupt(void) { /* diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index c1f4b48c0..6584e94a8 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -333,6 +333,17 @@ int64_t hcall_setup_sbuf(struct vm *vm, uint64_t param); * * @return 0 on success, non-zero on error. */ + +int64_t hcall_get_cpu_pm_state(struct vm *vm, uint64_t cmd, uint64_t param); + +/** + * @brief Get VCPU Power state. + * + * @param VCPU power state data + * + * @return 0 on success, non-zero on error. + */ + int64_t hcall_world_switch(struct vcpu *vcpu); /** diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index c179060e4..3bef6515c 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -301,6 +301,26 @@ struct cpu_px_data { uint64_t status; /* success indicator */ } __attribute__((aligned(8))); +/** + * @brief Info PM command from DM/VHM. + * + * The command would specify request type(i.e. get px count or data) for + * specific VM and specific VCPU with specific state number.like P(n). + */ +#define PMCMD_VMID_MASK 0xff000000 +#define PMCMD_VCPUID_MASK 0x00ff0000 +#define PMCMD_STATE_NUM_MASK 0x0000ff00 +#define PMCMD_TYPE_MASK 0x000000ff + +#define PMCMD_VMID_SHIFT 24 +#define PMCMD_VCPUID_SHIFT 16 +#define PMCMD_STATE_NUM_SHIFT 8 + +enum pm_cmd_type { + PMCMD_GET_PX_CNT, + PMCMD_GET_PX_DATA, +}; + /** * @} */ diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index 8ce4c4015..168d86b9b 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -99,6 +99,10 @@ #define HC_WORLD_SWITCH _HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x01) #define HC_GET_SEC_INFO _HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x02) +/* Power management */ +#define HC_ID_PM_BASE 0x80UL +#define HC_PM_GET_CPU_STATE _HC_ID(HC_ID, HC_ID_PM_BASE + 0x00) + #define ACRN_DOM0_VMID (0UL) #define ACRN_INVALID_VMID (-1) #define ACRN_INVALID_HPA (-1UL)