Re: [PATCH v4 4/7] hv: add hypercall to register asyncio


Eddie Dong
 

-----Original Message-----
From: Chen, Conghui <conghui.chen@...>
Sent: Friday, September 16, 2022 1:11 AM
To: Dong, Eddie <eddie.dong@...>; acrn-dev@...
Subject: RE: [acrn-dev] [PATCH v4 4/7] hv: add hypercall to register asyncio

Hi Eddie,


-----Original Message-----
From: acrn-dev@...
<acrn-dev@...> On Behalf Of Conghui Chen
Sent: Monday, September 12, 2022 8:28 PM
To: acrn-dev@...
Cc: Chen, Conghui <conghui.chen@...>
Subject: [acrn-dev] [PATCH v4 4/7] 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.
We use the shared buffer between the VM & HV, why we need Hypecall?
These two hypercall are used by Sos to register/unregister an MMIO/PIO's
type/base/fd to hypervisor.
In hypervisor, it will record these info in a list through 'add_asyncio()'.
This list just like a dictionary, when the Guest do an IO, hv will check the list
first to see if it is an asyncio, If yes, return the corresponding fd from the list.
Then hv will use 'sbuf_put' to put the fd to the shared buffer.
I see. I am confused by the term of asyncio_req.
+ struct asyncio_req aioreqs[ACRN_ASYNCIO_MAX];

Based on what you said, it is asyncio, not xx_req. The request should be put into sbuf.

You may refer:
struct vm_io_handler_desc emul_pio[EMUL_PIO_IDX_MAX];






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 | 9 ++++
hypervisor/include/public/acrn_hv_defs.h | 3 ++
8 files changed, 146 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 cffd350e1..7c809234f 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..3d8609807 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->aioreqs[i].addr == 0 && vm->aioreqs[i].fd == 0)
{
+ vm->aioreqs[i].type = type;
+ vm->aioreqs[i].addr = addr;
+ vm->aioreqs[i].fd = fd;
+ INIT_LIST_HEAD(&vm->aioreqs[i].list);
+ list_add(&vm->aioreqs[i].list, &vm-
asyncio_queue);
+ ret = 0;
+ break;
+ }
+ }
+ spinlock_release(&vm->asyncio_lock);
Sbuf already has an API to add an element or remove, why we need a new
one?
Here only register the IO info to hypervisor from SOS, sbuf is not used here.


Regards,
Conghui.




+ 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->aioreqs[i].type == type
+ && vm->aioreqs[i].addr == addr
+ && vm->aioreqs[i].fd == fd) {
+ vm->aioreqs[i].type = 0;
+ vm->aioreqs[i].addr = 0;
+ vm->aioreqs[i].fd = 0;
+ list_del_init(&vm->aioreqs[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->asyncio_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..c055c40ae 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_req aioreqs[ACRN_ASYNCIO_MAX];
+ struct list_head asyncio_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..dfe855701 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_req {
+ 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 2f1674350..6fbab30a6 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
@@ -73,6 +74,7 @@
#define VIRTUAL_PM1A_ALWAYS_ZERO 0xc003

#define MAX_VM_NAME_LEN (16U)
+#define ACRN_ASYNCIO_BITMAP_SIZE
+INT_DIV_ROUNDUP(ACRN_ASYNCIO_REQUEST_MAX, 64U)

/**
* @brief Hypercall
@@ -342,6 +344,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 +480,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




Join acrn-dev@lists.projectacrn.org to automatically receive all group messages.