Re: [RFC PATCH 11/15] drivers/acrn: add the support of handling emulated ioreq

2019-08-18 Thread Zhao, Yakui




On 2019年08月16日 21:39, Dan Carpenter wrote:

On Fri, Aug 16, 2019 at 10:25:52AM +0800, Zhao Yakui wrote:

+int acrn_ioreq_create_client(unsigned short vmid,
+ioreq_handler_t handler,
+void *client_priv,
+char *name)
+{
+   struct acrn_vm *vm;
+   struct ioreq_client *client;
+   int client_id;
+
+   might_sleep();
+
+   vm = find_get_vm(vmid);
+   if (unlikely(!vm || !vm->req_buf)) {
+   pr_err("acrn-ioreq: failed to find vm from vmid %d\n", vmid);
+   put_vm(vm);
+   return -EINVAL;
+   }
+
+   client_id = alloc_client();
+   if (unlikely(client_id < 0)) {
+   pr_err("acrn-ioreq: vm[%d] failed to alloc ioreq client\n",
+  vmid);
+   put_vm(vm);
+   return -EINVAL;
+   }
+
+   client = acrn_ioreq_get_client(client_id);
+   if (unlikely(!client)) {
+   pr_err("failed to get the client.\n");
+   put_vm(vm);
+   return -EINVAL;


Do we need to clean up the alloc_client() allocation?


Thanks for the review.

The function of acrn_iocreq_get_client is used to return the client for 
the given client_id. (The ref_count of client is also added). If it is 
NULL, it indicates that it is already released in another place.


In the function of acrn_ioreq_create_client, we don't need to clean up 
the alloc_client as it always exists in course of creating_client.




regards,
dan carpenter


+   }
+
+   if (handler) {
+   client->handler = handler;
+   client->acrn_create_kthread = true;
+   }
+
+   client->ref_vm = vm;
+   client->vmid = vmid;
+   client->client_priv = client_priv;
+   if (name)
+   strncpy(client->name, name, sizeof(client->name) - 1);
+   rwlock_init(>range_lock);
+   INIT_LIST_HEAD(>range_list);
+   init_waitqueue_head(>wq);
+
+   /* When it is added to ioreq_client_list, the refcnt is increased */
+   spin_lock_bh(>ioreq_client_lock);
+   list_add(>list, >ioreq_client_list);
+   spin_unlock_bh(>ioreq_client_lock);
+
+   pr_info("acrn-ioreq: created ioreq client %d\n", client_id);
+
+   return client_id;
+}




Re: [RFC PATCH 11/15] drivers/acrn: add the support of handling emulated ioreq

2019-08-16 Thread Dan Carpenter
On Fri, Aug 16, 2019 at 10:25:52AM +0800, Zhao Yakui wrote:
> +int acrn_ioreq_create_client(unsigned short vmid,
> +  ioreq_handler_t handler,
> +  void *client_priv,
> +  char *name)
> +{
> + struct acrn_vm *vm;
> + struct ioreq_client *client;
> + int client_id;
> +
> + might_sleep();
> +
> + vm = find_get_vm(vmid);
> + if (unlikely(!vm || !vm->req_buf)) {
> + pr_err("acrn-ioreq: failed to find vm from vmid %d\n", vmid);
> + put_vm(vm);
> + return -EINVAL;
> + }
> +
> + client_id = alloc_client();
> + if (unlikely(client_id < 0)) {
> + pr_err("acrn-ioreq: vm[%d] failed to alloc ioreq client\n",
> +vmid);
> + put_vm(vm);
> + return -EINVAL;
> + }
> +
> + client = acrn_ioreq_get_client(client_id);
> + if (unlikely(!client)) {
> + pr_err("failed to get the client.\n");
> + put_vm(vm);
> + return -EINVAL;

Do we need to clean up the alloc_client() allocation?

regards,
dan carpenter

> + }
> +
> + if (handler) {
> + client->handler = handler;
> + client->acrn_create_kthread = true;
> + }
> +
> + client->ref_vm = vm;
> + client->vmid = vmid;
> + client->client_priv = client_priv;
> + if (name)
> + strncpy(client->name, name, sizeof(client->name) - 1);
> + rwlock_init(>range_lock);
> + INIT_LIST_HEAD(>range_list);
> + init_waitqueue_head(>wq);
> +
> + /* When it is added to ioreq_client_list, the refcnt is increased */
> + spin_lock_bh(>ioreq_client_lock);
> + list_add(>list, >ioreq_client_list);
> + spin_unlock_bh(>ioreq_client_lock);
> +
> + pr_info("acrn-ioreq: created ioreq client %d\n", client_id);
> +
> + return client_id;
> +}



[RFC PATCH 11/15] drivers/acrn: add the support of handling emulated ioreq

2019-08-15 Thread Zhao Yakui
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 =