Re: [RFC PATCH 09/15] drivers/acrn: add passthrough device support

2019-09-01 Thread Zhao, Yakui



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

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

+   case IC_ASSIGN_PTDEV: {
+   unsigned short bdf;
+
+   if (copy_from_user(, (void *)ioctl_param,


This casting is ugly and you also need a __user tag for Sparse.  Do
something like "void __user *p = ioctl_param;"


Sure. The __user tag will be added for the ioctl_param parameter of 
copy_from/to_user.





+  sizeof(unsigned short)))
+   return -EFAULT;
+
+   ret = hcall_assign_ptdev(vm->vmid, bdf);
+   if (ret < 0) {
+   pr_err("acrn: failed to assign ptdev!\n");
+   return -EFAULT;


Preserve the error code.  "return ret;".

Ok. It will preserver the err code.




+   }
+   break;
+   }
+   case IC_DEASSIGN_PTDEV: {
+   unsigned short bdf;
+
+   if (copy_from_user(, (void *)ioctl_param,
+  sizeof(unsigned short)))
+   return -EFAULT;
+
+   ret = hcall_deassign_ptdev(vm->vmid, bdf);
+   if (ret < 0) {
+   pr_err("acrn: failed to deassign ptdev!\n");
+   return -EFAULT;
+   }
+   break;
+   }
+
+   case IC_SET_PTDEV_INTR_INFO: {
+   struct ic_ptdev_irq ic_pt_irq;
+   struct hc_ptdev_irq *hc_pt_irq;
+
+   if (copy_from_user(_pt_irq, (void *)ioctl_param,
+  sizeof(ic_pt_irq)))
+   return -EFAULT;
+
+   hc_pt_irq = kmalloc(sizeof(*hc_pt_irq), GFP_KERNEL);
+   if (!hc_pt_irq)
+   return -ENOMEM;
+
+   memcpy(hc_pt_irq, _pt_irq, sizeof(*hc_pt_irq));


Use memdup_user().


OK. The memdup_user will be used.




+
+   ret = hcall_set_ptdev_intr_info(vm->vmid,
+   virt_to_phys(hc_pt_irq));
+   kfree(hc_pt_irq);
+   if (ret < 0) {
+   pr_err("acrn: failed to set intr info for ptdev!\n");
+   return -EFAULT;
+   }
+
+   break;
+   }


regards,
dan carpenter


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 08/15] drivers/acrn: add VM memory management for ACRN char device

2019-08-19 Thread Zhao, Yakui



On 2019年08月19日 15:39, Dan Carpenter wrote:

On Mon, Aug 19, 2019 at 01:32:54PM +0800, Zhao, Yakui wrote:

In fact as this driver is mainly used for embedded IOT usage, it doesn't
handle the complex cleanup when such error is encountered. Instead the clean
up is handled in free_guest_vm.


A use after free here seems like a potential security problem.  Security
matters for IoT...  :(


Thanks for pointing out the issue.
The cleanup will be considered carefully.



regards,
dan carpenter


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 15/15] drivers/acrn: add the support of offline SOS cpu

2019-08-19 Thread Zhao, Yakui



On 2019年08月19日 18:34, Dan Carpenter wrote:

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

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 0602125..6868003 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -588,6 +588,41 @@ static const struct file_operations fops = {
  #define SUPPORT_HV_API_VERSION_MAJOR  1
  #define SUPPORT_HV_API_VERSION_MINOR  0
  
+static ssize_t

+offline_cpu_store(struct device *dev,
+   struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+#ifdef CONFIG_X86
+   u64 cpu, lapicid;
+
+   if (kstrtoull(buf, 0, ) < 0)
+   return -EINVAL;




Thanks for the review.

Make sense.
The error code will be preserved.


Preserve the error code.

ret = kstrtoull(buf, 0, );
if (ret)
return ret;






+
+   if (cpu_possible(cpu)) {


You can't pass unchecked cpu values to cpu_possible() or it results in
an out of bounds read if cpu is >= than nr_cpu_ids.



OK. It will add the check of "cpu < num_possibles_cpu()" to avoid the 
out of bounds.



regards,
dan carpenter


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 00/15] acrn: add the ACRN driver module

2019-08-18 Thread Zhao, Yakui



On 2019年08月19日 13:25, Greg KH wrote:

On Mon, Aug 19, 2019 at 09:44:25AM +0800, Zhao, Yakui wrote:



On 2019年08月16日 14:39, Borislav Petkov wrote:

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

The first three patches are the changes under x86/acrn, which adds the
required APIs for the driver and reports the X2APIC caps.
The remaining patches add the ACRN driver module, which accepts the ioctl
from user-space and then communicate with the low-level ACRN hypervisor
by using hypercall.


I have a problem with that: you're adding interfaces to arch/x86/ and
its users go into staging. Why? Why not directly put the driver where
it belongs, clean it up properly and submit it like everything else is
submitted?


Thanks for your reply and the concern.

After taking a look at several driver examples(gma500, android), it seems
that they are firstly added into drivers/staging/XXX and then moved to
drivers/XXX after the driver becomes mature.
So we refer to this method to upstream ACRN driver part.


Those two examples are probably the worst examples to ever look at :)

The code quality of those submissions was horrible, gma500 took a very
long time to clean up and there are parts of the android code that are
still in staging to this day.


If the new driver can also be added by skipping the staging approach,
we will refine it and then submit it in normal process.


That is the normal process, staging should not be needed at all for any
code.  It is a fall-back for when the company involved has no idea of
how to upstream their code, which should NOT be the case here.


Thanks for your explanation.

OK. We will submit it in normal process.



thanks,

greg k-h


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 08/15] drivers/acrn: add VM memory management for ACRN char device

2019-08-18 Thread Zhao, Yakui



On 2019年08月16日 20:58, Dan Carpenter wrote:

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

