[PATCH v6 5/7] hv: dispatch asyncio request


Conghui Chen
 

For an IO request, hv will check if it was registered in asyncio desc
list. If yes, put the corresponding fd to the shared buffer. If the
shared buffer is full, yield the vcpu and try again later.

Signed-off-by: Conghui <conghui.chen@...>
Acked-by: Eddie Dong <eddie.dong@...>
---
hypervisor/common/sbuf.c | 2 +
hypervisor/dm/io_req.c | 77 ++++++++++++++++++++++++-
hypervisor/include/public/acrn_common.h | 3 +
3 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/hypervisor/common/sbuf.c b/hypervisor/common/sbuf.c
index 73131fd53..7ff3be1dd 100644
--- a/hypervisor/common/sbuf.c
+++ b/hypervisor/common/sbuf.c
@@ -66,6 +66,8 @@ uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data)
to = (void *)sbuf + SBUF_HEAD_SIZE + sbuf->tail;

(void)memcpy_s(to, sbuf->ele_size, data, sbuf->ele_size);
+ /* make sure write data before update head */
+ cpu_write_memory_barrier();

if (trigger_overwrite) {
sbuf->head = sbuf_next_ptr(sbuf->head,
diff --git a/hypervisor/dm/io_req.c b/hypervisor/dm/io_req.c
index 88085fcd5..a6c0713c6 100644
--- a/hypervisor/dm/io_req.c
+++ b/hypervisor/dm/io_req.c
@@ -7,6 +7,7 @@
#include <asm/irq.h>
#include <errno.h>
#include <logmsg.h>
+#include <sbuf.h>

#define DBG_LEVEL_IOREQ 6U

@@ -126,6 +127,69 @@ 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);
}

+static struct asyncio_desc *get_asyncio_desc(struct acrn_vcpu *vcpu, const struct io_request *io_req)
+{
+ uint64_t addr = 0;
+ uint32_t type;
+ struct list_head *pos;
+ struct asyncio_desc *iter_desc;
+ struct acrn_vm *vm = vcpu->vm;
+ struct asyncio_desc *ret = NULL;
+
+ switch (io_req->io_type) {
+ case ACRN_IOREQ_TYPE_PORTIO:
+ addr = io_req->reqs.pio_request.address;
+ type = ACRN_ASYNCIO_PIO;
+ break;
+
+ case ACRN_IOREQ_TYPE_MMIO:
+ addr = io_req->reqs.mmio_request.address;
+ type = ACRN_ASYNCIO_MMIO;
+ break;
+ default:
+ break;
+ }
+
+ if (addr != 0) {
+ spinlock_obtain(&vm->asyncio_lock);
+ list_for_each(pos, &vm->aiodesc_queue) {
+ iter_desc = container_of(pos, struct asyncio_desc, list);
+ if (iter_desc->addr == addr && iter_desc->type == type) {
+ ret = iter_desc;
+ break;
+ }
+ }
+ spinlock_release(&vm->asyncio_lock);
+ }
+
+ return ret;
+
+}
+static int acrn_insert_asyncio(struct acrn_vcpu *vcpu, const uint64_t asyncio_fd)
+{
+ struct acrn_vm *vm = vcpu->vm;
+ struct shared_buf *sbuf =
+ (struct shared_buf *)vm->sw.asyncio_sbuf;
+ int ret = -ENODEV;
+
+ if (sbuf != NULL) {
+ spinlock_obtain(&vm->asyncio_lock);
+ while (sbuf_put(sbuf, (uint8_t *)&asyncio_fd) == 0) {
+ /* sbuf is full, try later.. */
+ spinlock_release(&vm->asyncio_lock);
+ asm_pause();
+ if (need_reschedule(pcpuid_from_vcpu(vcpu))) {
+ schedule();
+ }
+ spinlock_obtain(&vm->asyncio_lock);
+ }
+
+ spinlock_release(&vm->asyncio_lock);
+ arch_fire_hsm_interrupt();
+ ret = 0;
+ }
+ return ret;
+}
/**
* @brief Deliver \p io_req to Service VM and suspend \p vcpu till its completion
*
@@ -615,6 +679,7 @@ emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req)
{
int32_t status;
struct acrn_vm_config *vm_config;
+ struct asyncio_desc *aio_desc;

vm_config = get_vm_config(vcpu->vm->vm_id);

@@ -644,10 +709,16 @@ emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req)
*
* ACRN insert request to HSM and inject upcall.
*/
- status = acrn_insert_request(vcpu, io_req);
- if (status == 0) {
- dm_emulate_io_complete(vcpu);
+ aio_desc = get_asyncio_desc(vcpu, io_req);
+ if (aio_desc) {
+ status = acrn_insert_asyncio(vcpu, aio_desc->fd);
} else {
+ status = acrn_insert_request(vcpu, io_req);
+ if (status == 0) {
+ dm_emulate_io_complete(vcpu);
+ }
+ }
+ if (status != 0) {
/* here for both IO & MMIO, the direction, address,
* size definition is same
*/
diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h
index 86299ce05..c332632e4 100644
--- a/hypervisor/include/public/acrn_common.h
+++ b/hypervisor/include/public/acrn_common.h
@@ -725,6 +725,9 @@ struct acrn_vdev {
uint8_t args[128];
};

+#define ACRN_ASYNCIO_PIO (0x01U)
+#define ACRN_ASYNCIO_MMIO (0x02U)
+
#define SBUF_MAGIC 0x5aa57aa71aa13aa3UL
#define SBUF_MAX_SIZE (1UL << 22U)
#define SBUF_HEAD_SIZE 64U
--
2.25.1