hv: add hypercall to register asyncio

Add hypercall to add/remove asyncio request info. Hv will record the
info in a list, and when a new ioreq is come, hv will check if it is
in the asyncio list, if yes, queue the fd to asyncio buffer.

Tracked-On: #8209
Signed-off-by: Conghui <conghui.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Conghui 2022-08-25 14:29:35 +08:00 committed by acrnsi-robot
parent 12bfa98a37
commit 4c79354798
8 changed files with 145 additions and 0 deletions

View File

@ -58,6 +58,10 @@ static const struct hc_dispatch hc_dispatch_table[] = {
.handler = hcall_inject_msi},
[HC_IDX(HC_SET_IOREQ_BUFFER)] = {
.handler = hcall_set_ioreq_buffer},
[HC_IDX(HC_ASYNCIO_ASSIGN)] = {
.handler = hcall_asyncio_assign},
[HC_IDX(HC_ASYNCIO_DEASSIGN)] = {
.handler = hcall_asyncio_deassign},
[HC_IDX(HC_NOTIFY_REQUEST_FINISH)] = {
.handler = hcall_notify_ioreq_finish},
[HC_IDX(HC_VM_SET_MEMORY_REGIONS)] = {

View File

@ -545,6 +545,34 @@ int32_t hcall_setup_sbuf(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
return ret;
}
int32_t hcall_asyncio_assign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
__unused uint64_t param1, uint64_t param2)
{
struct acrn_asyncio_info asyncio_info;
struct acrn_vm *vm = vcpu->vm;
int ret = -1;
if (copy_from_gpa(vm, &asyncio_info, param2, sizeof(asyncio_info)) == 0) {
add_asyncio(target_vm, asyncio_info.type, asyncio_info.addr, asyncio_info.fd);
ret = 0;
}
return ret;
}
int32_t hcall_asyncio_deassign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
__unused uint64_t param1, uint64_t param2)
{
struct acrn_asyncio_info asyncio_info;
struct acrn_vm *vm = vcpu->vm;
int ret = -1;
if (copy_from_gpa(vm, &asyncio_info, param2, sizeof(asyncio_info)) == 0) {
remove_asyncio(target_vm, asyncio_info.type, asyncio_info.addr, asyncio_info.fd);
ret = 0;
}
return ret;
}
/**
* @brief notify request done
*

View File

@ -64,6 +64,63 @@ void reset_vm_ioreqs(struct acrn_vm *vm)
}
}
int add_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd)
{
uint32_t i;
int ret = -1;
if (addr != 0UL) {
spinlock_obtain(&vm->asyncio_lock);
for (i = 0U; i < ACRN_ASYNCIO_MAX; i++) {
if ((vm->aio_desc[i].addr == 0UL) && (vm->aio_desc[i].fd == 0UL)) {
vm->aio_desc[i].type = type;
vm->aio_desc[i].addr = addr;
vm->aio_desc[i].fd = fd;
INIT_LIST_HEAD(&vm->aio_desc[i].list);
list_add(&vm->aio_desc[i].list, &vm->aiodesc_queue);
ret = 0;
break;
}
}
spinlock_release(&vm->asyncio_lock);
if (i == ACRN_ASYNCIO_MAX) {
pr_fatal("too much fastio, would not support!");
}
} else {
pr_err("%s: base = 0 is not supported!", __func__);
}
return ret;
}
int remove_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd)
{
uint32_t i;
int ret = -1;
if (addr != 0UL) {
spinlock_obtain(&vm->asyncio_lock);
for (i = 0U; i < ACRN_ASYNCIO_MAX; i++) {
if ((vm->aio_desc[i].type == type)
&& (vm->aio_desc[i].addr == addr)
&& (vm->aio_desc[i].fd == fd)) {
vm->aio_desc[i].type = 0U;
vm->aio_desc[i].addr = 0UL;
vm->aio_desc[i].fd = 0UL;
list_del_init(&vm->aio_desc[i].list);
ret = 0;
break;
}
}
spinlock_release(&vm->asyncio_lock);
if (i == ACRN_ASYNCIO_MAX) {
pr_fatal("Failed to find asyncio req on addr: %lx!", addr);
}
} else {
pr_err("%s: base = 0 is not supported!", __func__);
}
return ret;
}
static inline bool has_complete_ioreq(const struct acrn_vcpu *vcpu)
{
return (get_io_req_state(vcpu->vm, vcpu->vcpu_id) == ACRN_IOREQ_STATE_COMPLETE);
@ -186,6 +243,8 @@ int init_asyncio(struct acrn_vm *vm, uint64_t *hva)
if (sbuf != NULL) {
if (sbuf->magic == SBUF_MAGIC) {
vm->sw.asyncio_sbuf = sbuf;
INIT_LIST_HEAD(&vm->aiodesc_queue);
spinlock_init(&vm->asyncio_lock);
ret = 0;
}
}

View File

@ -28,6 +28,7 @@
#include <asm/cpu_caps.h>
#include <asm/e820.h>
#include <asm/vm_config.h>
#include <io_req.h>
#ifdef CONFIG_HYPERV_ENABLED
#include <asm/guest/hyperv.h>
#endif
@ -144,6 +145,10 @@ struct acrn_vm {
uint16_t vm_id; /* Virtual machine identifier */
enum vm_state state; /* VM state */
struct acrn_vuart vuart[MAX_VUART_NUM_PER_VM]; /* Virtual UART */
struct asyncio_desc aio_desc[ACRN_ASYNCIO_MAX];
struct list_head aiodesc_queue;
spinlock_t asyncio_lock; /* Spin-lock used to protect asyncio add/remove for a VM */
enum vpic_wire_mode wire_mode;
struct iommu_domain *iommu; /* iommu domain of this VM */
/* vm_state_lock used to protect vm/vcpu state transition,

View File

@ -524,6 +524,33 @@ int32_t hcall_set_callback_vector(struct acrn_vcpu *vcpu, struct acrn_vm *target
*/
int32_t hcall_setup_sbuf(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
/**
* @brief Assign an asyncio to a VM.
*
* @param vcpu not used
* @param target_vm which VM the asyncio belongs.
* @param param1 guest physical address. This gpa points to
* struct acrn_asyncio_info
* @param param2 not used
*
* @return 0 on success, non-zero on error.
*/
int32_t hcall_asyncio_assign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
__unused uint64_t param1, uint64_t param2);
/**
* @brief Deassign an asyncio from a VM.
*
* @param vcpu not used
* @param target_vm which VM the asyncio belongs.
* @param param1 guest physical address. This gpa points to
* struct acrn_asyncio_info
* @param param2 not used
*
* @return 0 on success, non-zero on error.
*/
int32_t hcall_asyncio_deassign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
__unused uint64_t param1, uint64_t param2);
/**
* @brief Setup the hypervisor NPK log.
*

View File

@ -40,6 +40,13 @@ struct io_request {
} reqs;
};
struct asyncio_desc {
uint32_t type;
uint64_t addr;
uint64_t fd;
struct list_head list;
};
/**
* @brief Definition of a IO port range
*/
@ -293,6 +300,10 @@ void unregister_mmio_emulation_handler(struct acrn_vm *vm,
void deinit_emul_io(struct acrn_vm *vm);
int init_asyncio(struct acrn_vm *vm, uint64_t *hva);
int add_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd);
int remove_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd);
/**
* @}
*/