+int hugepage_map_guest(struct acrn_vm *vm, struct vm_memmap *memmap)
+{
+   struct page *page = NULL, *regions_buf_pg = NULL;
+   unsigned long len, guest_gpa, vma;
+   struct vm_memory_region *region_array;
+   struct set_regions *regions;
+   int max_size = PAGE_SIZE / sizeof(struct vm_memory_region);
+   int ret;
+
+   if (!vm || !memmap)
+   return -EINVAL;
+
+   len = memmap->len;
+   vma = memmap->vma_base;
+   guest_gpa = memmap->gpa;
+
+   /* prepare set_memory_regions info */
+   regions_buf_pg = alloc_page(GFP_KERNEL);
+   if (!regions_buf_pg)
+   return -ENOMEM;
+
+   regions = kzalloc(sizeof(*regions), GFP_KERNEL);
+   if (!regions) {
+   __free_page(regions_buf_pg);
+   return -ENOMEM;


It's better to do a goto err_free_regions_buf here.  More comments
below.


+   }
+   regions->mr_num = 0;
+   regions->vmid = vm->vmid;
+   regions->regions_gpa = page_to_phys(regions_buf_pg);
+   region_array = page_to_virt(regions_buf_pg);
+
+   while (len > 0) {
+   unsigned long vm0_gpa, pagesize;
+
+   ret = get_user_pages_fast(vma, 1, 1, );
+   if (unlikely(ret != 1) || (!page)) {
+   pr_err("failed to pin huge page!\n");
+   ret = -ENOMEM;
+   goto err;


goto err is a red flag.  It's better if error labels do one specific
named thing like:

err_regions:
kfree(regions);
err_free_regions_buf:
__free_page(regions_buf_pg);

We should unwind in the opposite/mirror order from how things were
allocated.  Then we can remove the if statements in the error handling.


Thanks for the review.

Will follow your suggestion to unwind the error handling.



In this situation, say the user triggers an -EFAULT in
get_user_pages_fast() in the second iteration through the loop.  That
means that "page" is the non-NULL page from the previous iteration.  We
have already added it to add_guest_map().  But now we're freeing it
without removing it from the map so probably it leads to a use after
free.

The best way to write the error handling in a loop like this is to
clean up the partial iteration that has succeed (nothing here), and then
unwind all the successful iterations at the bottom of the function.
"goto unwind_loop;"



In theory we should cleanup the previous success iteration if it 
encounters one error in the current iteration.

But it will be quite complex to cleanup up the previous iteration.
call the set_memory_regions for MR_DEL op.
call the remove_guest_map for the added hash item
call the put_page for returned page in get_user_pages_fast.

In fact as this driver is mainly used for embedded IOT usage, it doesn't 
handle the complex cleanup when such error is encountered. Instead the 
clean up is handled in free_guest_vm.



+   }
+
+   vm0_gpa = page_to_phys(page);
+   pagesize = PAGE_SIZE << compound_order(page);
+
+   ret = add_guest_map(vm, vm0_gpa, guest_gpa, pagesize);
+   if (ret < 0) {
+   pr_err("failed to add memseg for huge page!\n");
+   goto err;


So then here, it would be:

pr_err("failed to add memseg for huge page!\n");
put_page(page);
goto unwind_loop;

regards,
dan carpenter


+   }
+
+   /* fill each memory region into region_array */
+   region_array[regions->mr_num].type = MR_ADD;
+   region_array[regions->mr_num].gpa = guest_gpa;
+   region_array[regions->mr_num].vm0_gpa = vm0_gpa;
+   region_array[regions->mr_num].size = pagesize;
+   region_array[regions->mr_num].prot =
+   (MEM_TYPE_WB & MEM_TYPE_MASK) |
+   (memmap->prot & MEM_ACCESS_RIGHT_MASK);
+   regions->mr_num++;
+   if (regions->mr_num == max_size) {
+   pr_debug("region buffer full, set & renew regions!\n");
+   ret = set_memory_regions(regions);
+   if (ret < 0) {
+   pr_err("failed to set regions,ret=%d!\n", ret);
+   goto err;
+   }
+   regions->mr_num = 0;
+   }
+
+   len -= pagesize;
+   vma += pagesize;
+   guest_gpa += pagesize;
+   }
+
+   ret = set_memory_regions(regions);
+   if (ret < 0) {
+   pr_err("failed to set regions, ret=%d!\n",

Re: [RFC PATCH 10/15] drivers/acrn: add interrupt injection support

2019-08-18 Thread Zhao, Yakui



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

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

+   case IC_VM_INTR_MONITOR: {
+   struct page *page;
+
+   ret = get_user_pages_fast(ioctl_param, 1, 1, );
+   if (unlikely(ret != 1) || !page) {


Not required.


Do you mean that it is enough to check the condition of "ret != 1"?
OK. It will be removed.





+   pr_err("acrn-dev: failed to pin intr hdr buffer!\n");
+   return -ENOMEM;
+   }
+
+   ret = hcall_vm_intr_monitor(vm->vmid, page_to_phys(page));
+   if (ret < 0) {
+   pr_err("acrn-dev: monitor intr data err=%ld\n", ret);
+   return -EFAULT;
+   }
+   break;
+   }
+


regards,
dan carpenter


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


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;
+}



___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 04/15] drivers/acrn: add the basic framework of acrn char device driver

2019-08-18 Thread Zhao, Yakui



On 2019年08月16日 15:05, Greg KH wrote:

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

ACRN hypervisor service module is the important middle layer that allows
the Linux kernel to communicate with the ACRN hypervisor. It includes
the management of virtualized CPU/memory/device/interrupt for other ACRN
guest. The user-space applications can use the provided ACRN ioctls to
interact with ACRN hypervisor through different hypercalls.

Add one basic framework firstly and the following patches will
add the corresponding implementations, which includes the management of
virtualized CPU/memory/interrupt and the emulation of MMIO/IO/PCI access.
The device file of /dev/acrn_hsm can be accessed in user-space to
communicate with ACRN module.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Jack Ren 
Signed-off-by: Jack Ren 
Co-developed-by: Mingqiang Chi 
Signed-off-by: Mingqiang Chi 
Co-developed-by: Liu Shuo 
Signed-off-by: Liu Shuo 
Signed-off-by: Zhao Yakui 
---
  drivers/staging/Kconfig |   2 +


Also, your subject line for all of these patches are wrong, it is not
drivers/acrn :(


Thanks for the pointing out it.

It will be fixed.



And you forgot to cc: the staging maintainer :(


Do you mean that the maintainer of staging subsystem is also added in 
the patch commit log?





As I have said with NUMEROUS Intel patches in the past, I now refuse to
take patches from you all WITHOUT having it signed-off-by someone from
the Intel "OTC" group (or whatever the Intel Linux group is called these
days).  They are a resource you can not ignore, and if you do, you just
end up making the rest of the kernel community grumpy by having us do
their work for them :(

Please work with them.


OK. I will work with some peoples in OTC group to prepare the better 
ACRN driver.




greg k-h


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 00/15] acrn: add the ACRN driver module

2019-08-18 Thread Zhao, Yakui



On 2019年08月16日 15:03, Greg KH wrote:

On Fri, Aug 16, 2019 at 08:39:25AM +0200, Borislav Petkov wrote:

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

The first three patches are the changes under x86/acrn, which adds the
required APIs for the driver and reports the X2APIC caps.
The remaining patches add the ACRN driver module, which accepts the ioctl
from user-space and then communicate with the low-level ACRN hypervisor
by using hypercall.


I have a problem with that: you're adding interfaces to arch/x86/ and
its users go into staging. Why? Why not directly put the driver where
it belongs, clean it up properly and submit it like everything else is
submitted?

I don't want to have stuff in arch/x86/ which is used solely by code in
staging and the latter is lingering there indefinitely because no one is
cleaning it up...


I agree, stuff in drivers/staging/ must be self-contained, with no
changes outside of the code's subdirectory needed in order for it to
work.  That way it is trivial for us to delete it when it never gets
cleaned up :)


Thanks for pointing out the rule of drivers/staging.
The acrn staging driver is one self-contained driver. But it has some 
dependency on arch/x86/acrn and need to call the APIs in arch/x86/acrn.


If there is no driver,  the API without user had better not be added.
If API is not added,  the driver can't be compiled correctly.
The ACRN driver is one new driver. Maybe it will have some bugs and not 
be mature. So we want to add the driver as the staging.


What is the better approach to handle such scenario?



You never say _why_ this should go into drivers/staging/, nor do you
have a TODO file like all other staging code that explains exactly what
needs to be done to get it out of there.


Ok. The TODO file will be added in next version.




thanks,

greg k-h


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RFC PATCH 00/15] acrn: add the ACRN driver module

2019-08-18 Thread Zhao, Yakui



On 2019年08月16日 14:39, Borislav Petkov wrote:

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

The first three patches are the changes under x86/acrn, which adds the
required APIs for the driver and reports the X2APIC caps.
The remaining patches add the ACRN driver module, which accepts the ioctl
from user-space and then communicate with the low-level ACRN hypervisor
by using hypercall.


I have a problem with that: you're adding interfaces to arch/x86/ and
its users go into staging. Why? Why not directly put the driver where
it belongs, clean it up properly and submit it like everything else is
submitted?


Thanks for your reply and the concern.

After taking a look at several driver examples(gma500, android), it 
seems that they are firstly added into drivers/staging/XXX and then 
moved to drivers/XXX after the driver becomes mature.

So we refer to this method to upstream ACRN driver part.

If the new driver can also be added by skipping the staging approach,
we will refine it and then submit it in normal process.


I don't want to have stuff in arch/x86/ which is used solely by code in
staging and the latter is lingering there indefinitely because no one is
cleaning it up...



The ACRN driver will be the only user of the added APIs in x86/acrn. 
Without the APIs in x86/acrn, the driver can't add the driver-specifc 
upcall notification ISR or call the hypercall.


Not sure whether it can be sent in two patch sets?
The first is to add the required APIs for ACRN driver.
The second is to add the ACRN driver

Thanks
   Yakui
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC PATCH 10/15] drivers/acrn: add interrupt injection support

2019-08-15 Thread Zhao Yakui
After ACRN devicemodel finishes the emulation of trapped MMIO/IO/PCICFG
access, it needs to inject one interrupt to notify that the guest can be
resumed.
IC_SET_IRQLINE: This is used to inject virtual IOAPIC gsi interrupt
IC_INJECT_MSI: Inject virtual MSI interrupt to guest OS
IC_VM_INTR_MONITOR: monitor the interrupt info for one guest OS

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Mingqiang Chi 
Signed-off-by: Mingqiang Chi 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/acrn_dev.c   | 48 +++
 drivers/staging/acrn/acrn_vm_mngt.c   | 28 ++
 include/linux/acrn/acrn_drv.h | 12 
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 18 
 4 files changed, 106 insertions(+)

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 28bbd78..1476817 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -316,6 +317,53 @@ long acrn_dev_ioctl(struct file *filep,
break;
}
 
+   case IC_SET_IRQLINE: {
+   ret = hcall_set_irqline(vm->vmid, ioctl_param);
+   if (ret < 0) {
+   pr_err("acrn: failed to set irqline!\n");
+   return -EFAULT;
+   }
+   break;
+   }
+
+   case IC_INJECT_MSI: {
+   struct acrn_msi_entry *msi;
+
+   msi = kmalloc(sizeof(*msi), GFP_KERNEL);
+   if (!msi)
+   return -ENOMEM;
+
+   if (copy_from_user(msi, (void *)ioctl_param, sizeof(*msi))) {
+   kfree(msi);
+   return -EFAULT;
+   }
+
+   ret = hcall_inject_msi(vm->vmid, virt_to_phys(msi));
+   kfree(msi);
+   if (ret < 0) {
+   pr_err("acrn: failed to inject!\n");
+   return -EFAULT;
+   }
+   break;
+   }
+
+   case IC_VM_INTR_MONITOR: {
+   struct page *page;
+
+   ret = get_user_pages_fast(ioctl_param, 1, 1, );
+   if (unlikely(ret != 1) || !page) {
+   pr_err("acrn-dev: failed to pin intr hdr buffer!\n");
+   return -ENOMEM;
+   }
+
+   ret = hcall_vm_intr_monitor(vm->vmid, page_to_phys(page));
+   if (ret < 0) {
+   pr_err("acrn-dev: monitor intr data err=%ld\n", ret);
+   return -EFAULT;
+   }
+   break;
+   }
+
default:
pr_warn("Unknown IOCTL 0x%x\n", ioctl_num);
ret = -EFAULT;
diff --git a/drivers/staging/acrn/acrn_vm_mngt.c 
b/drivers/staging/acrn/acrn_vm_mngt.c
index 9c6dd6d..4287595 100644
--- a/drivers/staging/acrn/acrn_vm_mngt.c
+++ b/drivers/staging/acrn/acrn_vm_mngt.c
@@ -11,8 +11,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 
 #include "acrn_hypercall.h"
 #include "acrn_drv_internal.h"
@@ -72,3 +74,29 @@ int acrn_vm_destroy(struct acrn_vm *vm)
vm->vmid = ACRN_INVALID_VMID;
return 0;
 }
+
+int acrn_inject_msi(unsigned short vmid, unsigned long msi_addr,
+   unsigned long msi_data)
+{
+   struct acrn_msi_entry *msi;
+   int ret;
+
+   msi = kzalloc(sizeof(*msi), GFP_KERNEL);
+
+   if (!msi)
+   return -ENOMEM;
+
+   /* msi_addr: addr[19:12] with dest vcpu id */
+   /* msi_data: data[7:0] with vector */
+   msi->msi_addr = msi_addr;
+   msi->msi_data = msi_data;
+   ret = hcall_inject_msi(vmid, virt_to_phys(msi));
+   kfree(msi);
+   if (ret < 0) {
+   pr_err("acrn: failed to inject MSI for vmid %d, msi_addr %lx 
msi_data%lx!\n",
+  vmid, msi_addr, msi_data);
+   return -EFAULT;
+   }
+   return 0;
+}
+EXPORT_SYMBOL_GPL(acrn_inject_msi);
diff --git a/include/linux/acrn/acrn_drv.h b/include/linux/acrn/acrn_drv.h
index 62b03f0..bcdfcaf 100644
--- a/include/linux/acrn/acrn_drv.h
+++ b/include/linux/acrn/acrn_drv.h
@@ -83,4 +83,16 @@ extern int acrn_del_memory_region(unsigned short vmid, 
unsigned long gpa,
 extern int acrn_write_protect_page(unsigned short vmid, unsigned long gpa,
   unsigned char set);
 
+/**
+ * acrn_inject_msi() - inject MSI interrupt to guest
+ *
+ * @vmid: guest vmid
+ * @msi_addr: MSI addr matches MSI spec
+ * @msi_data: MSI data matches MSI spec
+ *
+ * Return: 0 on success, <0 on error
+ */
+extern int acrn_inject_msi(unsigned short vmid, unsigned long msi_addr,
+  unsigned long msi_data);
+
 #endif
diff --git a/include/uapi/linux/acr

[RFC PATCH 14/15] drivers/acrn: add the support of irqfd and eventfd

2019-08-15 Thread Zhao Yakui
The ioventfd/irqfd based on eventfd is one mechanism that is widely used
to implement virtio kernel backend driver. After the ioreq is trigged from
virtio front driver, the eventfd_signal is called to notify the eventfd so
that the virtio kernel backend driver is waked up to handle the request.
After it is done, it will wake up the irqfd to inject the interrupt to
virtio front driver.

Each ioeventfd registered by userspace can map a PIO/MMIO range of the
guest to eventfd, and response to signal the eventfd when get the
in-range IO write from guest. Then the other side of eventfd can be
notified to process the IO request.

As we only use the ioeventfd to listen virtqueue's kick register, some
limitations are added:
  1) Length support can only be 1, 2, 4 or 8
  2) Only support write operation, read will get 0
  3) Same address, shorter length writing can be handled with the
 integral data matching

The irqfd based on eventfd provides a pipe for injecting guest interrupt
through a file description writing operation. Each irqfd registered by
userspace can map a interrupt of the guest to eventfd, and a writing
operation on one side of the eventfd will trigger the interrupt injection
on acrn_hsm side.

Co-developed-by: Shuo Liu 
Signed-off-by: Shuo Liu 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/Makefile |   4 +-
 drivers/staging/acrn/acrn_dev.c   |  19 ++
 drivers/staging/acrn/acrn_drv_internal.h  |  10 +
 drivers/staging/acrn/acrn_ioeventfd.c | 407 ++
 drivers/staging/acrn/acrn_irqfd.c | 339 +
 drivers/staging/acrn/acrn_vm_mngt.c   |   9 +-
 include/uapi/linux/acrn/acrn_ioctl_defs.h |  25 ++
 7 files changed, 811 insertions(+), 2 deletions(-)
 create mode 100644 drivers/staging/acrn/acrn_ioeventfd.c
 create mode 100644 drivers/staging/acrn/acrn_irqfd.c

diff --git a/drivers/staging/acrn/Makefile b/drivers/staging/acrn/Makefile
index a381944..f8d8ee2 100644
--- a/drivers/staging/acrn/Makefile
+++ b/drivers/staging/acrn/Makefile
@@ -4,4 +4,6 @@ acrn-y := acrn_dev.o \
  acrn_vm_mngt.o \
  acrn_mm.o \
  acrn_mm_hugetlb.o \
