From d123083fa98d121f049819ed7f4eccfd2fc1c17a Mon Sep 17 00:00:00 2001 From: Minggui Cao Date: Thu, 13 Sep 2018 16:51:34 +0800 Subject: [PATCH] HV: add hypercall to monitor UOS PTdev intr status The hypercall can be used by SOS/DM to monitor UOS pass-thru devices' interrupt data; and if an "interrupt storm" happens in UOS, it can be used to delay the UOS PTdev interrupt's injection for sometime. The two functions are implemented by one hypercall with two sub-commands, and with the data/params in the buffer. Tracked-On: #866 Signed-off-by: Minggui Cao Acked-by: Anthony Xu --- hypervisor/arch/x86/guest/vmcall.c | 4 +++ hypervisor/common/hypercall.c | 44 ++++++++++++++++++++++++ hypervisor/include/common/hypercall.h | 13 +++++++ hypervisor/include/public/acrn_common.h | 20 +++++++++++ hypervisor/include/public/acrn_hv_defs.h | 1 + 5 files changed, 82 insertions(+) diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index e06f27c59..4d1e0eb59 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -181,6 +181,10 @@ int vmcall_vmexit_handler(struct vcpu *vcpu) ret = hcall_save_restore_sworld_ctx(vcpu); break; + case HC_VM_INTR_MONITOR: + ret = hcall_vm_intr_monitor(vm, (uint16_t)param1, param2); + break; + default: pr_err("op %d: Invalid hypercall\n", hypcall_id); ret = -EPERM; diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 2c98ed8f8..c5976c8b7 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -995,3 +995,47 @@ int32_t hcall_get_cpu_pm_state(struct vm *vm, uint64_t cmd, uint64_t param) } } + +/** + *@pre Pointer vm shall point to VM0 + */ +int32_t hcall_vm_intr_monitor(struct vm *vm, uint16_t vmid, uint64_t param) +{ + struct acrn_intr_monitor *intr_hdr; + uint64_t hpa; + struct vm *target_vm = get_vm_from_vmid(vmid); + + if (target_vm == NULL) { + return -1; + } + + /* the param for this hypercall is page aligned */ + hpa = gpa2hpa(vm, param); + if (hpa == 0UL) { + pr_err("%s: invalid GPA.\n", __func__); + return -EINVAL; + } + + intr_hdr = (struct acrn_intr_monitor *)hpa2hva(hpa); + + switch (intr_hdr->cmd) { + case INTR_CMD_GET_DATA: + intr_hdr->buf_cnt = get_vm_ptdev_intr_data(target_vm, + intr_hdr->buffer, intr_hdr->buf_cnt); + break; + + case INTR_CMD_DELAY_INT: + /* buffer[0] is the delay time (in MS), if 0 to cancel delay */ + target_vm->intr_inject_delay_delta = + intr_hdr->buffer[0] * CYCLES_PER_MS; + break; + + default: + /* if cmd wrong it goes here should not happen */ + break; + } + + pr_dbg("intr monitor:%d, cnt=%d", intr_hdr->cmd, intr_hdr->buf_cnt); + + return 0; +} diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index cb18fa8d0..609ce0327 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -387,6 +387,19 @@ int32_t hcall_setup_hv_npk_log(struct vm *vm, uint64_t param); int32_t hcall_get_cpu_pm_state(struct vm *vm, uint64_t cmd, uint64_t param); +/** + * @brief Get VCPU a VM's interrupt count data. + * + * @param vm pointer to VM data structure + * @param vmid id of the VM + * @param param guest physical address. This gpa points to data structure of + * acrn_intr_monitor + * + * @pre Pointer vm shall point to VM0 + * @return 0 on success, non-zero on error. + */ +int32_t hcall_vm_intr_monitor(struct vm *vm, uint16_t vmid, uint64_t param); + /** * @defgroup trusty_hypercall Trusty Hypercalls * diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index c39f8e870..c4e1536fe 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -453,6 +453,26 @@ enum pm_cmd_type { PMCMD_GET_CX_DATA, }; +/** + * @brief Info to get a VM interrupt count data + * + * the parameter for HC_VM_INTR_MONITOR hypercall + */ +#define MAX_PTDEV_NUM 24 +struct acrn_intr_monitor { + /** sub command for intr monitor */ + uint32_t cmd; + /** the count of this buffer to save */ + uint32_t buf_cnt; + + /** the buffer which save each interrupt count */ + uint64_t buffer[MAX_PTDEV_NUM * 2]; +} __aligned(8); + +/** cmd for intr monitor **/ +#define INTR_CMD_GET_DATA 0U +#define INTR_CMD_DELAY_INT 1U + /** * @} */ diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index 8a2537926..aa4318bb6 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -43,6 +43,7 @@ #define HC_DEASSERT_IRQLINE BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x01UL) #define HC_PULSE_IRQLINE BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x02UL) #define HC_INJECT_MSI BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x03UL) +#define HC_VM_INTR_MONITOR BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x04UL) /* DM ioreq management */ #define HC_ID_IOREQ_BASE 0x30UL