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 <minggui.cao@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Minggui Cao 2018-09-13 16:51:34 +08:00 committed by lijinxia
parent 918403f925
commit d123083fa9
5 changed files with 82 additions and 0 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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
*

View File

@ -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
/**
* @}
*/

View File

@ -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