After guest UOS is booted, the MMIO/IO access will cause that
it exits from VMX non-root env into ACRN hypervisor. Then the ACRN
hypervisor will inject virtual irq into the Linux guest with ACRN HSM
module. The ACRN_HSM handles this virtual irq (which is based on
HYPERVISOR_CALLBACK_VECTOR), parses corresponding IO request from shared
IOReq buffer and distributes it to different ioreq client. After the
ioreq emulation is finished, it will notify ACRN hypervisor and then
hypervisor will resume the execution of guest UOS.
ACRN HSM module will group some range of emulated MMIO/IO addr as
one ioreq_client. It will determine which ioreq_client should handle
the emulated MMIO/IO request based on the address and then dispatch it
into the ioreq_client thread. User-space device model will create one
default ioreq_client, which is used to handle the emulated MMIO/IO in
user-space thread.
Add ioreq service and defines IOReq APIs like below:
int acrn_ioreq_create_client(unsigned long vmid,
ioreq_handler_t handler,
void *client_priv,
char *name);
void acrn_ioreq_destroy_client(int client_id);
int acrn_ioreq_add_iorange(int client_id, enum request_type type,
long start, long end);
int acrn_ioreq_del_iorange(int client_id, enum request_type type,
long start, long end);
struct acrn_request * acrn_ioreq_get_reqbuf(int client_id);
int acrn_ioreq_attach_client(int client_id);
int acrn_ioreq_complete_request(int client_id);
Co-developed-by: Jason Chen CJ
Signed-off-by: Jason Chen CJ
Co-developed-by: Yin FengWei
Signed-off-by: Yin FengWei
Co-developed-by: Liu Shuo
Signed-off-by: Liu Shuo
Signed-off-by: Zhao Yakui
---
drivers/staging/acrn/Makefile | 3 +-
drivers/staging/acrn/acrn_dev.c | 58 ++
drivers/staging/acrn/acrn_drv_internal.h | 33 ++
drivers/staging/acrn/acrn_ioreq.c | 937 ++
drivers/staging/acrn/acrn_vm_mngt.c | 7 +
include/linux/acrn/acrn_drv.h | 102
include/uapi/linux/acrn/acrn_common_def.h | 176 ++
include/uapi/linux/acrn/acrn_ioctl_defs.h | 20 +
8 files changed, 1335 insertions(+), 1 deletion(-)
create mode 100644 drivers/staging/acrn/acrn_ioreq.c
diff --git a/drivers/staging/acrn/Makefile b/drivers/staging/acrn/Makefile
index ec62afe..a381944 100644
--- a/drivers/staging/acrn/Makefile
+++ b/drivers/staging/acrn/Makefile
@@ -3,4 +3,5 @@ acrn-y := acrn_dev.o \
acrn_hypercall.o \
acrn_vm_mngt.o \
acrn_mm.o \
- acrn_mm_hugetlb.o
+ acrn_mm_hugetlb.o \
+ acrn_ioreq.o
diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 1476817..28258fb 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include "acrn_hypercall.h"
#include "acrn_drv_internal.h"
@@ -59,6 +60,9 @@ int acrn_dev_open(struct inode *inodep, struct file *filep)
INIT_HLIST_HEAD(>hugepage_hlist[i]);
mutex_init(>hugepage_lock);
+ INIT_LIST_HEAD(>ioreq_client_list);
+ spin_lock_init(>ioreq_client_lock);
+
write_lock_bh(_vm_list_lock);
vm_list_add(>list);
write_unlock_bh(_vm_list_lock);
@@ -131,9 +135,20 @@ long acrn_dev_ioctl(struct file *filep,
vm->vmid = created_vm->vmid;
atomic_set(>vcpu_num, 0);
+ ret = acrn_ioreq_init(vm, created_vm->req_buf);
+ if (ret < 0)
+ goto ioreq_buf_fail;
+
pr_info("acrn: VM %d created\n", created_vm->vmid);
kfree(created_vm);
break;
+
+ioreq_buf_fail:
+ hcall_destroy_vm(created_vm->vmid);
+ vm->vmid = ACRN_INVALID_VMID;
+ kfree(created_vm);
+ break;
+
}
case IC_START_VM: {
@@ -364,6 +379,47 @@ long acrn_dev_ioctl(struct file *filep,
break;
}
+ case IC_CREATE_IOREQ_CLIENT: {
+ int client_id;
+
+ client_id = acrn_ioreq_create_fallback_client(vm->vmid,
+ "acrndm");
+ if (client_id < 0)
+ return -EFAULT;
+ return client_id;
+ }
+
+ case IC_DESTROY_IOREQ_CLIENT: {
+ int client = ioctl_param;
+
+ acrn_ioreq_destroy_client(client);
+ break;
+ }
+
+ case IC_ATTACH_IOREQ_CLIENT: {
+ int client = ioctl_param;
+
+ return acrn_ioreq_attach_client(client);
+ }
+
+ case IC_NOTIFY_REQUEST_FINISH: {
+ struct ioreq_notify notify;
+
+ if (copy_from_user(, (void *)ioctl_param,
+ sizeof(notify)))
+ return -EFAULT;
+
+ ret =