Date
1 - 3 of 3
[PATCH v5 4/7] hv: add hypercall to register asyncio
Conghui Chen
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. v4->v5: 1. change struct asyncio_req aioreqs[ACRN_ASYNCIO_MAX]; to struct asyncio_desc aio_desc[ACRN_ASYNCIO_MAX]; 2. change vm->asyncio_queue to vm->aiodesc_queue Signed-off-by: Conghui <conghui.chen@...> --- hypervisor/arch/x86/guest/vmcall.c | 4 ++ hypervisor/common/hypercall.c | 28 ++++++++++ hypervisor/dm/io_req.c | 59 ++++++++++++++++++++++ hypervisor/include/arch/x86/asm/guest/vm.h | 5 ++ hypervisor/include/common/hypercall.h | 27 ++++++++++ hypervisor/include/dm/io_req.h | 11 ++++ hypervisor/include/public/acrn_common.h | 8 +++ hypervisor/include/public/acrn_hv_defs.h | 3 ++ 8 files changed, 145 insertions(+) diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index 66aac127c..e7ad68940 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -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)] = { diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index f86e3d9d7..982c0d903 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -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_reqinfo 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_reqinfo 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 * diff --git a/hypervisor/dm/io_req.c b/hypervisor/dm/io_req.c index 2ddecfe37..88085fcd5 100644 --- a/hypervisor/dm/io_req.c +++ b/hypervisor/dm/io_req.c @@ -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 != 0) { + spinlock_obtain(&vm->asyncio_lock); + for (i = 0; i < ACRN_ASYNCIO_MAX; i++) { + if (vm->aio_desc[i].addr == 0 && vm->aio_desc[i].fd == 0) { + 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 != 0) { + spinlock_obtain(&vm->asyncio_lock); + for (i = 0; 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 = 0; + vm->aio_desc[i].addr = 0; + vm->aio_desc[i].fd = 0; + 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; } } diff --git a/hypervisor/include/arch/x86/asm/guest/vm.h b/hypervisor/include/arch/x86/asm/guest/vm.h index 8ce702137..62b606be1 100644 --- a/hypervisor/include/arch/x86/asm/guest/vm.h +++ b/hypervisor/include/arch/x86/asm/guest/vm.h @@ -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, diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index 3810f3b6d..75fc777bf 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -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_reqinfo + * @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_reqinfo + * @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. * diff --git a/hypervisor/include/dm/io_req.h b/hypervisor/include/dm/io_req.h index d5ebd2268..775389b0b 100644 --- a/hypervisor/include/dm/io_req.h +++ b/hypervisor/include/dm/io_req.h @@ -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); /** * @} */ diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index a2293c1fa..656c0a45b 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -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_reqinfo { + 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 * diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index c36955f4b..9d9bc2fb7 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -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 -- 2.25.1 |
|
toggle quoted message
Show quoted text
-----Original Message-----Why this is still req (request)? It is a desc or info. Given this one is very close to struct asyncio_desc. Should struct asyncio_desc include this one? The rest is fine. /** |
|
Conghui Chen
Hi Eddie,
Why this is still req (request)? It is a desc or info. Sorry for missing this one. Will change name to ' struct acrn_asyncio_info' in V6. This structure is only used as the parameter of the hypercall, and is shared with kernel. It may change due to the hypercall extension. So, I think better not include it in the hv owns structure asyncio_desc. Regards, Conghui. The rest is fine. |
|