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:
parent
12bfa98a37
commit
4c79354798
|
@ -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)] = {
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue