Date
1 - 1 of 1
[PATCH v6 3/7] hv: support asyncio request
Conghui Chen
Current IO emulation is synchronous. The user VM need to wait for the
completion of the the I/O request before return. But Virtio Spec
introduces introduces asynchronous IO with a new register in MMIO/PIO
space named NOTIFY, to be used for FE driver to notify BE driver, ACRN
hypervisor can emulate this register by sending a notification to vCPU
in Service VM side. This way, FE side can resume to work without waiting
for the full completion of BE side response.
Signed-off-by: Conghui <conghui.chen@...>
Acked-by: Eddie Dong <eddie.dong@...>
---
hypervisor/arch/x86/guest/vm.c | 1 +
hypervisor/common/sbuf.c | 5 ++++-
hypervisor/debug/sbuf.c | 4 ++--
hypervisor/dm/io_req.c | 17 +++++++++++++++++
hypervisor/include/arch/x86/asm/guest/vm.h | 1 +
hypervisor/include/arch/x86/asm/per_cpu.h | 2 +-
hypervisor/include/dm/io_req.h | 2 ++
hypervisor/include/public/acrn_common.h | 4 +++-
8 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c
index bdd31d3fa..c103d3a1f 100644
--- a/hypervisor/arch/x86/guest/vm.c
+++ b/hypervisor/arch/x86/guest/vm.c
@@ -758,6 +758,7 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v
/* Populate return VM handle */
*rtn_vm = vm;
vm->sw.io_shared_page = NULL;
+ vm->sw.asyncio_sbuf = NULL;
if ((vm_config->load_order == POST_LAUNCHED_VM)
&& ((vm_config->guest_flags & GUEST_FLAG_IO_COMPLETION_POLLING) != 0U)) {
/* enable IO completion polling mode per its guest flags in vm_config. */
diff --git a/hypervisor/common/sbuf.c b/hypervisor/common/sbuf.c
index 36ce9d2fa..73131fd53 100644
--- a/hypervisor/common/sbuf.c
+++ b/hypervisor/common/sbuf.c
@@ -79,7 +79,7 @@ uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data)
return ele_size;
}
-int32_t sbuf_setup_common(__unused struct acrn_vm *vm, uint16_t cpu_id, uint32_t sbuf_id, uint64_t *hva)
+int32_t sbuf_setup_common(struct acrn_vm *vm, uint16_t cpu_id, uint32_t sbuf_id, uint64_t *hva)
{
int32_t ret = 0;
@@ -90,6 +90,9 @@ int32_t sbuf_setup_common(__unused struct acrn_vm *vm, uint16_t cpu_id, uint32_t
case ACRN_SOCWATCH:
ret = sbuf_share_setup(cpu_id, sbuf_id, hva);
break;
+ case ACRN_ASYNCIO:
+ ret = init_asyncio(vm, hva);
+ break;
default:
pr_err("%s not support sbuf_id %d", __func__, sbuf_id);
ret = -1;
diff --git a/hypervisor/debug/sbuf.c b/hypervisor/debug/sbuf.c
index 8b8ec4605..178d6928d 100644
--- a/hypervisor/debug/sbuf.c
+++ b/hypervisor/debug/sbuf.c
@@ -17,7 +17,7 @@
int32_t sbuf_share_setup(uint16_t pcpu_id, uint32_t sbuf_id, uint64_t *hva)
{
- if ((pcpu_id >= get_pcpu_nums()) || (sbuf_id >= ACRN_SBUF_ID_MAX)) {
+ if ((pcpu_id >= get_pcpu_nums()) || (sbuf_id >= ACRN_SBUF_PER_PCPU_ID_MAX)) {
return -EINVAL;
}
@@ -33,7 +33,7 @@ void sbuf_reset(void)
uint16_t pcpu_id, sbuf_id;
for (pcpu_id = 0U; pcpu_id < get_pcpu_nums(); pcpu_id++) {
- for (sbuf_id = 0U; sbuf_id < ACRN_SBUF_ID_MAX; sbuf_id++) {
+ for (sbuf_id = 0U; sbuf_id < ACRN_SBUF_PER_PCPU_ID_MAX; sbuf_id++) {
per_cpu(sbuf, pcpu_id)[sbuf_id] = 0U;
}
}
diff --git a/hypervisor/dm/io_req.c b/hypervisor/dm/io_req.c
index afb695179..2ddecfe37 100644
--- a/hypervisor/dm/io_req.c
+++ b/hypervisor/dm/io_req.c
@@ -177,6 +177,23 @@ void set_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id, uint32_t state)
}
}
+int init_asyncio(struct acrn_vm *vm, uint64_t *hva)
+{
+ struct shared_buf *sbuf = (struct shared_buf *)hva;
+ int ret = -1;
+
+ stac();
+ if (sbuf != NULL) {
+ if (sbuf->magic == SBUF_MAGIC) {
+ vm->sw.asyncio_sbuf = sbuf;
+ ret = 0;
+ }
+ }
+ clac();
+
+ return ret;
+}
+
void set_hsm_notification_vector(uint32_t vector)
{
acrn_hsm_notification_vector = vector;
diff --git a/hypervisor/include/arch/x86/asm/guest/vm.h b/hypervisor/include/arch/x86/asm/guest/vm.h
index 62267af27..8ce702137 100644
--- a/hypervisor/include/arch/x86/asm/guest/vm.h
+++ b/hypervisor/include/arch/x86/asm/guest/vm.h
@@ -69,6 +69,7 @@ struct vm_sw_info {
struct sw_module_info acpi_info;
/* HVA to IO shared page */
void *io_shared_page;
+ void *asyncio_sbuf;
/* If enable IO completion polling mode */
bool is_polling_ioreq;
};
diff --git a/hypervisor/include/arch/x86/asm/per_cpu.h b/hypervisor/include/arch/x86/asm/per_cpu.h
index 1c7c83d80..dc21e5855 100644
--- a/hypervisor/include/arch/x86/asm/per_cpu.h
+++ b/hypervisor/include/arch/x86/asm/per_cpu.h
@@ -25,7 +25,7 @@ struct per_cpu_region {
uint8_t vmxon_region[PAGE_SIZE];
void *vmcs_run;
#ifdef HV_DEBUG
- struct shared_buf *sbuf[ACRN_SBUF_ID_MAX];
+ struct shared_buf *sbuf[ACRN_SBUF_PER_PCPU_ID_MAX];
char logbuf[LOG_MESSAGE_MAX_SIZE];
uint32_t npk_log_ref;
#endif
diff --git a/hypervisor/include/dm/io_req.h b/hypervisor/include/dm/io_req.h
index f64abf22c..d5ebd2268 100644
--- a/hypervisor/include/dm/io_req.h
+++ b/hypervisor/include/dm/io_req.h
@@ -291,6 +291,8 @@ void register_mmio_emulation_handler(struct acrn_vm *vm,
void unregister_mmio_emulation_handler(struct acrn_vm *vm,
uint64_t start, uint64_t end);
void deinit_emul_io(struct acrn_vm *vm);
+
+int init_asyncio(struct acrn_vm *vm, uint64_t *hva);
/**
* @}
*/
diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h
index 7c73ca070..a2293c1fa 100644
--- a/hypervisor/include/public/acrn_common.h
+++ b/hypervisor/include/public/acrn_common.h
@@ -746,7 +746,9 @@ enum {
ACRN_HVLOG,
ACRN_SEP,
ACRN_SOCWATCH,
- ACRN_SBUF_ID_MAX,
+ /* The sbuf with above ids are created each pcpu */
+ ACRN_SBUF_PER_PCPU_ID_MAX,
+ ACRN_ASYNCIO = 64,
};
/* Make sure sizeof(struct shared_buf) == SBUF_HEAD_SIZE */
--
2.25.1
completion of the the I/O request before return. But Virtio Spec
introduces introduces asynchronous IO with a new register in MMIO/PIO
space named NOTIFY, to be used for FE driver to notify BE driver, ACRN
hypervisor can emulate this register by sending a notification to vCPU
in Service VM side. This way, FE side can resume to work without waiting
for the full completion of BE side response.
Signed-off-by: Conghui <conghui.chen@...>
Acked-by: Eddie Dong <eddie.dong@...>
---
hypervisor/arch/x86/guest/vm.c | 1 +
hypervisor/common/sbuf.c | 5 ++++-
hypervisor/debug/sbuf.c | 4 ++--
hypervisor/dm/io_req.c | 17 +++++++++++++++++
hypervisor/include/arch/x86/asm/guest/vm.h | 1 +
hypervisor/include/arch/x86/asm/per_cpu.h | 2 +-
hypervisor/include/dm/io_req.h | 2 ++
hypervisor/include/public/acrn_common.h | 4 +++-
8 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c
index bdd31d3fa..c103d3a1f 100644
--- a/hypervisor/arch/x86/guest/vm.c
+++ b/hypervisor/arch/x86/guest/vm.c
@@ -758,6 +758,7 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v
/* Populate return VM handle */
*rtn_vm = vm;
vm->sw.io_shared_page = NULL;
+ vm->sw.asyncio_sbuf = NULL;
if ((vm_config->load_order == POST_LAUNCHED_VM)
&& ((vm_config->guest_flags & GUEST_FLAG_IO_COMPLETION_POLLING) != 0U)) {
/* enable IO completion polling mode per its guest flags in vm_config. */
diff --git a/hypervisor/common/sbuf.c b/hypervisor/common/sbuf.c
index 36ce9d2fa..73131fd53 100644
--- a/hypervisor/common/sbuf.c
+++ b/hypervisor/common/sbuf.c
@@ -79,7 +79,7 @@ uint32_t sbuf_put(struct shared_buf *sbuf, uint8_t *data)
return ele_size;
}
-int32_t sbuf_setup_common(__unused struct acrn_vm *vm, uint16_t cpu_id, uint32_t sbuf_id, uint64_t *hva)
+int32_t sbuf_setup_common(struct acrn_vm *vm, uint16_t cpu_id, uint32_t sbuf_id, uint64_t *hva)
{
int32_t ret = 0;
@@ -90,6 +90,9 @@ int32_t sbuf_setup_common(__unused struct acrn_vm *vm, uint16_t cpu_id, uint32_t
case ACRN_SOCWATCH:
ret = sbuf_share_setup(cpu_id, sbuf_id, hva);
break;
+ case ACRN_ASYNCIO:
+ ret = init_asyncio(vm, hva);
+ break;
default:
pr_err("%s not support sbuf_id %d", __func__, sbuf_id);
ret = -1;
diff --git a/hypervisor/debug/sbuf.c b/hypervisor/debug/sbuf.c
index 8b8ec4605..178d6928d 100644
--- a/hypervisor/debug/sbuf.c
+++ b/hypervisor/debug/sbuf.c
@@ -17,7 +17,7 @@
int32_t sbuf_share_setup(uint16_t pcpu_id, uint32_t sbuf_id, uint64_t *hva)
{
- if ((pcpu_id >= get_pcpu_nums()) || (sbuf_id >= ACRN_SBUF_ID_MAX)) {
+ if ((pcpu_id >= get_pcpu_nums()) || (sbuf_id >= ACRN_SBUF_PER_PCPU_ID_MAX)) {
return -EINVAL;
}
@@ -33,7 +33,7 @@ void sbuf_reset(void)
uint16_t pcpu_id, sbuf_id;
for (pcpu_id = 0U; pcpu_id < get_pcpu_nums(); pcpu_id++) {
- for (sbuf_id = 0U; sbuf_id < ACRN_SBUF_ID_MAX; sbuf_id++) {
+ for (sbuf_id = 0U; sbuf_id < ACRN_SBUF_PER_PCPU_ID_MAX; sbuf_id++) {
per_cpu(sbuf, pcpu_id)[sbuf_id] = 0U;
}
}
diff --git a/hypervisor/dm/io_req.c b/hypervisor/dm/io_req.c
index afb695179..2ddecfe37 100644
--- a/hypervisor/dm/io_req.c
+++ b/hypervisor/dm/io_req.c
@@ -177,6 +177,23 @@ void set_io_req_state(struct acrn_vm *vm, uint16_t vcpu_id, uint32_t state)
}
}
+int init_asyncio(struct acrn_vm *vm, uint64_t *hva)
+{
+ struct shared_buf *sbuf = (struct shared_buf *)hva;
+ int ret = -1;
+
+ stac();
+ if (sbuf != NULL) {
+ if (sbuf->magic == SBUF_MAGIC) {
+ vm->sw.asyncio_sbuf = sbuf;
+ ret = 0;
+ }
+ }
+ clac();
+
+ return ret;
+}
+
void set_hsm_notification_vector(uint32_t vector)
{
acrn_hsm_notification_vector = vector;
diff --git a/hypervisor/include/arch/x86/asm/guest/vm.h b/hypervisor/include/arch/x86/asm/guest/vm.h
index 62267af27..8ce702137 100644
--- a/hypervisor/include/arch/x86/asm/guest/vm.h
+++ b/hypervisor/include/arch/x86/asm/guest/vm.h
@@ -69,6 +69,7 @@ struct vm_sw_info {
struct sw_module_info acpi_info;
/* HVA to IO shared page */
void *io_shared_page;
+ void *asyncio_sbuf;
/* If enable IO completion polling mode */
bool is_polling_ioreq;
};
diff --git a/hypervisor/include/arch/x86/asm/per_cpu.h b/hypervisor/include/arch/x86/asm/per_cpu.h
index 1c7c83d80..dc21e5855 100644
--- a/hypervisor/include/arch/x86/asm/per_cpu.h
+++ b/hypervisor/include/arch/x86/asm/per_cpu.h
@@ -25,7 +25,7 @@ struct per_cpu_region {
uint8_t vmxon_region[PAGE_SIZE];
void *vmcs_run;
#ifdef HV_DEBUG
- struct shared_buf *sbuf[ACRN_SBUF_ID_MAX];
+ struct shared_buf *sbuf[ACRN_SBUF_PER_PCPU_ID_MAX];
char logbuf[LOG_MESSAGE_MAX_SIZE];
uint32_t npk_log_ref;
#endif
diff --git a/hypervisor/include/dm/io_req.h b/hypervisor/include/dm/io_req.h
index f64abf22c..d5ebd2268 100644
--- a/hypervisor/include/dm/io_req.h
+++ b/hypervisor/include/dm/io_req.h
@@ -291,6 +291,8 @@ void register_mmio_emulation_handler(struct acrn_vm *vm,
void unregister_mmio_emulation_handler(struct acrn_vm *vm,
uint64_t start, uint64_t end);
void deinit_emul_io(struct acrn_vm *vm);
+
+int init_asyncio(struct acrn_vm *vm, uint64_t *hva);
/**
* @}
*/
diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h
index 7c73ca070..a2293c1fa 100644
--- a/hypervisor/include/public/acrn_common.h
+++ b/hypervisor/include/public/acrn_common.h
@@ -746,7 +746,9 @@ enum {
ACRN_HVLOG,
ACRN_SEP,
ACRN_SOCWATCH,
- ACRN_SBUF_ID_MAX,
+ /* The sbuf with above ids are created each pcpu */
+ ACRN_SBUF_PER_PCPU_ID_MAX,
+ ACRN_ASYNCIO = 64,
};
/* Make sure sizeof(struct shared_buf) == SBUF_HEAD_SIZE */
--
2.25.1