View File

@ -26,6 +26,7 @@
*/
#define ACRN_IO_REQUEST_MAX 16U
#define ACRN_ASYNCIO_MAX 64U
#define ACRN_IOREQ_STATE_PENDING 0U
#define ACRN_IOREQ_STATE_COMPLETE 1U
@ -342,6 +343,12 @@ struct acrn_io_request_buffer {
};
};
struct acrn_asyncio_info {
uint32_t type;
uint64_t addr;
uint64_t fd;
};
/**
* @brief Info to create a VM, the parameter for HC_CREATE_VM hypercall
*/
@ -472,6 +479,7 @@ struct acrn_irqline_ops {
uint32_t op;
};
/**
* @brief Info to inject a MSI interrupt to VM
*

View File

@ -50,6 +50,9 @@
#define HC_ID_IOREQ_BASE 0x30UL
#define HC_SET_IOREQ_BUFFER BASE_HC_ID(HC_ID, HC_ID_IOREQ_BASE + 0x00UL)
#define HC_NOTIFY_REQUEST_FINISH BASE_HC_ID(HC_ID, HC_ID_IOREQ_BASE + 0x01UL)
#define HC_ASYNCIO_ASSIGN BASE_HC_ID(HC_ID, HC_ID_IOREQ_BASE + 0x02UL)
#define HC_ASYNCIO_DEASSIGN BASE_HC_ID(HC_ID, HC_ID_IOREQ_BASE + 0x03UL)
/* Guest memory management */
#define HC_ID_MEM_BASE 0x40UL