- acrn_ioreq.o
+ acrn_ioreq.o  \
+ acrn_ioeventfd.o \
+ acrn_irqfd.o
diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index ef0ec50..0602125 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -141,6 +141,8 @@ long acrn_dev_ioctl(struct file *filep,
if (ret < 0)
goto ioreq_buf_fail;
 
+   acrn_ioeventfd_init(vm->vmid);
+   acrn_irqfd_init(vm->vmid);
pr_info("acrn: VM %d created\n", created_vm->vmid);
kfree(created_vm);
break;
@@ -506,6 +508,23 @@ long acrn_dev_ioctl(struct file *filep,
 
break;
}
+   case IC_EVENT_IOEVENTFD: {
+   struct acrn_ioeventfd args;
+
+   if (copy_from_user(, (void *)ioctl_param, sizeof(args)))
+   return -EFAULT;
+   ret = acrn_ioeventfd_config(vm->vmid, );
+   break;
+   }
+
+   case IC_EVENT_IRQFD: {
+   struct acrn_irqfd args;
+
+   if (copy_from_user(, (void *)ioctl_param, sizeof(args)))
+   return -EFAULT;
+   ret = acrn_irqfd_config(vm->vmid, );
+   break;
+   }
 
default:
pr_warn("Unknown IOCTL 0x%x\n", ioctl_num);
diff --git a/drivers/staging/acrn/acrn_drv_internal.h 
b/drivers/staging/acrn/acrn_drv_internal.h
index 7813387..b9ded9a 100644
--- a/drivers/staging/acrn/acrn_drv_internal.h
+++ b/drivers/staging/acrn/acrn_drv_internal.h
@@ -173,4 +173,14 @@ void acrn_ioreq_driver_init(void);
 void acrn_ioreq_clear_request(struct acrn_vm *vm);
 int acrn_ioreq_distribute_request(struct acrn_vm *vm);
 
+/* ioeventfd APIs */
+int acrn_ioeventfd_init(unsigned short vmid);
+int acrn_ioeventfd_config(unsigned short vmid, struct acrn_ioeventfd *args);
+void acrn_ioeventfd_deinit(unsigned short vmid);
+
+/* irqfd APIs */
+int acrn_irqfd_init(unsigned short vmid);
+int acrn_irqfd_config(unsigned short vmid, struct acrn_irqfd *args);
+void acrn_irqfd_deinit(unsigned short vmid);
+
 #endif
diff --git a/drivers/staging/acrn/acrn_ioeventfd.c 
b/drivers/staging/acrn/acrn_ioeventfd.c
new file mode 100644
index 000..b330625
--- /dev/null
+++ b/drivers/staging/acrn/acrn_ioeventfd.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * ACRN hyperviosr service module (SRV): ioeventfd based on eventfd
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Liu Shuo 
+ * Zhao Yakui 
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "acrn_drv_internal.h"
+#include "acrn_hy

[RFC PATCH 08/15] drivers/acrn: add VM memory management for ACRN char device

2019-08-15 Thread Zhao Yakui
In order to launch the ACRN guest system, it needs to setup the mapping
between GPA (guest physical address) and HPA (host physical address).
This is based on memory virtualization and configured in EPT table.
The ioctl related with memory management is added and then the hypercall
is called so that the ACRN hypervisor can help to setup the memory
mapping for ACRN guest.
The 1G/2M huge page is used to optimize the EPT table for guest VM. This
will simplify the memory allocation and also optimizes the TLB.
For the MMIO mapping: It can support 4K/2M page.

IC_SET_MEMSEG: This is used to setup the memory mapping for the memory
of guest system by using hugetlb(Guest physical address and host virtual
addr).It is also used to setup the device MMIO mapping for PCI device.
IC_UNSET_MEMSEG: This is used to remove the device MMIO mapping for PCI
device. This is used with updating the MMIO mapping together. As the
acrn hypervisor is mainly used for embedded IOT device, it doesn't support
the dynamica removal of memory mapping.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Li, Fei 
Signed-off-by: Li, Fei 
Co-developed-by: Liu Shuo 
Signed-off-by: Liu Shuo 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/Makefile |   4 +-
 drivers/staging/acrn/acrn_dev.c   |  27 +++
 drivers/staging/acrn/acrn_drv_internal.h  |  90 +++---
 drivers/staging/acrn/acrn_mm.c| 227 
 drivers/staging/acrn/acrn_mm_hugetlb.c| 281 ++
 drivers/staging/acrn/acrn_vm_mngt.c   |   2 +
 include/linux/acrn/acrn_drv.h |  86 +
 include/uapi/linux/acrn/acrn_common_def.h |  25 +++
 include/uapi/linux/acrn/acrn_ioctl_defs.h |  41 +
 9 files changed, 759 insertions(+), 24 deletions(-)
 create mode 100644 drivers/staging/acrn/acrn_mm.c
 create mode 100644 drivers/staging/acrn/acrn_mm_hugetlb.c
 create mode 100644 include/linux/acrn/acrn_drv.h
 create mode 100644 include/uapi/linux/acrn/acrn_common_def.h

diff --git a/drivers/staging/acrn/Makefile b/drivers/staging/acrn/Makefile
index 426d6e8..ec62afe 100644
--- a/drivers/staging/acrn/Makefile
+++ b/drivers/staging/acrn/Makefile
@@ -1,4 +1,6 @@
 obj-$(CONFIG_ACRN_HSM) := acrn.o
 acrn-y := acrn_dev.o \
  acrn_hypercall.o \
- acrn_vm_mngt.o
+ acrn_vm_mngt.o \
+ acrn_mm.o \
+ acrn_mm_hugetlb.o
diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 7372316..cb62819 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -44,6 +44,7 @@ static
 int acrn_dev_open(struct inode *inodep, struct file *filep)
 {
struct acrn_vm *vm;
+   int i;
 
vm = kzalloc(sizeof(*vm), GFP_KERNEL);
if (!vm)
@@ -53,6 +54,10 @@ int acrn_dev_open(struct inode *inodep, struct file *filep)
vm->vmid = ACRN_INVALID_VMID;
vm->dev = acrn_device;
 
+   for (i = 0; i < HUGEPAGE_HLIST_ARRAY_SIZE; i++)
+   INIT_HLIST_HEAD(>hugepage_hlist[i]);
+   mutex_init(>hugepage_lock);
+
write_lock_bh(_vm_list_lock);
vm_list_add(>list);
write_unlock_bh(_vm_list_lock);
@@ -212,6 +217,28 @@ long acrn_dev_ioctl(struct file *filep,
return ret;
}
 
+   case IC_SET_MEMSEG: {
+   struct vm_memmap memmap;
+
+   if (copy_from_user(, (void *)ioctl_param,
+  sizeof(memmap)))
+   return -EFAULT;
+
+   ret = map_guest_memseg(vm, );
+   break;
+   }
+
+   case IC_UNSET_MEMSEG: {
+   struct vm_memmap memmap;
+
+   if (copy_from_user(, (void *)ioctl_param,
+  sizeof(memmap)))
+   return -EFAULT;
+
+   ret = unmap_guest_memseg(vm, );
+   break;
+   }
+
default:
pr_warn("Unknown IOCTL 0x%x\n", ioctl_num);
ret = -EFAULT;
diff --git a/drivers/staging/acrn/acrn_drv_internal.h 
b/drivers/staging/acrn/acrn_drv_internal.h
index 6758dea..5098765 100644
--- a/drivers/staging/acrn/acrn_drv_internal.h
+++ b/drivers/staging/acrn/acrn_drv_internal.h
@@ -11,6 +11,57 @@
 #include 
 #include 
 
+struct vm_memory_region {
+#define MR_ADD 0
+#define MR_DEL 2
+   u32 type;
+
+   /* IN: mem attr */
+   u32 prot;
+
+   /* IN: beginning guest GPA to map */
+   u64 gpa;
+
+   /* IN: VM0's GPA which foreign gpa will be mapped to */
+   u64 vm0_gpa;
+
+   /* IN: size of the region */
+   u64 size;
+};
+
+struct set_regions {
+   /*IN: vmid for this hypercall */
+   u16 vmid;
+
+   /** Reserved */
+   u16 reserved[3];
+
+   /* IN: multi memmaps numbers */
+   u32 mr_num;
+
+   /** Reserved */
+   u32 reserved1;
+   /* IN:
+* the gpa of memmaps buffer, point to the memm

[RFC PATCH 12/15] drivers/acrn: add driver-specific IRQ handle to dispatch IO_REQ request

2019-08-15 Thread Zhao Yakui
After ACRN hypervisor captures the io_request(mmio, IO, PCI access) from
guest OS, it will send the IRQ interrupt to SOS system.
The HYPERVISOR_CALLBACK_VECTOR ISR handler will be executed and it
needs to call the driver-specific ISR handler to dispatch emulated
io_request.
After the emulation of ioreq request is finished, the ACRN hypervisor
is notified and then can resume the execution of guest OS.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Mingqiang Chi 
Signed-off-by: Mingqiang Chi 
Co-developed-by: Liu Shuo 
Signed-off-by: Liu Shuo 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/acrn_dev.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 28258fb..93f45e3 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ static intacrn_hsm_inited;
 static int major;
 static struct class*acrn_class;
 static struct device   *acrn_device;
+static struct tasklet_struct acrn_io_req_tasklet;
 
 static
 int acrn_dev_open(struct inode *inodep, struct file *filep)
@@ -416,6 +418,16 @@ long acrn_dev_ioctl(struct file *filep,
break;
}
case IC_CLEAR_VM_IOREQ: {
+   /*
+* we need to flush the current pending ioreq dispatch
+* tasklet and finish it before clearing all ioreq of this VM.
+* With tasklet_kill, there still be a very rare race which
+* might lost one ioreq tasklet for other VMs. So arm one after
+* the clearing. It's harmless.
+*/
+   tasklet_schedule(_io_req_tasklet);
+   tasklet_kill(_io_req_tasklet);
+   tasklet_schedule(_io_req_tasklet);
acrn_ioreq_clear_request(vm);
break;
}
@@ -449,6 +461,28 @@ static int acrn_dev_release(struct inode *inodep, struct 
file *filep)
return 0;
 }
 
+static void io_req_tasklet(unsigned long data)
+{
+   struct acrn_vm *vm;
+   /* This is already in tasklet. Use read_lock for list_lock */
+
+   read_lock(_vm_list_lock);
+   list_for_each_entry(vm, _vm_list, list) {
+   if (!vm || !vm->req_buf)
+   break;
+
+   get_vm(vm);
+   acrn_ioreq_distribute_request(vm);
+   put_vm(vm);
+   }
+   read_unlock(_vm_list_lock);
+}
+
+static void acrn_intr_handler(void)
+{
+   tasklet_schedule(_io_req_tasklet);
+}
+
 static const struct file_operations fops = {
.open = acrn_dev_open,
.release = acrn_dev_release,
@@ -462,6 +496,7 @@ static const struct file_operations fops = {
 
 static int __init acrn_init(void)
 {
+   unsigned long flag;
struct api_version *api_version;
acrn_hsm_inited = 0;
if (x86_hyper_type != X86_HYPER_ACRN)
@@ -518,6 +553,10 @@ static int __init acrn_init(void)
return PTR_ERR(acrn_device);
}
 
+   tasklet_init(_io_req_tasklet, io_req_tasklet, 0);
+   local_irq_save(flag);
+   acrn_setup_intr_irq(acrn_intr_handler);
+   local_irq_restore(flag);
acrn_ioreq_driver_init();
pr_info("acrn: ACRN Hypervisor service module initialized\n");
acrn_hsm_inited = 1;
@@ -529,6 +568,8 @@ static void __exit acrn_exit(void)
if (!acrn_hsm_inited)
return;
 
+   tasklet_kill(_io_req_tasklet);
+   acrn_remove_intr_irq();
device_destroy(acrn_class, MKDEV(major, 0));
class_unregister(acrn_class);
class_destroy(acrn_class);
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC PATCH 04/15] drivers/acrn: add the basic framework of acrn char device driver

2019-08-15 Thread Zhao Yakui
ACRN hypervisor service module is the important middle layer that allows
the Linux kernel to communicate with the ACRN hypervisor. It includes
the management of virtualized CPU/memory/device/interrupt for other ACRN
guest. The user-space applications can use the provided ACRN ioctls to
interact with ACRN hypervisor through different hypercalls.

Add one basic framework firstly and the following patches will
add the corresponding implementations, which includes the management of
virtualized CPU/memory/interrupt and the emulation of MMIO/IO/PCI access.
The device file of /dev/acrn_hsm can be accessed in user-space to
communicate with ACRN module.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Jack Ren 
Signed-off-by: Jack Ren 
Co-developed-by: Mingqiang Chi 
Signed-off-by: Mingqiang Chi 
Co-developed-by: Liu Shuo 
Signed-off-by: Liu Shuo 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/Kconfig |   2 +
 drivers/staging/Makefile|   1 +
 drivers/staging/acrn/Kconfig|  18 ++
 drivers/staging/acrn/Makefile   |   2 +
 drivers/staging/acrn/acrn_dev.c | 123 
 5 files changed, 146 insertions(+)
 create mode 100644 drivers/staging/acrn/Kconfig
 create mode 100644 drivers/staging/acrn/Makefile
 create mode 100644 drivers/staging/acrn/acrn_dev.c

diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 7c96a01..0766de5 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -120,4 +120,6 @@ source "drivers/staging/kpc2000/Kconfig"
 
 source "drivers/staging/isdn/Kconfig"
 
+source "drivers/staging/acrn/Kconfig"
+
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index fcaac96..f927eb0 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -49,4 +49,5 @@ obj-$(CONFIG_XIL_AXIS_FIFO)   += axis-fifo/
 obj-$(CONFIG_EROFS_FS) += erofs/
 obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
 obj-$(CONFIG_KPC2000)  += kpc2000/
+obj-$(CONFIG_ACRN_HSM) += acrn/
 obj-$(CONFIG_ISDN_CAPI)+= isdn/
diff --git a/drivers/staging/acrn/Kconfig b/drivers/staging/acrn/Kconfig
new file mode 100644
index 000..a047d5f
--- /dev/null
+++ b/drivers/staging/acrn/Kconfig
@@ -0,0 +1,18 @@
+config ACRN_HSM
+   tristate "Intel ACRN Hypervisor service Module"
+   depends on ACRN_GUEST
+   depends on HUGETLBFS
+   depends on PCI_MSI
+   default n
+   help
+ This is the Hypervisor service Module (ACRN.ko) for ACRN guest
+ to communicate with ACRN hypervisor. It includes the management
+ of virtualized CPU/memory/device/interrupt for other ACRN guest.
+
+ It is required if it needs to manage other ACRN guests. User-guest
+ OS does not need it.
+
+ If unsure, say N.
+ If you wish to work on this driver, to help improve it, or to
+ report problems you have with them, please use the
+ acrn-...@lists.projectacrn.org mailing list.
diff --git a/drivers/staging/acrn/Makefile b/drivers/staging/acrn/Makefile
new file mode 100644
index 000..48fca38
--- /dev/null
+++ b/drivers/staging/acrn/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ACRN_HSM) := acrn.o
+acrn-y := acrn_dev.o
diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
new file mode 100644
index 000..55a7612
--- /dev/null
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * ACRN hyperviosr service module (HSM): main framework
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Jason Chen CJ 
+ * Zhao Yakui 
+ * Jack Ren 
+ * Mingqiang Chi 
+ * Liu Shuo 
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define  DEVICE_NAME "acrn_hsm"
+#define  CLASS_NAME  "acrn"
+
+static int acrn_hsm_inited;
+static int major;
+static struct class*acrn_class;
+static struct device   *acrn_device;
+
+static
+int acrn_dev_open(struct inode *inodep, struct file *filep)
+{
+   pr_info("%s: opening device node\n", __func__);
+
+   return 0;
+}
+
+static
+long acrn_dev_ioctl(struct file *filep,
+   unsigned int ioctl_num, unsigned long ioctl_param)
+{
+   long ret = 0;
+
+   return ret;
+}
+
+static int acrn_dev_release(struct inode *inodep, struct file *filep)
+{
+   return 0;
+}
+
+static const struct file_operations fops = {
+   .open = acrn_dev_open,
+   .release = acrn_dev_release,
+   .unlocked_ioctl = acrn_dev_ioctl,
+};
+
+#define EAX_PRIVILEGE_VM   BIT(0)
+
+static int __init acrn_init(void)
+{
+   acrn_hsm_inited = 0;
+   if (x86_hyper_type != X86_HYPER_ACRN)
+   return -ENODEV;
+
+   if (!(cpuid_eax(0x4001) & EAX_PRIVILEGE_VM))
+   return -EPERM;
+
+   /* 

[RFC PATCH 00/15] acrn: add the ACRN driver module

2019-08-15 Thread Zhao Yakui
ACRN is a flexible, lightweight reference hypervisor, built with real-time
and safety-criticality in mind, optimized to streamline embedded development
through an open source platform. It is built for embedded IOT with small
footprint and real-time features. More details can be found
in https://projectacrn.org/

This is the patch set that add the ACRN driver module on ACRN guest, which
acts as the router to communciate with ACRN hypervisor.
The user-space applications can use the provided ACRN ioctls to
interact with ACRN hypervisor through different hypercalls. After the ACRN
module is loaded, the device file of /dev/acrn_hsm can be accessed in
user-space. It includes the management of virtualized CPU/memory/
device/interrupt/MMIO emulation for other ACRN guest. 
 
The first three patches are the changes under x86/acrn, which adds the
required APIs for the driver and reports the X2APIC caps. 
The remaining patches add the ACRN driver module, which accepts the ioctl
from user-space and then communicate with the low-level ACRN hypervisor
by using hypercall.


Zhao Yakui (15):
  x86/acrn: Report X2APIC for ACRN guest
  x86/acrn: Add two APIs to add/remove driver-specific upcall ISR handler
  x86/acrn: Add hypercall for ACRN guest
  drivers/acrn: add the basic framework of acrn char device driver
  drivers/acrn: add driver-specific hypercall for ACRN_HSM
  drivers/acrn: add the support of querying ACRN api version
  drivers/acrn: add acrn vm/vcpu management for ACRN_HSM char device
  drivers/acrn: add VM memory management for ACRN char device
  drivers/acrn: add passthrough device support
  drivers/acrn: add interrupt injection support
  drivers/acrn: add the support of handling emulated ioreq
  drivers/acrn: add driver-specific IRQ handle to dispatch IO_REQ request
  drivers/acrn: add service to obtain Power data transition
  drivers/acrn: add the support of irqfd and eventfd
  drivers/acrn: add the support of offline SOS cpu

 arch/x86/include/asm/acrn.h   |  57 ++
 arch/x86/kernel/cpu/acrn.c|  20 +-
 drivers/staging/Kconfig   |   2 +
 drivers/staging/Makefile  |   1 +
 drivers/staging/acrn/Kconfig  |  18 +
 drivers/staging/acrn/Makefile |   9 +
 drivers/staging/acrn/acrn_dev.c   | 727 +++
 drivers/staging/acrn/acrn_drv_internal.h  | 186 ++
 drivers/staging/acrn/acrn_hv_defs.h   |  65 +++
 drivers/staging/acrn/acrn_hypercall.c | 136 +
 drivers/staging/acrn/acrn_hypercall.h | 132 +
 drivers/staging/acrn/acrn_ioeventfd.c | 407 +
 drivers/staging/acrn/acrn_ioreq.c | 937 ++
 drivers/staging/acrn/acrn_irqfd.c | 339 +++
 drivers/staging/acrn/acrn_mm.c| 227 
 drivers/staging/acrn/acrn_mm_hugetlb.c| 281 +
 drivers/staging/acrn/acrn_vm_mngt.c   | 116 
 include/linux/acrn/acrn_drv.h | 200 +++
 include/uapi/linux/acrn/acrn_common_def.h | 201 +++
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 345 +++
 20 files changed, 4400 insertions(+), 6 deletions(-)
 create mode 100644 drivers/staging/acrn/Kconfig
 create mode 100644 drivers/staging/acrn/Makefile
 create mode 100644 drivers/staging/acrn/acrn_dev.c
 create mode 100644 drivers/staging/acrn/acrn_drv_internal.h
 create mode 100644 drivers/staging/acrn/acrn_hv_defs.h
 create mode 100644 drivers/staging/acrn/acrn_hypercall.c
 create mode 100644 drivers/staging/acrn/acrn_hypercall.h
 create mode 100644 drivers/staging/acrn/acrn_ioeventfd.c
 create mode 100644 drivers/staging/acrn/acrn_ioreq.c
 create mode 100644 drivers/staging/acrn/acrn_irqfd.c
 create mode 100644 drivers/staging/acrn/acrn_mm.c
 create mode 100644 drivers/staging/acrn/acrn_mm_hugetlb.c
 create mode 100644 drivers/staging/acrn/acrn_vm_mngt.c
 create mode 100644 include/linux/acrn/acrn_drv.h
 create mode 100644 include/uapi/linux/acrn/acrn_common_def.h
 create mode 100644 include/uapi/linux/acrn/acrn_ioctl_defs.h

-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC PATCH 06/15] drivers/acrn: add the support of querying ACRN api version

2019-08-15 Thread Zhao Yakui
In order to assure that the ACRN module can work with the required ACRN
hypervisor, it needs to check whether the required version is consistent
with the queried version from ACRN ypervisor. If it is inconsistent, it
won't coninue the initialization of ACRN_HSM module.
Similarly the user-space module also needs to check the driver version.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Liu Shuo 
Signed-off-by: Liu Shuo 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/acrn_dev.c   | 47 +++
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 32 +
 2 files changed, 79 insertions(+)
 create mode 100644 include/uapi/linux/acrn/acrn_ioctl_defs.h

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 55a7612..57cd2bb 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -18,13 +18,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
+
+#include "acrn_hypercall.h"
 
 #define  DEVICE_NAME "acrn_hsm"
 #define  CLASS_NAME  "acrn"
 
+#define ACRN_API_VERSION_MAJOR 1
+#define ACRN_API_VERSION_MINOR 0
+
 static int acrn_hsm_inited;
 static int major;
 static struct class*acrn_class;
@@ -44,6 +53,19 @@ long acrn_dev_ioctl(struct file *filep,
 {
long ret = 0;
 
+   if (ioctl_num == IC_GET_API_VERSION) {
+   struct api_version api_version;
+
+   api_version.major_version = ACRN_API_VERSION_MAJOR;
+   api_version.minor_version = ACRN_API_VERSION_MINOR;
+
+   if (copy_to_user((void *)ioctl_param, _version,
+sizeof(api_version)))
+   return -EFAULT;
+
+   return 0;
+   }
+
return ret;
 }
 
@@ -59,9 +81,12 @@ static const struct file_operations fops = {
 };
 
 #define EAX_PRIVILEGE_VM   BIT(0)
+#define SUPPORT_HV_API_VERSION_MAJOR   1
+#define SUPPORT_HV_API_VERSION_MINOR   0
 
 static int __init acrn_init(void)
 {
+   struct api_version *api_version;
acrn_hsm_inited = 0;
if (x86_hyper_type != X86_HYPER_ACRN)
return -ENODEV;
@@ -69,6 +94,28 @@ static int __init acrn_init(void)
if (!(cpuid_eax(0x4001) & EAX_PRIVILEGE_VM))
return -EPERM;
 
+   api_version = kmalloc(sizeof(*api_version), GFP_KERNEL);
+   if (!api_version)
+   return -ENOMEM;
+
+   if (hcall_get_api_version(virt_to_phys(api_version)) < 0) {
+   pr_err("acrn: failed to get api version from Hypervisor !\n");
+   kfree(api_version);
+   return -EINVAL;
+   }
+
+   if (api_version->major_version >= SUPPORT_HV_API_VERSION_MAJOR &&
+   api_version->minor_version >= SUPPORT_HV_API_VERSION_MINOR) {
+   pr_info("acrn: hv api version %d.%d\n",
+   api_version->major_version, api_version->minor_version);
+   kfree(api_version);
+   } else {
+   pr_err("acrn: not support hv api version %d.%d!\n",
+  api_version->major_version, api_version->minor_version);
+   kfree(api_version);
+   return -EINVAL;
+   }
+
/* Try to dynamically allocate a major number for the device */
major = register_chrdev(0, DEVICE_NAME, );
if (major < 0) {
diff --git a/include/uapi/linux/acrn/acrn_ioctl_defs.h 
b/include/uapi/linux/acrn/acrn_ioctl_defs.h
new file mode 100644
index 000..8dbf69a
--- /dev/null
+++ b/include/uapi/linux/acrn/acrn_ioctl_defs.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/**
+ * @file acrn_ioctl_defs.h
+ *
+ * ACRN definition for ioctl to user space
+ */
+
+#ifndef __ACRN_IOCTL_DEFS_H__
+#define __ACRN_IOCTL_DEFS_H__
+
+/**
+ * struct api_version - data structure to track ACRN_SRV API version
+ *
+ * @major_version: major version of ACRN_SRV API
+ * @minor_version: minor version of ACRN_SRV API
+ */
+struct api_version {
+   uint32_t major_version;
+   uint32_t minor_version;
+};
+
+/*
+ * Common IOCTL ID definition for DM
+ */
+#define _IC_ID(x, y) (((x) << 24) | (y))
+#define IC_ID 0x43UL
+
+/* General */
+#define IC_ID_GEN_BASE  0x0UL
+#define IC_GET_API_VERSION _IC_ID(IC_ID, IC_ID_GEN_BASE + 0x00)
+
+#endif /* __ACRN_IOCTL_DEFS_H__ */
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC PATCH 03/15] x86/acrn: Add hypercall for ACRN guest

2019-08-15 Thread Zhao Yakui
When ACRN hypervisor is detected, the hypercall is needed so that the
ACRN guest can query/config some settings. For example: it can be used
to query the resources in hypervisor and manage the CPU/memory/device/
interrupt for guest operating system.

On x86 it is implemented with the VMCALL instruction.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Signed-off-by: Zhao Yakui 
---
 arch/x86/include/asm/acrn.h | 54 +
 1 file changed, 54 insertions(+)

diff --git a/arch/x86/include/asm/acrn.h b/arch/x86/include/asm/acrn.h
index 857e6244..ab97c3d 100644
--- a/arch/x86/include/asm/acrn.h
+++ b/arch/x86/include/asm/acrn.h
@@ -11,4 +11,58 @@ extern void acrn_hv_vector_handler(struct pt_regs *regs);
 
 extern void acrn_setup_intr_irq(void (*handler)(void));
 extern void acrn_remove_intr_irq(void);
+
+/*
+ * Hypercalls for ACRN guest
+ *
+ * Hypercall number is passed in R8 register.
+ * Up to 2 arguments are passed in RDI, RSI.
+ * Return value will be placed in RAX.
+ */
+static inline long acrn_hypercall0(unsigned long hcall_id)
+{
+   long result;
+
+   /* the hypercall is implemented with the VMCALL instruction.
+* volatile qualifier is added to avoid that it is dropped
+* because of compiler optimization.
+*/
+   asm volatile("movq %[hcall_id], %%r8\n\t"
+"vmcall\n\t"
+: "=a" (result)
+: [hcall_id] "g" (hcall_id)
+: "r8");
+
+   return result;
+}
+
+static inline long acrn_hypercall1(unsigned long hcall_id,
+  unsigned long param1)
+{
+   long result;
+
+   asm volatile("movq %[hcall_id], %%r8\n\t"
+"vmcall\n\t"
+: "=a" (result)
+: [hcall_id] "g" (hcall_id), "D" (param1)
+: "r8");
+
+   return result;
+}
+
+static inline long acrn_hypercall2(unsigned long hcall_id,
+  unsigned long param1,
+  unsigned long param2)
+{
+   long result;
+
+   asm volatile("movq %[hcall_id], %%r8\n\t"
+"vmcall\n\t"
+: "=a" (result)
+: [hcall_id] "g" (hcall_id), "D" (param1), "S" (param2)
+: "r8");
+
+   return result;
+}
+
 #endif /* _ASM_X86_ACRN_H */
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC PATCH 09/15] drivers/acrn: add passthrough device support

2019-08-15 Thread Zhao Yakui
Pass-through device plays an important role for guest OS when it is
accessed exclusively by guest OS. This is critical for the performance
scenario. After one PCI device is assigned to guest OS, it can be
accessed exclusively by guest system. It can avoid the device emulation
and provide the better performance.
It provides the following operations for supporting pass-through device.
- assign, pass-through device
   ACRN_ASSIGN_PTDEV: Assign one PCI device to one guest OS
- deassign pass-through device
   ACRN_DEASSIGN_PTDEV: Return the assigned PCI device from
the guest OS so that it can be assigned to another guest OS.
- set, reset pass-through device intr info
   ACRN_SET_PTDEV_INTR_INFO
   ACRN_RESET_PTDEV_INTR_INFO : This is used to configure
the interrupt info for the assigned pass-through device so that
ACRN hypervisor can inject the interrupt into guest system after
the device interrupt is triggered.

Co-developed-by: Gao, Shiqing 
Signed-off-by: Gao, Shiqing 
Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/acrn_dev.c   | 77 +++
 drivers/staging/acrn/acrn_drv_internal.h  | 25 ++
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 47 +++
 3 files changed, 149 insertions(+)

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index cb62819..28bbd78 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -239,6 +239,83 @@ long acrn_dev_ioctl(struct file *filep,
break;
}
 
+   case IC_ASSIGN_PTDEV: {
+   unsigned short bdf;
+
+   if (copy_from_user(, (void *)ioctl_param,
+  sizeof(unsigned short)))
+   return -EFAULT;
+
+   ret = hcall_assign_ptdev(vm->vmid, bdf);
+   if (ret < 0) {
+   pr_err("acrn: failed to assign ptdev!\n");
+   return -EFAULT;
+   }
+   break;
+   }
+   case IC_DEASSIGN_PTDEV: {
+   unsigned short bdf;
+
+   if (copy_from_user(, (void *)ioctl_param,
+  sizeof(unsigned short)))
+   return -EFAULT;
+
+   ret = hcall_deassign_ptdev(vm->vmid, bdf);
+   if (ret < 0) {
+   pr_err("acrn: failed to deassign ptdev!\n");
+   return -EFAULT;
+   }
+   break;
+   }
+
+   case IC_SET_PTDEV_INTR_INFO: {
+   struct ic_ptdev_irq ic_pt_irq;
+   struct hc_ptdev_irq *hc_pt_irq;
+
+   if (copy_from_user(_pt_irq, (void *)ioctl_param,
+  sizeof(ic_pt_irq)))
+   return -EFAULT;
+
+   hc_pt_irq = kmalloc(sizeof(*hc_pt_irq), GFP_KERNEL);
+   if (!hc_pt_irq)
+   return -ENOMEM;
+
+   memcpy(hc_pt_irq, _pt_irq, sizeof(*hc_pt_irq));
+
+   ret = hcall_set_ptdev_intr_info(vm->vmid,
+   virt_to_phys(hc_pt_irq));
+   kfree(hc_pt_irq);
+   if (ret < 0) {
+   pr_err("acrn: failed to set intr info for ptdev!\n");
+   return -EFAULT;
+   }
+
+   break;
+   }
+   case IC_RESET_PTDEV_INTR_INFO: {
+   struct ic_ptdev_irq ic_pt_irq;
+   struct hc_ptdev_irq *hc_pt_irq;
+
+   if (copy_from_user(_pt_irq, (void *)ioctl_param,
+  sizeof(ic_pt_irq)))
+   return -EFAULT;
+
+   hc_pt_irq = kmalloc(sizeof(*hc_pt_irq), GFP_KERNEL);
+   if (!hc_pt_irq)
+   return -ENOMEM;
+
+   memcpy(hc_pt_irq, _pt_irq, sizeof(*hc_pt_irq));
+
+   ret = hcall_reset_ptdev_intr_info(vm->vmid,
+ virt_to_phys(hc_pt_irq));
+   kfree(hc_pt_irq);
+   if (ret < 0) {
+   pr_err("acrn: failed to reset intr info for ptdev!\n");
+   return -EFAULT;
+   }
+   break;
+   }
+
default:
pr_warn("Unknown IOCTL 0x%x\n", ioctl_num);
ret = -EFAULT;
diff --git a/drivers/staging/acrn/acrn_drv_internal.h 
b/drivers/staging/acrn/acrn_drv_internal.h
index 5098765..3e633cd 100644
--- a/drivers/staging/acrn/acrn_drv_internal.h
+++ b/drivers/staging/acrn/acrn_drv_internal.h
@@ -115,4 +115,29 @@ void hugepage_free_guest(struct acrn_vm *vm);
 void *hugepage_map_guest_phys(struct acrn_vm *vm, u64 guest_phys, size_t size);
 int hugepage_unmap_guest_phys(struct acrn_vm *vm, u64 guest_phys);
 int set_memory_regions(struct set_regions *regions)

[RFC PATCH 13/15] drivers/acrn: add service to obtain Power data transition

2019-08-15 Thread Zhao Yakui
The px/cx data is critical to support the power transition. DM will get
these data to build DSDT for UOS. With this DSDT, UOS would have the
capability on power control if acpi-cpufreq/idle driver is enabled in
kernel.
Add the PM ioctl that is used to obtain the info of power state
so that the DM can construct the DSDT with Power frequence/C-state idle
for guest system.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Victor Sun 
Signed-off-by: Victor Sun 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/acrn_dev.c   | 75 +++
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 36 +++
 2 files changed, 111 insertions(+)

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 93f45e3..ef0ec50 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -432,6 +432,81 @@ long acrn_dev_ioctl(struct file *filep,
break;
}
 
+   case IC_PM_GET_CPU_STATE: {
+   u64 cmd;
+
+   if (copy_from_user(, (void *)ioctl_param, sizeof(cmd)))
+   return -EFAULT;
+
+   switch (cmd & PMCMD_TYPE_MASK) {
+   case PMCMD_GET_PX_CNT:
+   case PMCMD_GET_CX_CNT: {
+   u64 *pm_info;
+
+   pm_info = kmalloc(sizeof(u64), GFP_KERNEL);
+   if (!pm_info)
+   return -ENOMEM;
+
+   ret = hcall_get_cpu_state(cmd, virt_to_phys(pm_info));
+   if (ret < 0) {
+   kfree(pm_info);
+   return -EFAULT;
+   }
+
+   if (copy_to_user((void *)ioctl_param,
+pm_info, sizeof(u64)))
+   ret = -EFAULT;
+
+   kfree(pm_info);
+   break;
+   }
+   case PMCMD_GET_PX_DATA: {
+   struct cpu_px_data *px_data;
+
+   px_data = kmalloc(sizeof(*px_data), GFP_KERNEL);
+   if (!px_data)
+   return -ENOMEM;
+
+   ret = hcall_get_cpu_state(cmd, virt_to_phys(px_data));
+   if (ret < 0) {
+   kfree(px_data);
+   return -EFAULT;
+   }
+
+   if (copy_to_user((void *)ioctl_param,
+px_data, sizeof(*px_data)))
+   ret = -EFAULT;
+
+   kfree(px_data);
+   break;
+   }
+   case PMCMD_GET_CX_DATA: {
+   struct cpu_cx_data *cx_data;
+
+   cx_data = kmalloc(sizeof(*cx_data), GFP_KERNEL);
+   if (!cx_data)
+   return -ENOMEM;
+
+   ret = hcall_get_cpu_state(cmd, virt_to_phys(cx_data));
+   if (ret < 0) {
+   kfree(cx_data);
+   return -EFAULT;
+   }
+
+   if (copy_to_user((void *)ioctl_param,
+cx_data, sizeof(*cx_data)))
+   ret = -EFAULT;
+   kfree(cx_data);
+   break;
+   }
+   default:
+   ret = -EFAULT;
+   break;
+   }
+
+   break;
+   }
+
default:
pr_warn("Unknown IOCTL 0x%x\n", ioctl_num);
ret = -EFAULT;
diff --git a/include/uapi/linux/acrn/acrn_ioctl_defs.h 
b/include/uapi/linux/acrn/acrn_ioctl_defs.h
index c3c4f98..c762bd2 100644
--- a/include/uapi/linux/acrn/acrn_ioctl_defs.h
+++ b/include/uapi/linux/acrn/acrn_ioctl_defs.h
@@ -234,6 +234,39 @@ struct ioreq_notify {
uint32_t vcpu;
 };
 
+struct acrn_generic_address {
+   uint8_t space_id;
+   uint8_t bit_width;
+   uint8_t bit_offset;
+   uint8_t access_size;
+   uint64_taddress;
+};
+
+struct cpu_cx_data {
+   struct acrn_generic_address cx_reg;
+   uint8_t type;
+   uint32_tlatency;
+   uint64_tpower;
+};
+
+struct cpu_px_data {
+   uint64_t core_frequency;/* megahertz */
+   uint64_t power; /* milliWatts */
+   uint64_t transition_latency;/* microseconds */
+   uint64_t bus_master_latency;/* microseconds */
+   uint64_t control;   /* control value */
+   uint64_t status;/* success indicator */
+};
+
+#define PMCMD_TYPE_MASK0x00ff
+
+enum pm_cmd_type {
+   PMCMD_GET_PX_CNT,
+   PMCMD_GET_PX_DATA,
+

[RFC PATCH 15/15] drivers/acrn: add the support of offline SOS cpu

2019-08-15 Thread Zhao Yakui
The ACRN-hypervisor works in partition mode. In such case the guest OS
and domain0 kernel will run in the different CPUs.  In course of booting
domain0 kernel, it can use all the available CPUs,which can accelerate
the booting. But after the booting is finished, it needs to offline the
other CPUs so that they can be allocated to the guest OS.

add sysfs with attr "offline_cpu", use
echo cpu_id > /sys/class/acrn/acrn_hsm/offline_cpu
to do the hypercall offline/destroy according vcpu.
before doing it, It will offline cpu by using the below cmd:
echo 0 > /sys/devices/system/cpu/cpuX/online

Currently this is mainly used in user-space device model before
booting other ACRN guest.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Signed-off-by: Zhao Yakui 
---
 drivers/staging/acrn/acrn_dev.c | 45 +
 1 file changed, 45 insertions(+)

diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 0602125..6868003 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -588,6 +588,41 @@ static const struct file_operations fops = {
 #define SUPPORT_HV_API_VERSION_MAJOR   1
 #define SUPPORT_HV_API_VERSION_MINOR   0
 
+static ssize_t
+offline_cpu_store(struct device *dev,
+   struct device_attribute *attr,
+   const char *buf, size_t count)
+{
+#ifdef CONFIG_X86
+   u64 cpu, lapicid;
+
+   if (kstrtoull(buf, 0, ) < 0)
+   return -EINVAL;
+
+   if (cpu_possible(cpu)) {
+   lapicid = cpu_data(cpu).apicid;
+   pr_info("acrn: try to offline cpu %lld with lapicid %lld\n",
+   cpu, lapicid);
+   if (hcall_sos_offline_cpu(lapicid) < 0) {
+   pr_err("acrn: failed to offline cpu from 
Hypervisor!\n");
+   return -EINVAL;
+   }
+   }
+#endif
+   return count;
+}
+
+static DEVICE_ATTR(offline_cpu, 00200, NULL, offline_cpu_store);
+
+static struct attribute *acrn_attrs[] = {
+   _attr_offline_cpu.attr,
+   NULL
+};
+
+static struct attribute_group acrn_attr_group = {
+   .attrs = acrn_attrs,
+};
+
 static int __init acrn_init(void)
 {
unsigned long flag;
@@ -647,6 +682,15 @@ static int __init acrn_init(void)
return PTR_ERR(acrn_device);
}
 
+   if (sysfs_create_group(_device->kobj, _attr_group)) {
+   pr_warn("acrn: sysfs create failed\n");
+   device_destroy(acrn_class, MKDEV(major, 0));
+   class_unregister(acrn_class);
+   class_destroy(acrn_class);
+   unregister_chrdev(major, DEVICE_NAME);
+   return -EINVAL;
+   }
+
tasklet_init(_io_req_tasklet, io_req_tasklet, 0);
local_irq_save(flag);
acrn_setup_intr_irq(acrn_intr_handler);
@@ -664,6 +708,7 @@ static void __exit acrn_exit(void)
 
tasklet_kill(_io_req_tasklet);
acrn_remove_intr_irq();
+   sysfs_remove_group(_device->kobj, _attr_group);
device_destroy(acrn_class, MKDEV(major, 0));
class_unregister(acrn_class);
class_destroy(acrn_class);
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[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,
+   

[RFC PATCH 02/15] x86/acrn: Add two APIs to add/remove driver-specific upcall ISR handler

2019-08-15 Thread Zhao Yakui
After the ACRN hypervisor sends the upcall notify interrupt, the upcall ISR
handler will be served. Now almost nothing is handled in upcall ISR handler
except acking EOI.
The driver-specific ISR handler is registered by the driver, which helps to
handle the real notification from ACRN hypervisor.
This is similar to that in XEN/HyperV.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Signed-off-by: Zhao Yakui 
---
 arch/x86/include/asm/acrn.h |  3 +++
 arch/x86/kernel/cpu/acrn.c  | 12 
 2 files changed, 15 insertions(+)

diff --git a/arch/x86/include/asm/acrn.h b/arch/x86/include/asm/acrn.h
index 4adb13f..857e6244 100644
--- a/arch/x86/include/asm/acrn.h
+++ b/arch/x86/include/asm/acrn.h
@@ -8,4 +8,7 @@ extern void acrn_hv_callback_vector(void);
 #endif
 
 extern void acrn_hv_vector_handler(struct pt_regs *regs);
+
+extern void acrn_setup_intr_irq(void (*handler)(void));
+extern void acrn_remove_intr_irq(void);
 #endif /* _ASM_X86_ACRN_H */
diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
index 95db5c4..a1ce52a 100644
--- a/arch/x86/kernel/cpu/acrn.c
+++ b/arch/x86/kernel/cpu/acrn.c
@@ -56,6 +56,18 @@ __visible void __irq_entry acrn_hv_vector_handler(struct 
pt_regs *regs)
set_irq_regs(old_regs);
 }
 
+void acrn_setup_intr_irq(void (*handler)(void))
+{
+   acrn_intr_handler = handler;
+}
+EXPORT_SYMBOL_GPL(acrn_setup_intr_irq);
+
+void acrn_remove_intr_irq(void)
+{
+   acrn_intr_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(acrn_remove_intr_irq);
+
 const __initconst struct hypervisor_x86 x86_hyper_acrn = {
.name   = "ACRN",
.detect = acrn_detect,
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RFC PATCH 05/15] drivers/acrn: add driver-specific hypercall for ACRN_HSM

2019-08-15 Thread Zhao Yakui
After the user-space calls the ioctls, the module will then call the
defined hypercall so that the ACRN hypervisor can take the corresponding
action. It includes the management of creating vcpu, guest memory
management and interrupt injection, pass-through device management.
The available driver-specific hypercalls for ACRN HSM module are added
so that the ACRN_HSM module can communicate with the low-level
ACRN hypervisor.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Co-developed-by: Jack Ren 
Signed-off-by: Jack Ren 
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_hv_defs.h   |  65 
 drivers/staging/acrn/acrn_hypercall.c | 136 ++
 drivers/staging/acrn/acrn_hypercall.h | 132 +
 4 files changed, 335 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/acrn/acrn_hv_defs.h
 create mode 100644 drivers/staging/acrn/acrn_hypercall.c
 create mode 100644 drivers/staging/acrn/acrn_hypercall.h

diff --git a/drivers/staging/acrn/Makefile b/drivers/staging/acrn/Makefile
index 48fca38..a58b0d1 100644
--- a/drivers/staging/acrn/Makefile
+++ b/drivers/staging/acrn/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ACRN_HSM) := acrn.o
-acrn-y := acrn_dev.o
+acrn-y := acrn_dev.o \
+ acrn_hypercall.o
diff --git a/drivers/staging/acrn/acrn_hv_defs.h 
b/drivers/staging/acrn/acrn_hv_defs.h
new file mode 100644
index 000..55417d2
--- /dev/null
+++ b/drivers/staging/acrn/acrn_hv_defs.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * hypercall ID definition
+ *
+ */
+
+#ifndef _ACRN_HV_DEFS_H
+#define _ACRN_HV_DEFS_H
+
+/*
+ * Common structures for HV/HSM
+ */
+
+#define _HC_ID(x, y) (((x) << 24) | (y))
+
+#define HC_ID 0x80UL
+
+/* general */
+#define HC_ID_GEN_BASE   0x0UL
+#define HC_GET_API_VERSION  _HC_ID(HC_ID, HC_ID_GEN_BASE + 0x00)
+#define HC_SOS_OFFLINE_CPU  _HC_ID(HC_ID, HC_ID_GEN_BASE + 0x01)
+#define HC_GET_PLATFORM_INFO_HC_ID(HC_ID, HC_ID_GEN_BASE + 0x03)
+
+/* VM management */
+#define HC_ID_VM_BASE   0x10UL
+#define HC_CREATE_VM_HC_ID(HC_ID, HC_ID_VM_BASE + 0x00)
+#define HC_DESTROY_VM   _HC_ID(HC_ID, HC_ID_VM_BASE + 0x01)
+#define HC_START_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x02)
+#define HC_PAUSE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x03)
+#define HC_CREATE_VCPU  _HC_ID(HC_ID, HC_ID_VM_BASE + 0x04)
+#define HC_RESET_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x05)
+#define HC_SET_VCPU_REGS_HC_ID(HC_ID, HC_ID_VM_BASE + 0x06)
+
+/* IRQ and Interrupts */
+#define HC_ID_IRQ_BASE  0x20UL
+#define HC_INJECT_MSI   _HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x03)
+#define HC_VM_INTR_MONITOR  _HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x04)
+#define HC_SET_IRQLINE  _HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x05)
+
+/* DM ioreq management */
+#define HC_ID_IOREQ_BASE0x30UL
+#define HC_SET_IOREQ_BUFFER _HC_ID(HC_ID, HC_ID_IOREQ_BASE + 0x00)
+#define HC_NOTIFY_REQUEST_FINISH_HC_ID(HC_ID, HC_ID_IOREQ_BASE + 0x01)
+
+/* Guest memory management */
+#define HC_ID_MEM_BASE  0x40UL
+#define HC_VM_SET_MEMORY_REGIONS_HC_ID(HC_ID, HC_ID_MEM_BASE + 0x02)
+#define HC_VM_WRITE_PROTECT_PAGE_HC_ID(HC_ID, HC_ID_MEM_BASE + 0x03)
+
+/* PCI assignment*/
+#define HC_ID_PCI_BASE  0x50UL
+#define HC_ASSIGN_PTDEV _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x00)
+#define HC_DEASSIGN_PTDEV   _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x01)
+#define HC_SET_PTDEV_INTR_INFO  _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x03)
+#define HC_RESET_PTDEV_INTR_INFO_HC_ID(HC_ID, HC_ID_PCI_BASE + 0x04)
+
+/* DEBUG */
+#define HC_ID_DBG_BASE  0x60UL
+
+/* Power management */
+#define HC_ID_PM_BASE   0x80UL
+#define HC_PM_GET_CPU_STATE _HC_ID(HC_ID, HC_ID_PM_BASE + 0x00)
+#define HC_PM_SET_SSTATE_DATA   _HC_ID(HC_ID, HC_ID_PM_BASE + 0x01)
+
+#endif /* __ACRN_HV_DEFS_H */
diff --git a/drivers/staging/acrn/acrn_hypercall.c 
b/drivers/staging/acrn/acrn_hypercall.c
new file mode 100644
index 000..6d83475
--- /dev/null
+++ b/drivers/staging/acrn/acrn_hypercall.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * ACRN hyperviosr service module (HSM): driver-specific hypercall
+ *
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Jason Chen CJ 
+ * Zhao Yakui 
+ * Jack Ren 
+ * Yin FengWei 
+ * Liu Shuo 
+ */
+
+#include 
+#include 
+#include 
+#include "acrn_hv_defs.h"
+#include "acrn_hypercall.h"
+
+/* General */
+long hcall_get_api_version(unsigned long api_version)
+{
+   return acrn_hypercall1(HC_GET_API_VERSION, api_version);
+}
+
+long hcall_sos_off

[RFC PATCH 07/15] drivers/acrn: add acrn vm/vcpu management for ACRN_HSM char device

2019-08-15 Thread Zhao Yakui
The VM management is one important role of acrn module. It is used to
manage another VM based on the user-space ioctls. It includes the
following VM operation: CREATE/START/PAUSE/DESTROY VM, CREATE_VCPU,
IC_SET_VCPU_REGS.
acrn_ioctl is provided so that the user of /dev/acrn_hsm can manage
the VM for the given guest. After the ioctl is called, the hypercall
is then called so that the ACRN hypervisor can help to manage the
corresponding VM and create the required VCPU.

As ACRN is mainly used for embedded IOT usage, no interface is provided
to destroy the vcpu explicitly. When the VM is destroyed, the low-level
ACRN hypervisor will free the corresponding vcpu implicitly.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
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   | 169 +-
 drivers/staging/acrn/acrn_drv_internal.h  |  74 +
 drivers/staging/acrn/acrn_vm_mngt.c   |  72 +
 include/uapi/linux/acrn/acrn_ioctl_defs.h | 126 ++
 5 files changed, 442 insertions(+), 2 deletions(-)
 create mode 100644 drivers/staging/acrn/acrn_drv_internal.h
 create mode 100644 drivers/staging/acrn/acrn_vm_mngt.c

diff --git a/drivers/staging/acrn/Makefile b/drivers/staging/acrn/Makefile
index a58b0d1..426d6e8 100644
--- a/drivers/staging/acrn/Makefile
+++ b/drivers/staging/acrn/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ACRN_HSM) := acrn.o
 acrn-y := acrn_dev.o \
- acrn_hypercall.o
+ acrn_hypercall.o \
+ acrn_vm_mngt.o
diff --git a/drivers/staging/acrn/acrn_dev.c b/drivers/staging/acrn/acrn_dev.c
index 57cd2bb..7372316 100644
--- a/drivers/staging/acrn/acrn_dev.c
+++ b/drivers/staging/acrn/acrn_dev.c
@@ -27,6 +27,7 @@
 #include 
 
 #include "acrn_hypercall.h"
+#include "acrn_drv_internal.h"
 
 #define  DEVICE_NAME "acrn_hsm"
 #define  CLASS_NAME  "acrn"
@@ -42,8 +43,22 @@ static struct device *acrn_device;
 static
 int acrn_dev_open(struct inode *inodep, struct file *filep)
 {
-   pr_info("%s: opening device node\n", __func__);
+   struct acrn_vm *vm;
+
+   vm = kzalloc(sizeof(*vm), GFP_KERNEL);
+   if (!vm)
+   return -ENOMEM;
+
+   refcount_set(>refcnt, 1);
+   vm->vmid = ACRN_INVALID_VMID;
+   vm->dev = acrn_device;
 
+   write_lock_bh(_vm_list_lock);
+   vm_list_add(>list);
+   write_unlock_bh(_vm_list_lock);
+   filep->private_data = vm;
+
+   pr_info("%s: opening device node\n", __func__);
return 0;
 }
 
@@ -52,6 +67,15 @@ long acrn_dev_ioctl(struct file *filep,
unsigned int ioctl_num, unsigned long ioctl_param)
 {
long ret = 0;
+   struct acrn_vm *vm;
+
+   pr_debug("[%s] ioctl_num=0x%x\n", __func__, ioctl_num);
+
+   vm = (struct acrn_vm *)filep->private_data;
+   if (!vm) {
+   pr_err("acrn: invalid VM !\n");
+   return -EFAULT;
+   }
 
if (ioctl_num == IC_GET_API_VERSION) {
struct api_version api_version;
@@ -66,11 +90,154 @@ long acrn_dev_ioctl(struct file *filep,
return 0;
}
 
+   if ((vm->vmid == ACRN_INVALID_VMID) && (ioctl_num != IC_CREATE_VM)) {
+   pr_err("acrn: invalid VM ID for IOCTL %x!\n", ioctl_num);
+   return -EFAULT;
+   }
+
+   switch (ioctl_num) {
+   case IC_CREATE_VM: {
+   struct acrn_create_vm *created_vm;
+
+   created_vm = kmalloc(sizeof(*created_vm), GFP_KERNEL);
+   if (!created_vm)
+   return -ENOMEM;
+
+   if (copy_from_user(created_vm, (void *)ioctl_param,
+  sizeof(struct acrn_create_vm))) {
+   kfree(created_vm);
+   return -EFAULT;
+   }
+
+   ret = hcall_create_vm(virt_to_phys(created_vm));
+   if ((ret < 0) || (created_vm->vmid == ACRN_INVALID_VMID)) {
+   pr_err("acrn: failed to create VM from Hypervisor !\n");
+   kfree(created_vm);
+   return -EFAULT;
+   }
+
+   if (copy_to_user((void *)ioctl_param, created_vm,
+sizeof(struct acrn_create_vm))) {
+   kfree(created_vm);
+   return -EFAULT;
+   }
+
+   vm->vmid = created_vm->vmid;
+   atomic_set(>vcpu_num, 0);
+
+   pr_info("acrn: VM %d created\n", created_vm->vmid);
+   kfree(created_vm);
+   break;
+   }
+
+   case IC_START_VM: {
+   ret = hcall_start_vm(vm->vmid);
+   if (ret &l

[RFC PATCH 01/15] x86/acrn: Report X2APIC for ACRN guest

2019-08-15 Thread Zhao Yakui
After lapic is switched from xapic to x2apic mode, it can use the APIC
MSR register to access local apic register in ACRN guest. This will
help to remove some traps of lapic access in ACRN guest.
Report the X2APIC so that the ACRN guest can be switched to x2apic mode.

Co-developed-by: Jason Chen CJ 
Signed-off-by: Jason Chen CJ 
Signed-off-by: Zhao Yakui 
---
 arch/x86/kernel/cpu/acrn.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/acrn.c b/arch/x86/kernel/cpu/acrn.c
index 676022e..95db5c4 100644
--- a/arch/x86/kernel/cpu/acrn.c
+++ b/arch/x86/kernel/cpu/acrn.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -29,12 +30,7 @@ static void __init acrn_init_platform(void)
 
 static bool acrn_x2apic_available(void)
 {
-   /*
-* x2apic is not supported for now. Future enablement will have to check
-* X86_FEATURE_X2APIC to determine whether x2apic is supported in the
-* guest.
-*/
-   return false;
+   return boot_cpu_has(X86_FEATURE_X2APIC);
 }
 
 static void (*acrn_intr_handler)(void);
-- 
2.7.4

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel