2020-10-19 10:22:16

by Shuo Liu

[permalink] [raw]
Subject: [PATCH v5 00/17] HSM driver for ACRN hypervisor

From: Shuo Liu <[email protected]>

ACRN is a Type 1 reference hypervisor stack, running directly on the bare-metal
hardware, and is suitable for a variety of IoT and embedded device solutions.

ACRN implements a hybrid VMM architecture, using a privileged Service VM. The
Service VM manages the system resources (CPU, memory, etc.) and I/O devices of
User VMs. Multiple User VMs are supported, with each of them running Linux,
Android OS or Windows. Both Service VM and User VMs are guest VM.

Below figure shows the architecture.

Service VM User VM
+----------------------------+ | +------------------+
| +--------------+ | | | |
| |ACRN userspace| | | | |
| +--------------+ | | | |
|-----------------ioctl------| | | | ...
|kernel space +----------+ | | | |
| | HSM | | | | Drivers |
| +----------+ | | | |
+--------------------|-------+ | +------------------+
+---------------------hypercall----------------------------------------+
| ACRN Hypervisor |
+----------------------------------------------------------------------+
| Hardware |
+----------------------------------------------------------------------+

There is only one Service VM which could run Linux as OS.

In a typical case, the Service VM will be auto started when ACRN Hypervisor is
booted. Then the ACRN userspace (an application running in Service VM) could be
used to start/stop User VMs by communicating with ACRN Hypervisor Service
Module (HSM).

ACRN Hypervisor Service Module (HSM) is a middle layer that allows the ACRN
userspace and Service VM OS kernel to communicate with ACRN Hypervisor
and manage different User VMs. This middle layer provides the following
functionalities,
- Issues hypercalls to the hypervisor to manage User VMs:
* VM/vCPU management
* Memory management
* Device passthrough
* Interrupts injection
- I/O requests handling from User VMs.
- Exports ioctl through HSM char device.
- Exports function calls for other kernel modules

ACRN is focused on embedded system. So it doesn't support some features.
E.g.,
- ACRN doesn't support VM migration.
- ACRN doesn't support vCPU migration.

This patch set adds the HSM to the Linux kernel.

The basic ARCN support was merged to upstream already.
https://lore.kernel.org/lkml/[email protected]/

ChangeLog:
v5:
- Corrected typo in documentation.
- Removed unused pr_fmt().
- Used supported constraint with a explicit MOV to R8 at beginning of ASM for hypercall interface.
- Used dev_dbg() to replace dev_err() in places which might cause a DoS.
- Introduced acrn_vm_list_lock as a mutex for friendly review.
- Changed to use default attribute group list to add attribute files.

v4:
- Used acrn_dev.this_device directly for dev_*() (Reinette)
- Removed the odd usage of {get|put}_device() on &acrn_dev->this_device (Greg)
- Removed unused log code. (Greg)
- Corrected the return error values. (Greg)
- Mentioned that HSM relies hypervisor for sanity check in acrn_dev_ioctl() comments (Greg)

v3:
- Used {get|put}_device() helpers on &acrn_dev->this_device
- Moved unused code from front patches to later ones.
- Removed self-defined pr_fmt() and dev_fmt()
- Provided comments for acrn_vm_list_lock.

v2:
- Removed API version related code. (Dave)
- Replaced pr_*() by dev_*(). (Greg)
- Used -ENOTTY as the error code of unsupported ioctl. (Greg)

Shuo Liu (16):
docs: acrn: Introduce ACRN
x86/acrn: Introduce acrn_{setup, remove}_intr_handler()
x86/acrn: Introduce hypercall interfaces
virt: acrn: Introduce ACRN HSM basic driver
virt: acrn: Introduce VM management interfaces
virt: acrn: Introduce an ioctl to set vCPU registers state
virt: acrn: Introduce EPT mapping management
virt: acrn: Introduce I/O request management
virt: acrn: Introduce PCI configuration space PIO accesses combiner
virt: acrn: Introduce interfaces for PCI device passthrough
virt: acrn: Introduce interrupt injection interfaces
virt: acrn: Introduce interfaces to query C-states and P-states
allowed by hypervisor
virt: acrn: Introduce I/O ranges operation interfaces
virt: acrn: Introduce ioeventfd
virt: acrn: Introduce irqfd
virt: acrn: Introduce an interface for Service VM to control vCPU

Yin Fengwei (1):
x86/acrn: Introduce an API to check if a VM is privileged

.../userspace-api/ioctl/ioctl-number.rst | 1 +
Documentation/virt/acrn/index.rst | 11 +
Documentation/virt/acrn/introduction.rst | 40 ++
Documentation/virt/acrn/io-request.rst | 97 +++
Documentation/virt/index.rst | 1 +
MAINTAINERS | 9 +
arch/x86/include/asm/acrn.h | 71 ++
arch/x86/kernel/cpu/acrn.c | 33 +-
drivers/virt/Kconfig | 2 +
drivers/virt/Makefile | 1 +
drivers/virt/acrn/Kconfig | 15 +
drivers/virt/acrn/Makefile | 3 +
drivers/virt/acrn/acrn_drv.h | 229 +++++++
drivers/virt/acrn/hsm.c | 435 ++++++++++++
drivers/virt/acrn/hypercall.h | 254 +++++++
drivers/virt/acrn/ioeventfd.c | 273 ++++++++
drivers/virt/acrn/ioreq.c | 645 ++++++++++++++++++
drivers/virt/acrn/irqfd.c | 235 +++++++
drivers/virt/acrn/mm.c | 305 +++++++++
drivers/virt/acrn/vm.c | 126 ++++
include/uapi/linux/acrn.h | 486 +++++++++++++
21 files changed, 3271 insertions(+), 1 deletion(-)
create mode 100644 Documentation/virt/acrn/index.rst
create mode 100644 Documentation/virt/acrn/introduction.rst
create mode 100644 Documentation/virt/acrn/io-request.rst
create mode 100644 arch/x86/include/asm/acrn.h
create mode 100644 drivers/virt/acrn/Kconfig
create mode 100644 drivers/virt/acrn/Makefile
create mode 100644 drivers/virt/acrn/acrn_drv.h
create mode 100644 drivers/virt/acrn/hsm.c
create mode 100644 drivers/virt/acrn/hypercall.h
create mode 100644 drivers/virt/acrn/ioeventfd.c
create mode 100644 drivers/virt/acrn/ioreq.c
create mode 100644 drivers/virt/acrn/irqfd.c
create mode 100644 drivers/virt/acrn/mm.c
create mode 100644 drivers/virt/acrn/vm.c
create mode 100644 include/uapi/linux/acrn.h


base-commit: 18445bf405cb331117bc98427b1ba6f12418ad17
--
2.28.0


2020-10-19 10:22:31

by Shuo Liu

[permalink] [raw]
Subject: [PATCH v5 17/17] virt: acrn: Introduce an interface for Service VM to control vCPU

From: Shuo Liu <[email protected]>

ACRN supports partition mode to achieve real-time requirements. In
partition mode, a CPU core can be dedicated to a vCPU of User VM. The
local APIC of the dedicated CPU core can be passthrough to the User VM.
The Service VM controls the assignment of the CPU cores.

Introduce an interface for the Service VM to remove the control of CPU
core from hypervisor perspective so that the CPU core can be a dedicated
CPU core of User VM.

Signed-off-by: Shuo Liu <[email protected]>
Reviewed-by: Zhi Wang <[email protected]>
Reviewed-by: Reinette Chatre <[email protected]>
Cc: Zhi Wang <[email protected]>
Cc: Zhenyu Wang <[email protected]>
Cc: Yu Wang <[email protected]>
Cc: Reinette Chatre <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
drivers/virt/acrn/hsm.c | 48 +++++++++++++++++++++++++++++++++++
drivers/virt/acrn/hypercall.h | 14 ++++++++++
2 files changed, 62 insertions(+)

diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
index c7290e177b1e..8c3799cc0313 100644
--- a/drivers/virt/acrn/hsm.c
+++ b/drivers/virt/acrn/hsm.c
@@ -9,6 +9,7 @@
* Yakui Zhao <[email protected]>
*/

+#include <linux/cpu.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -341,6 +342,52 @@ static int acrn_dev_release(struct inode *inode, struct file *filp)
return 0;
}

+static ssize_t remove_cpu_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u64 cpu, lapicid;
+ int ret;
+
+ if (kstrtoull(buf, 0, &cpu) < 0)
+ return -EINVAL;
+
+ if (cpu >= num_possible_cpus() || cpu == 0 || !cpu_is_hotpluggable(cpu))
+ return -EINVAL;
+
+ if (cpu_online(cpu))
+ remove_cpu(cpu);
+
+ lapicid = cpu_data(cpu).apicid;
+ dev_dbg(dev, "Try to remove cpu %lld with lapicid %lld\n", cpu, lapicid);
+ ret = hcall_sos_remove_cpu(lapicid);
+ if (ret < 0) {
+ dev_err(dev, "Failed to remove cpu %lld!\n", cpu);
+ goto fail_remove;
+ }
+
+ return count;
+
+fail_remove:
+ add_cpu(cpu);
+ return ret;
+}
+static DEVICE_ATTR_WO(remove_cpu);
+
+static struct attribute *acrn_attrs[] = {
+ &dev_attr_remove_cpu.attr,
+ NULL
+};
+
+static struct attribute_group acrn_attr_group = {
+ .attrs = acrn_attrs,
+};
+
+static const struct attribute_group *acrn_attr_groups[] = {
+ &acrn_attr_group,
+ NULL
+};
+
static const struct file_operations acrn_fops = {
.owner = THIS_MODULE,
.open = acrn_dev_open,
@@ -352,6 +399,7 @@ struct miscdevice acrn_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "acrn_hsm",
.fops = &acrn_fops,
+ .groups = acrn_attr_groups,
};

static int __init hsm_init(void)
diff --git a/drivers/virt/acrn/hypercall.h b/drivers/virt/acrn/hypercall.h
index e640632366f0..0cfad05bd1a9 100644
--- a/drivers/virt/acrn/hypercall.h
+++ b/drivers/virt/acrn/hypercall.h
@@ -13,6 +13,9 @@

#define HC_ID 0x80UL

+#define HC_ID_GEN_BASE 0x0UL
+#define HC_SOS_REMOVE_CPU _HC_ID(HC_ID, HC_ID_GEN_BASE + 0x01)
+
#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)
@@ -42,6 +45,17 @@
#define HC_ID_PM_BASE 0x80UL
#define HC_PM_GET_CPU_STATE _HC_ID(HC_ID, HC_ID_PM_BASE + 0x00)

+/**
+ * hcall_sos_remove_cpu() - Remove a vCPU of Service VM
+ * @cpu: The vCPU to be removed
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_sos_remove_cpu(u64 cpu)
+{
+ return acrn_hypercall1(HC_SOS_REMOVE_CPU, cpu);
+}
+
/**
* hcall_create_vm() - Create a User VM
* @vminfo: Service VM GPA of info of User VM creation
--
2.28.0

2020-10-19 10:22:43

by Shuo Liu

[permalink] [raw]
Subject: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

From: Shuo Liu <[email protected]>

A virtual CPU of User VM has different context due to the different
registers state. ACRN userspace needs to set the virtual CPU
registers state (e.g. giving a initial registers state to a virtual
BSP of a User VM).

HSM provides an ioctl ACRN_IOCTL_SET_VCPU_REGS to do the virtual CPU
registers state setting. The ioctl passes the registers state from ACRN
userspace to the hypervisor directly.

Signed-off-by: Shuo Liu <[email protected]>
Reviewed-by: Zhi Wang <[email protected]>
Reviewed-by: Reinette Chatre <[email protected]>
Cc: Zhi Wang <[email protected]>
Cc: Zhenyu Wang <[email protected]>
Cc: Yu Wang <[email protected]>
Cc: Reinette Chatre <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
drivers/virt/acrn/hsm.c | 15 ++++++++
drivers/virt/acrn/hypercall.h | 13 +++++++
include/uapi/linux/acrn.h | 71 +++++++++++++++++++++++++++++++++++
3 files changed, 99 insertions(+)

diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
index cbda67d4eb89..58ceb02e82db 100644
--- a/drivers/virt/acrn/hsm.c
+++ b/drivers/virt/acrn/hsm.c
@@ -9,6 +9,7 @@
* Yakui Zhao <[email protected]>
*/

+#include <linux/io.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -46,6 +47,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
{
struct acrn_vm *vm = filp->private_data;
struct acrn_vm_creation *vm_param;
+ struct acrn_vcpu_regs *cpu_regs;
int ret = 0;

if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) {
@@ -97,6 +99,19 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
case ACRN_IOCTL_DESTROY_VM:
ret = acrn_vm_destroy(vm);
break;
+ case ACRN_IOCTL_SET_VCPU_REGS:
+ cpu_regs = memdup_user((void __user *)ioctl_param,
+ sizeof(struct acrn_vcpu_regs));
+ if (IS_ERR(cpu_regs))
+ return PTR_ERR(cpu_regs);
+
+ ret = hcall_set_vcpu_regs(vm->vmid, virt_to_phys(cpu_regs));
+ if (ret < 0)
+ dev_dbg(acrn_dev.this_device,
+ "Failed to set regs state of VM%u!\n",
+ vm->vmid);
+ kfree(cpu_regs);
+ break;
default:
dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd);
ret = -ENOTTY;
diff --git a/drivers/virt/acrn/hypercall.h b/drivers/virt/acrn/hypercall.h
index 426b66cadb1f..f29cfae08862 100644
--- a/drivers/virt/acrn/hypercall.h
+++ b/drivers/virt/acrn/hypercall.h
@@ -19,6 +19,7 @@
#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_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)

/**
* hcall_create_vm() - Create a User VM
@@ -75,4 +76,16 @@ static inline long hcall_reset_vm(u64 vmid)
return acrn_hypercall1(HC_RESET_VM, vmid);
}

+/**
+ * hcall_set_vcpu_regs() - Set up registers of virtual CPU of a User VM
+ * @vmid: User VM ID
+ * @regs_state: Service VM GPA of registers state
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_set_vcpu_regs(u64 vmid, u64 regs_state)
+{
+ return acrn_hypercall2(HC_SET_VCPU_REGS, vmid, regs_state);
+}
+
#endif /* __ACRN_HSM_HYPERCALL_H */
diff --git a/include/uapi/linux/acrn.h b/include/uapi/linux/acrn.h
index 364b1a783074..1d5b82e154fb 100644
--- a/include/uapi/linux/acrn.h
+++ b/include/uapi/linux/acrn.h
@@ -36,6 +36,75 @@ struct acrn_vm_creation {
__u8 reserved2[8];
} __attribute__((aligned(8)));

+struct acrn_gp_regs {
+ __u64 rax;
+ __u64 rcx;
+ __u64 rdx;
+ __u64 rbx;
+ __u64 rsp;
+ __u64 rbp;
+ __u64 rsi;
+ __u64 rdi;
+ __u64 r8;
+ __u64 r9;
+ __u64 r10;
+ __u64 r11;
+ __u64 r12;
+ __u64 r13;
+ __u64 r14;
+ __u64 r15;
+};
+
+struct acrn_descriptor_ptr {
+ __u16 limit;
+ __u64 base;
+ __u16 reserved[3];
+} __attribute__ ((__packed__));
+
+struct acrn_regs {
+ struct acrn_gp_regs gprs;
+ struct acrn_descriptor_ptr gdt;
+ struct acrn_descriptor_ptr idt;
+
+ __u64 rip;
+ __u64 cs_base;
+ __u64 cr0;
+ __u64 cr4;
+ __u64 cr3;
+ __u64 ia32_efer;
+ __u64 rflags;
+ __u64 reserved_64[4];
+
+ __u32 cs_ar;
+ __u32 cs_limit;
+ __u32 reserved_32[3];
+
+ __u16 cs_sel;
+ __u16 ss_sel;
+ __u16 ds_sel;
+ __u16 es_sel;
+ __u16 fs_sel;
+ __u16 gs_sel;
+ __u16 ldt_sel;
+ __u16 tr_sel;
+
+ __u16 reserved_16[4];
+};
+
+/**
+ * struct acrn_vcpu_regs - Info of vCPU registers state
+ * @vcpu_id: vCPU ID
+ * @reserved0: Reserved
+ * @vcpu_regs: vCPU registers state
+ *
+ * This structure will be passed to hypervisor directly.
+ */
+struct acrn_vcpu_regs {
+ __u16 vcpu_id;
+ __u16 reserved0[3];
+ struct acrn_regs vcpu_regs;
+} __attribute__((aligned(8)));
+
/* The ioctl type, documented in ioctl-number.rst */
#define ACRN_IOCTL_TYPE 0xA2

@@ -52,5 +121,7 @@ struct acrn_vm_creation {
_IO(ACRN_IOCTL_TYPE, 0x13)
#define ACRN_IOCTL_RESET_VM \
_IO(ACRN_IOCTL_TYPE, 0x15)
+#define ACRN_IOCTL_SET_VCPU_REGS \
+ _IOW(ACRN_IOCTL_TYPE, 0x16, struct acrn_vcpu_regs)

#endif /* _UAPI_ACRN_H */
--
2.28.0

2020-10-19 20:49:42

by Shuo Liu

[permalink] [raw]
Subject: [PATCH v5 16/17] virt: acrn: Introduce irqfd

From: Shuo Liu <[email protected]>

irqfd is a mechanism to inject a specific interrupt to a User VM using a
decoupled eventfd mechanism.

Vhost is a kernel-level virtio server which uses eventfd for interrupt
injection. To support vhost on ACRN, irqfd is introduced in HSM.

HSM provides ioctls to associate a virtual Message Signaled Interrupt
(MSI) with an eventfd. The corresponding virtual MSI will be injected
into a User VM once the eventfd got signal.

Signed-off-by: Shuo Liu <[email protected]>
Reviewed-by: Zhi Wang <[email protected]>
Reviewed-by: Reinette Chatre <[email protected]>
Cc: Zhi Wang <[email protected]>
Cc: Zhenyu Wang <[email protected]>
Cc: Yu Wang <[email protected]>
Cc: Reinette Chatre <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
drivers/virt/acrn/Makefile | 2 +-
drivers/virt/acrn/acrn_drv.h | 10 ++
drivers/virt/acrn/hsm.c | 7 ++
drivers/virt/acrn/irqfd.c | 235 +++++++++++++++++++++++++++++++++++
drivers/virt/acrn/vm.c | 3 +
include/uapi/linux/acrn.h | 15 +++
6 files changed, 271 insertions(+), 1 deletion(-)
create mode 100644 drivers/virt/acrn/irqfd.c

diff --git a/drivers/virt/acrn/Makefile b/drivers/virt/acrn/Makefile
index 755b583b32ca..08ce641dcfa1 100644
--- a/drivers/virt/acrn/Makefile
+++ b/drivers/virt/acrn/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ACRN_HSM) := acrn.o
-acrn-y := hsm.o vm.o mm.o ioreq.o ioeventfd.o
+acrn-y := hsm.o vm.o mm.o ioreq.o ioeventfd.o irqfd.o
diff --git a/drivers/virt/acrn/acrn_drv.h b/drivers/virt/acrn/acrn_drv.h
index c66c620b9f10..8354d0d5881c 100644
--- a/drivers/virt/acrn/acrn_drv.h
+++ b/drivers/virt/acrn/acrn_drv.h
@@ -161,6 +161,9 @@ extern rwlock_t acrn_vm_list_lock;
* @ioeventfds_lock: Lock to protect ioeventfds list
* @ioeventfds: List to link all hsm_ioeventfd
* @ioeventfd_client: I/O client for ioeventfds of the VM
+ * @irqfds_lock: Lock to protect irqfds list
+ * @irqfds: List to link all hsm_irqfd
+ * @irqfd_wq: Workqueue for irqfd async shutdown
*/
struct acrn_vm {
struct list_head list;
@@ -180,6 +183,9 @@ struct acrn_vm {
struct mutex ioeventfds_lock;
struct list_head ioeventfds;
struct acrn_ioreq_client *ioeventfd_client;
+ struct mutex irqfds_lock;
+ struct list_head irqfds;
+ struct workqueue_struct *irqfd_wq;
};

struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
@@ -216,4 +222,8 @@ int acrn_ioeventfd_init(struct acrn_vm *vm);
int acrn_ioeventfd_config(struct acrn_vm *vm, struct acrn_ioeventfd *args);
void acrn_ioeventfd_deinit(struct acrn_vm *vm);

+int acrn_irqfd_init(struct acrn_vm *vm);
+int acrn_irqfd_config(struct acrn_vm *vm, struct acrn_irqfd *args);
+void acrn_irqfd_deinit(struct acrn_vm *vm);
+
#endif /* __ACRN_HSM_DRV_H */
diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
index 16f0280148f3..c7290e177b1e 100644
--- a/drivers/virt/acrn/hsm.c
+++ b/drivers/virt/acrn/hsm.c
@@ -115,6 +115,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
struct acrn_vm_memmap memmap;
struct acrn_msi_entry *msi;
struct acrn_pcidev *pcidev;
+ struct acrn_irqfd irqfd;
struct page *page;
u64 cstate_cmd;
int ret = 0;
@@ -317,6 +318,12 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,

ret = acrn_ioeventfd_config(vm, &ioeventfd);
break;
+ case ACRN_IOCTL_IRQFD:
+ if (copy_from_user(&irqfd, (void __user *)ioctl_param,
+ sizeof(irqfd)))
+ return -EFAULT;
+ ret = acrn_irqfd_config(vm, &irqfd);
+ break;
default:
dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd);
ret = -ENOTTY;
diff --git a/drivers/virt/acrn/irqfd.c b/drivers/virt/acrn/irqfd.c
new file mode 100644
index 000000000000..a8766d528e29
--- /dev/null
+++ b/drivers/virt/acrn/irqfd.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ACRN HSM irqfd: use eventfd objects to inject virtual interrupts
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ * Authors:
+ * Shuo Liu <[email protected]>
+ * Yakui Zhao <[email protected]>
+ */
+
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+
+#include "acrn_drv.h"
+
+static LIST_HEAD(acrn_irqfd_clients);
+static DEFINE_MUTEX(acrn_irqfds_mutex);
+
+/**
+ * struct hsm_irqfd - Properties of HSM irqfd
+ * @vm: Associated VM pointer
+ * @wait: Entry of wait-queue
+ * @shutdown: Async shutdown work
+ * @eventfd: Associated eventfd
+ * @list: Entry within &acrn_vm.irqfds of irqfds of a VM
+ * @pt: Structure for select/poll on the associated eventfd
+ * @msi: MSI data
+ */
+struct hsm_irqfd {
+ struct acrn_vm *vm;
+ wait_queue_entry_t wait;
+ struct work_struct shutdown;
+ struct eventfd_ctx *eventfd;
+ struct list_head list;
+ poll_table pt;
+ struct acrn_msi_entry msi;
+};
+
+static void acrn_irqfd_inject(struct hsm_irqfd *irqfd)
+{
+ struct acrn_vm *vm = irqfd->vm;
+
+ acrn_msi_inject(vm, irqfd->msi.msi_addr,
+ irqfd->msi.msi_data);
+}
+
+static void hsm_irqfd_shutdown(struct hsm_irqfd *irqfd)
+{
+ u64 cnt;
+
+ lockdep_assert_held(&irqfd->vm->irqfds_lock);
+
+ /* remove from wait queue */
+ list_del_init(&irqfd->list);
+ eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt);
+ eventfd_ctx_put(irqfd->eventfd);
+ kfree(irqfd);
+}
+
+static void hsm_irqfd_shutdown_work(struct work_struct *work)
+{
+ struct hsm_irqfd *irqfd;
+ struct acrn_vm *vm;
+
+ irqfd = container_of(work, struct hsm_irqfd, shutdown);
+ vm = irqfd->vm;
+ mutex_lock(&vm->irqfds_lock);
+ if (!list_empty(&irqfd->list))
+ hsm_irqfd_shutdown(irqfd);
+ mutex_unlock(&vm->irqfds_lock);
+}
+
+/* Called with wqh->lock held and interrupts disabled */
+static int hsm_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode,
+ int sync, void *key)
+{
+ unsigned long poll_bits = (unsigned long)key;
+ struct hsm_irqfd *irqfd;
+ struct acrn_vm *vm;
+
+ irqfd = container_of(wait, struct hsm_irqfd, wait);
+ vm = irqfd->vm;
+ if (poll_bits & POLLIN)
+ /* An event has been signaled, inject an interrupt */
+ acrn_irqfd_inject(irqfd);
+
+ if (poll_bits & POLLHUP)
+ /* Do shutdown work in thread to hold wqh->lock */
+ queue_work(vm->irqfd_wq, &irqfd->shutdown);
+
+ return 0;
+}
+
+static void hsm_irqfd_poll_func(struct file *file, wait_queue_head_t *wqh,
+ poll_table *pt)
+{
+ struct hsm_irqfd *irqfd;
+
+ irqfd = container_of(pt, struct hsm_irqfd, pt);
+ add_wait_queue(wqh, &irqfd->wait);
+}
+
+/*
+ * Assign an eventfd to a VM and create a HSM irqfd associated with the
+ * eventfd. The properties of the HSM irqfd are built from a &struct
+ * acrn_irqfd.
+ */
+static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
+{
+ struct eventfd_ctx *eventfd = NULL;
+ struct hsm_irqfd *irqfd, *tmp;
+ unsigned int events;
+ struct fd f;
+ int ret = 0;
+
+ irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
+ if (!irqfd)
+ return -ENOMEM;
+
+ irqfd->vm = vm;
+ memcpy(&irqfd->msi, &args->msi, sizeof(args->msi));
+ INIT_LIST_HEAD(&irqfd->list);
+ INIT_WORK(&irqfd->shutdown, hsm_irqfd_shutdown_work);
+
+ f = fdget(args->fd);
+ if (!f.file) {
+ ret = -EBADF;
+ goto out;
+ }
+
+ eventfd = eventfd_ctx_fileget(f.file);
+ if (IS_ERR(eventfd)) {
+ ret = PTR_ERR(eventfd);
+ goto fail;
+ }
+
+ irqfd->eventfd = eventfd;
+
+ /*
+ * Install custom wake-up handling to be notified whenever underlying
+ * eventfd is signaled.
+ */
+ init_waitqueue_func_entry(&irqfd->wait, hsm_irqfd_wakeup);
+ init_poll_funcptr(&irqfd->pt, hsm_irqfd_poll_func);
+
+ mutex_lock(&vm->irqfds_lock);
+ list_for_each_entry(tmp, &vm->irqfds, list) {
+ if (irqfd->eventfd != tmp->eventfd)
+ continue;
+ ret = -EBUSY;
+ mutex_unlock(&vm->irqfds_lock);
+ goto fail;
+ }
+ list_add_tail(&irqfd->list, &vm->irqfds);
+ mutex_unlock(&vm->irqfds_lock);
+
+ /* Check the pending event in this stage */
+ events = f.file->f_op->poll(f.file, &irqfd->pt);
+
+ if (events & POLLIN)
+ acrn_irqfd_inject(irqfd);
+
+ fdput(f);
+ return 0;
+fail:
+ if (eventfd && !IS_ERR(eventfd))
+ eventfd_ctx_put(eventfd);
+
+ fdput(f);
+out:
+ kfree(irqfd);
+ return ret;
+}
+
+static int acrn_irqfd_deassign(struct acrn_vm *vm,
+ struct acrn_irqfd *args)
+{
+ struct hsm_irqfd *irqfd, *tmp;
+ struct eventfd_ctx *eventfd;
+
+ eventfd = eventfd_ctx_fdget(args->fd);
+ if (IS_ERR(eventfd))
+ return PTR_ERR(eventfd);
+
+ mutex_lock(&vm->irqfds_lock);
+ list_for_each_entry_safe(irqfd, tmp, &vm->irqfds, list) {
+ if (irqfd->eventfd == eventfd) {
+ hsm_irqfd_shutdown(irqfd);
+ break;
+ }
+ }
+ mutex_unlock(&vm->irqfds_lock);
+ eventfd_ctx_put(eventfd);
+
+ return 0;
+}
+
+int acrn_irqfd_config(struct acrn_vm *vm, struct acrn_irqfd *args)
+{
+ int ret;
+
+ if (args->flags & ACRN_IRQFD_FLAG_DEASSIGN)
+ ret = acrn_irqfd_deassign(vm, args);
+ else
+ ret = acrn_irqfd_assign(vm, args);
+
+ return ret;
+}
+
+int acrn_irqfd_init(struct acrn_vm *vm)
+{
+ INIT_LIST_HEAD(&vm->irqfds);
+ mutex_init(&vm->irqfds_lock);
+ vm->irqfd_wq = alloc_workqueue("acrn_irqfd-%u", 0, 0, vm->vmid);
+ if (!vm->irqfd_wq)
+ return -ENOMEM;
+
+ dev_dbg(acrn_dev.this_device, "VM %u irqfd init.\n", vm->vmid);
+ return 0;
+}
+
+void acrn_irqfd_deinit(struct acrn_vm *vm)
+{
+ struct hsm_irqfd *irqfd, *next;
+
+ dev_dbg(acrn_dev.this_device, "VM %u irqfd deinit.\n", vm->vmid);
+ destroy_workqueue(vm->irqfd_wq);
+ mutex_lock(&vm->irqfds_lock);
+ list_for_each_entry_safe(irqfd, next, &vm->irqfds, list)
+ hsm_irqfd_shutdown(irqfd);
+ mutex_unlock(&vm->irqfds_lock);
+}
diff --git a/drivers/virt/acrn/vm.c b/drivers/virt/acrn/vm.c
index 3c671b03b273..7f152a74b591 100644
--- a/drivers/virt/acrn/vm.c
+++ b/drivers/virt/acrn/vm.c
@@ -51,6 +51,7 @@ struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
write_unlock_bh(&acrn_vm_list_lock);

acrn_ioeventfd_init(vm);
+ acrn_irqfd_init(vm);
dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid);
return vm;
}
@@ -69,7 +70,9 @@ int acrn_vm_destroy(struct acrn_vm *vm)
write_unlock_bh(&acrn_vm_list_lock);

acrn_ioeventfd_deinit(vm);
+ acrn_irqfd_deinit(vm);
acrn_ioreq_deinit(vm);
+
if (vm->monitor_page) {
put_page(vm->monitor_page);
vm->monitor_page = NULL;
diff --git a/include/uapi/linux/acrn.h b/include/uapi/linux/acrn.h
index 7a99124c7d4d..75a687838a43 100644
--- a/include/uapi/linux/acrn.h
+++ b/include/uapi/linux/acrn.h
@@ -411,6 +411,19 @@ struct acrn_ioeventfd {
__u64 data;
};

+#define ACRN_IRQFD_FLAG_DEASSIGN 0x01
+/**
+ * struct acrn_irqfd - Data to operate a &struct hsm_irqfd
+ * @fd: The fd of eventfd associated with a hsm_irqfd
+ * @flags: Logical-OR of ACRN_IRQFD_FLAG_*
+ * @msi: Info of MSI associated with the irqfd
+ */
+struct acrn_irqfd {
+ __s32 fd;
+ __u32 flags;
+ struct acrn_msi_entry msi;
+};
+
/* The ioctl type, documented in ioctl-number.rst */
#define ACRN_IOCTL_TYPE 0xA2

@@ -467,5 +480,7 @@ struct acrn_ioeventfd {

#define ACRN_IOCTL_IOEVENTFD \
_IOW(ACRN_IOCTL_TYPE, 0x70, struct acrn_ioeventfd)
+#define ACRN_IOCTL_IRQFD \
+ _IOW(ACRN_IOCTL_TYPE, 0x71, struct acrn_irqfd)

#endif /* _UAPI_ACRN_H */
--
2.28.0

2020-10-19 21:12:17

by Shuo Liu

[permalink] [raw]
Subject: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

From: Shuo Liu <[email protected]>

The VM management interfaces expose several VM operations to ACRN
userspace via ioctls. For example, creating VM, starting VM, destroying
VM and so on.

The ACRN Hypervisor needs to exchange data with the ACRN userspace
during the VM operations. HSM provides VM operation ioctls to the ACRN
userspace and communicates with the ACRN Hypervisor for VM operations
via hypercalls.

HSM maintains a list of User VM. Each User VM will be bound to an
existing file descriptor of /dev/acrn_hsm. The User VM will be
destroyed when the file descriptor is closed.

Signed-off-by: Shuo Liu <[email protected]>
Reviewed-by: Zhi Wang <[email protected]>
Reviewed-by: Reinette Chatre <[email protected]>
Cc: Zhi Wang <[email protected]>
Cc: Zhenyu Wang <[email protected]>
Cc: Yu Wang <[email protected]>
Cc: Reinette Chatre <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
---
.../userspace-api/ioctl/ioctl-number.rst | 1 +
MAINTAINERS | 1 +
drivers/virt/acrn/Makefile | 2 +-
drivers/virt/acrn/acrn_drv.h | 21 ++++-
drivers/virt/acrn/hsm.c | 73 ++++++++++++++++-
drivers/virt/acrn/hypercall.h | 78 +++++++++++++++++++
drivers/virt/acrn/vm.c | 68 ++++++++++++++++
include/uapi/linux/acrn.h | 56 +++++++++++++
8 files changed, 296 insertions(+), 4 deletions(-)
create mode 100644 drivers/virt/acrn/hypercall.h
create mode 100644 drivers/virt/acrn/vm.c
create mode 100644 include/uapi/linux/acrn.h

diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 2a198838fca9..ac60efedb104 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -319,6 +319,7 @@ Code Seq# Include File Comments
0xA0 all linux/sdp/sdp.h Industrial Device Project
<mailto:[email protected]>
0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver
+0xA2 all uapi/linux/acrn.h ACRN hypervisor
0xA3 80-8F Port ACL in development:
<mailto:[email protected]>
0xA3 90-9F linux/dtlk.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 3030d0e93d02..d4c1ef303c2d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -443,6 +443,7 @@ S: Supported
W: https://projectacrn.org
F: Documentation/virt/acrn/
F: drivers/virt/acrn/
+F: include/uapi/linux/acrn.h

AD1889 ALSA SOUND DRIVER
L: [email protected]
diff --git a/drivers/virt/acrn/Makefile b/drivers/virt/acrn/Makefile
index 6920ed798aaf..cf8b4ed5e74e 100644
--- a/drivers/virt/acrn/Makefile
+++ b/drivers/virt/acrn/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ACRN_HSM) := acrn.o
-acrn-y := hsm.o
+acrn-y := hsm.o vm.o
diff --git a/drivers/virt/acrn/acrn_drv.h b/drivers/virt/acrn/acrn_drv.h
index 29eedd696327..e5aba86cad8c 100644
--- a/drivers/virt/acrn/acrn_drv.h
+++ b/drivers/virt/acrn/acrn_drv.h
@@ -3,16 +3,35 @@
#ifndef __ACRN_HSM_DRV_H
#define __ACRN_HSM_DRV_H

+#include <linux/acrn.h>
+#include <linux/dev_printk.h>
+#include <linux/miscdevice.h>
#include <linux/types.h>

+#include "hypercall.h"
+
+extern struct miscdevice acrn_dev;
+
#define ACRN_INVALID_VMID (0xffffU)

+#define ACRN_VM_FLAG_DESTROYED 0U
/**
* struct acrn_vm - Properties of ACRN User VM.
+ * @list: Entry within global list of all VMs
* @vmid: User VM ID
+ * @vcpu_num: Number of virtual CPUs in the VM
+ * @flags: Flags (ACRN_VM_FLAG_*) of the VM. This is VM flag management
+ * in HSM which is different from the &acrn_vm_creation.vm_flag.
*/
struct acrn_vm {
- u16 vmid;
+ struct list_head list;
+ u16 vmid;
+ int vcpu_num;
+ unsigned long flags;
};

+struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
+ struct acrn_vm_creation *vm_param);
+int acrn_vm_destroy(struct acrn_vm *vm);
+
#endif /* __ACRN_HSM_DRV_H */
diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
index 28a3052ffa55..cbda67d4eb89 100644
--- a/drivers/virt/acrn/hsm.c
+++ b/drivers/virt/acrn/hsm.c
@@ -9,7 +9,6 @@
* Yakui Zhao <[email protected]>
*/

-#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -38,10 +37,79 @@ static int acrn_dev_open(struct inode *inode, struct file *filp)
return 0;
}

+/*
+ * HSM relies on hypercall layer of the ACRN hypervisor to do the
+ * sanity check against the input parameters.
+ */
+static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long ioctl_param)
+{
+ struct acrn_vm *vm = filp->private_data;
+ struct acrn_vm_creation *vm_param;
+ int ret = 0;
+
+ if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) {
+ dev_dbg(acrn_dev.this_device,
+ "ioctl 0x%x: Invalid VM state!\n", cmd);
+ return -EINVAL;
+ }
+
+ switch (cmd) {
+ case ACRN_IOCTL_CREATE_VM:
+ vm_param = memdup_user((void __user *)ioctl_param,
+ sizeof(struct acrn_vm_creation));
+ if (IS_ERR(vm_param))
+ return PTR_ERR(vm_param);
+
+ vm = acrn_vm_create(vm, vm_param);
+ if (!vm) {
+ ret = -EINVAL;
+ kfree(vm_param);
+ break;
+ }
+
+ if (copy_to_user((void __user *)ioctl_param, vm_param,
+ sizeof(struct acrn_vm_creation))) {
+ acrn_vm_destroy(vm);
+ ret = -EFAULT;
+ }
+
+ kfree(vm_param);
+ break;
+ case ACRN_IOCTL_START_VM:
+ ret = hcall_start_vm(vm->vmid);
+ if (ret < 0)
+ dev_dbg(acrn_dev.this_device,
+ "Failed to start VM %u!\n", vm->vmid);
+ break;
+ case ACRN_IOCTL_PAUSE_VM:
+ ret = hcall_pause_vm(vm->vmid);
+ if (ret < 0)
+ dev_dbg(acrn_dev.this_device,
+ "Failed to pause VM %u!\n", vm->vmid);
+ break;
+ case ACRN_IOCTL_RESET_VM:
+ ret = hcall_reset_vm(vm->vmid);
+ if (ret < 0)
+ dev_dbg(acrn_dev.this_device,
+ "Failed to restart VM %u!\n", vm->vmid);
+ break;
+ case ACRN_IOCTL_DESTROY_VM:
+ ret = acrn_vm_destroy(vm);
+ break;
+ default:
+ dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd);
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
+
static int acrn_dev_release(struct inode *inode, struct file *filp)
{
struct acrn_vm *vm = filp->private_data;

+ acrn_vm_destroy(vm);
kfree(vm);
return 0;
}
@@ -50,9 +118,10 @@ static const struct file_operations acrn_fops = {
.owner = THIS_MODULE,
.open = acrn_dev_open,
.release = acrn_dev_release,
+ .unlocked_ioctl = acrn_dev_ioctl,
};

-static struct miscdevice acrn_dev = {
+struct miscdevice acrn_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "acrn_hsm",
.fops = &acrn_fops,
diff --git a/drivers/virt/acrn/hypercall.h b/drivers/virt/acrn/hypercall.h
new file mode 100644
index 000000000000..426b66cadb1f
--- /dev/null
+++ b/drivers/virt/acrn/hypercall.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ACRN HSM: hypercalls of ACRN Hypervisor
+ */
+#ifndef __ACRN_HSM_HYPERCALL_H
+#define __ACRN_HSM_HYPERCALL_H
+#include <asm/acrn.h>
+
+/*
+ * Hypercall IDs of the ACRN Hypervisor
+ */
+#define _HC_ID(x, y) (((x) << 24) | (y))
+
+#define HC_ID 0x80UL
+
+#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_RESET_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x05)
+
+/**
+ * hcall_create_vm() - Create a User VM
+ * @vminfo: Service VM GPA of info of User VM creation
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_create_vm(u64 vminfo)
+{
+ return acrn_hypercall1(HC_CREATE_VM, vminfo);
+}
+
+/**
+ * hcall_start_vm() - Start a User VM
+ * @vmid: User VM ID
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_start_vm(u64 vmid)
+{
+ return acrn_hypercall1(HC_START_VM, vmid);
+}
+
+/**
+ * hcall_pause_vm() - Pause a User VM
+ * @vmid: User VM ID
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_pause_vm(u64 vmid)
+{
+ return acrn_hypercall1(HC_PAUSE_VM, vmid);
+}
+
+/**
+ * hcall_destroy_vm() - Destroy a User VM
+ * @vmid: User VM ID
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_destroy_vm(u64 vmid)
+{
+ return acrn_hypercall1(HC_DESTROY_VM, vmid);
+}
+
+/**
+ * hcall_reset_vm() - Reset a User VM
+ * @vmid: User VM ID
+ *
+ * Return: 0 on success, <0 on failure
+ */
+static inline long hcall_reset_vm(u64 vmid)
+{
+ return acrn_hypercall1(HC_RESET_VM, vmid);
+}
+
+#endif /* __ACRN_HSM_HYPERCALL_H */
diff --git a/drivers/virt/acrn/vm.c b/drivers/virt/acrn/vm.c
new file mode 100644
index 000000000000..3f667ac8ac1e
--- /dev/null
+++ b/drivers/virt/acrn/vm.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ACRN_HSM: Virtual Machine management
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ * Authors:
+ * Jason Chen CJ <[email protected]>
+ * Yakui Zhao <[email protected]>
+ */
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include "acrn_drv.h"
+
+/* List of VMs */
+static LIST_HEAD(acrn_vm_list);
+/* To protect acrn_vm_list */
+static DEFINE_MUTEX(acrn_vm_list_lock);
+
+struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
+ struct acrn_vm_creation *vm_param)
+{
+ int ret;
+
+ ret = hcall_create_vm(virt_to_phys(vm_param));
+ if (ret < 0 || vm_param->vmid == ACRN_INVALID_VMID) {
+ dev_err(acrn_dev.this_device,
+ "Failed to create VM! Error: %d\n", ret);
+ return NULL;
+ }
+
+ vm->vmid = vm_param->vmid;
+ vm->vcpu_num = vm_param->vcpu_num;
+
+ mutex_lock(&acrn_vm_list_lock);
+ list_add(&vm->list, &acrn_vm_list);
+ mutex_unlock(&acrn_vm_list_lock);
+
+ dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid);
+ return vm;
+}
+
+int acrn_vm_destroy(struct acrn_vm *vm)
+{
+ int ret;
+
+ if (vm->vmid == ACRN_INVALID_VMID ||
+ test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags))
+ return 0;
+
+ /* Remove from global VM list */
+ mutex_lock(&acrn_vm_list_lock);
+ list_del_init(&vm->list);
+ mutex_unlock(&acrn_vm_list_lock);
+
+ ret = hcall_destroy_vm(vm->vmid);
+ if (ret < 0) {
+ dev_err(acrn_dev.this_device,
+ "Failed to destroy VM %u\n", vm->vmid);
+ clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags);
+ return ret;
+ }
+ dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid);
+ vm->vmid = ACRN_INVALID_VMID;
+ return 0;
+}
diff --git a/include/uapi/linux/acrn.h b/include/uapi/linux/acrn.h
new file mode 100644
index 000000000000..364b1a783074
--- /dev/null
+++ b/include/uapi/linux/acrn.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
+ *
+ * This file can be used by applications that need to communicate with the HSM
+ * via the ioctl interface.
+ */
+
+#ifndef _UAPI_ACRN_H
+#define _UAPI_ACRN_H
+
+#include <linux/types.h>
+
+/**
+ * struct acrn_vm_creation - Info to create a User VM
+ * @vmid: User VM ID returned from the hypervisor
+ * @reserved0: Reserved
+ * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
+ * @reserved1: Reserved
+ * @uuid: UUID of the VM. Pass to hypervisor directly.
+ * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
+ * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
+ * hypervisor directly.
+ * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
+ * @reserved2: Reserved
+ */
+struct acrn_vm_creation {
+ __u16 vmid;
+ __u16 reserved0;
+ __u16 vcpu_num;
+ __u16 reserved1;
+ __u8 uuid[16];
+ __u64 vm_flag;
+ __u64 ioreq_buf;
+ __u64 cpu_affinity;
+ __u8 reserved2[8];
+} __attribute__((aligned(8)));
+
+/* The ioctl type, documented in ioctl-number.rst */
+#define ACRN_IOCTL_TYPE 0xA2
+
+/*
+ * Common IOCTL IDs definition for ACRN userspace
+ */
+#define ACRN_IOCTL_CREATE_VM \
+ _IOWR(ACRN_IOCTL_TYPE, 0x10, struct acrn_vm_creation)
+#define ACRN_IOCTL_DESTROY_VM \
+ _IO(ACRN_IOCTL_TYPE, 0x11)
+#define ACRN_IOCTL_START_VM \
+ _IO(ACRN_IOCTL_TYPE, 0x12)
+#define ACRN_IOCTL_PAUSE_VM \
+ _IO(ACRN_IOCTL_TYPE, 0x13)
+#define ACRN_IOCTL_RESET_VM \
+ _IO(ACRN_IOCTL_TYPE, 0x15)
+
+#endif /* _UAPI_ACRN_H */
--
2.28.0

2020-10-22 04:38:03

by Dave Hansen

[permalink] [raw]
Subject: Re: [PATCH v5 00/17] HSM driver for ACRN hypervisor

How widely is ACRN used? It is some little Intel toy hypervisor, or is
it already seeing broad use in the world? This, for instance, seems to
have a backport:

https://github.com/teslamotors/linux/tree/intel-4.14

2020-10-26 04:15:49

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 00/17] HSM driver for ACRN hypervisor

Hi Dave,

On Wed 21.Oct'20 at 8:19:10 -0700, Dave Hansen wrote:
>How widely is ACRN used? It is some little Intel toy hypervisor, or is
>it already seeing broad use in the world? This, for instance, seems to
>have a backport:
>
> https://github.com/teslamotors/linux/tree/intel-4.14

So far as i know, ACRN is not widely used now. But it indeed has a
commercial IVI (In-Vehicle Infotainment) product "Chery EXEED" [1].
Today ACRN also has several design wins in industrial domain. For tree
of teslamotors, we were unaware. I think teslamotors' tree was derived
from [2].

Thanks
shuo

[1] https://projectacrn.org/acrn-project-chery-exeed-launch/
[2] https://github.com/projectacrn/acrn-kernel

2020-11-05 00:47:23

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
> --- /dev/null
> +++ b/include/uapi/linux/acrn.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
> + *
> + * This file can be used by applications that need to communicate with the HSM
> + * via the ioctl interface.
> + */
> +
> +#ifndef _UAPI_ACRN_H
> +#define _UAPI_ACRN_H
> +
> +#include <linux/types.h>
> +
> +/**
> + * struct acrn_vm_creation - Info to create a User VM
> + * @vmid: User VM ID returned from the hypervisor
> + * @reserved0: Reserved
> + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
> + * @reserved1: Reserved
> + * @uuid: UUID of the VM. Pass to hypervisor directly.
> + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
> + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
> + * hypervisor directly.
> + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
> + * @reserved2: Reserved

Reserved and must be 0? What are they reserved for?

Same for all of the reserved fields, why?

> + */
> +struct acrn_vm_creation {
> + __u16 vmid;
> + __u16 reserved0;
> + __u16 vcpu_num;
> + __u16 reserved1;
> + __u8 uuid[16];

We have a userspace-visable uid structure in include/uapi/uuid.h, why
not use that?

thanks,

greg k-h

2020-11-05 04:59:30

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
>On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
>> --- /dev/null
>> +++ b/include/uapi/linux/acrn.h
>> @@ -0,0 +1,56 @@
>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> +/*
>> + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
>> + *
>> + * This file can be used by applications that need to communicate with the HSM
>> + * via the ioctl interface.
>> + */
>> +
>> +#ifndef _UAPI_ACRN_H
>> +#define _UAPI_ACRN_H
>> +
>> +#include <linux/types.h>
>> +
>> +/**
>> + * struct acrn_vm_creation - Info to create a User VM
>> + * @vmid: User VM ID returned from the hypervisor
>> + * @reserved0: Reserved
>> + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
>> + * @reserved1: Reserved
>> + * @uuid: UUID of the VM. Pass to hypervisor directly.
>> + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
>> + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
>> + * hypervisor directly.
>> + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
>> + * @reserved2: Reserved
>
>Reserved and must be 0?

Not a must.

>What are they reserved for?
>
>Same for all of the reserved fields, why?

Some reserved fields are to map layout in the hypervisor side, others
are for future use.

>
>> + */
>> +struct acrn_vm_creation {
>> + __u16 vmid;
>> + __u16 reserved0;
>> + __u16 vcpu_num;
>> + __u16 reserved1;
>> + __u8 uuid[16];
>
>We have a userspace-visable uid structure in include/uapi/uuid.h, why
>not use that?

we just pass the uuid data from user space to hypervisor. So, we can
remove a header dependeny with using raw data format.

Thanks
shuo

2020-11-05 06:45:17

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu, Nov 05, 2020 at 11:10:29AM +0800, Shuo A Liu wrote:
> On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
> > On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
> > > --- /dev/null
> > > +++ b/include/uapi/linux/acrn.h
> > > @@ -0,0 +1,56 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > +/*
> > > + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
> > > + *
> > > + * This file can be used by applications that need to communicate with the HSM
> > > + * via the ioctl interface.
> > > + */
> > > +
> > > +#ifndef _UAPI_ACRN_H
> > > +#define _UAPI_ACRN_H
> > > +
> > > +#include <linux/types.h>
> > > +
> > > +/**
> > > + * struct acrn_vm_creation - Info to create a User VM
> > > + * @vmid: User VM ID returned from the hypervisor
> > > + * @reserved0: Reserved
> > > + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
> > > + * @reserved1: Reserved
> > > + * @uuid: UUID of the VM. Pass to hypervisor directly.
> > > + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
> > > + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
> > > + * hypervisor directly.
> > > + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
> > > + * @reserved2: Reserved
> >
> > Reserved and must be 0?
>
> Not a must.

That's guaranteed to come back and bite you in the end. You all have
read the "how to write a good api" document, right?

> > What are they reserved for?
> >
> > Same for all of the reserved fields, why?
>
> Some reserved fields are to map layout in the hypervisor side, others
> are for future use.

ioctls should not have these, again, please read the documentation. If
you need something new in the future, just make a new ioctl.

> > > + */
> > > +struct acrn_vm_creation {
> > > + __u16 vmid;
> > > + __u16 reserved0;
> > > + __u16 vcpu_num;
> > > + __u16 reserved1;
> > > + __u8 uuid[16];
> >
> > We have a userspace-visable uid structure in include/uapi/uuid.h, why
> > not use that?
>
> we just pass the uuid data from user space to hypervisor. So, we can
> remove a header dependeny with using raw data format.

I do not understand this, please use the built-in kernel types we have.

thanks,

greg k-h

2020-11-05 07:38:43

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu 5.Nov'20 at 7:29:07 +0100, Greg Kroah-Hartman wrote:
>On Thu, Nov 05, 2020 at 11:10:29AM +0800, Shuo A Liu wrote:
>> On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
>> > On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
>> > > --- /dev/null
>> > > +++ b/include/uapi/linux/acrn.h
>> > > @@ -0,0 +1,56 @@
>> > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > > +/*
>> > > + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
>> > > + *
>> > > + * This file can be used by applications that need to communicate with the HSM
>> > > + * via the ioctl interface.
>> > > + */
>> > > +
>> > > +#ifndef _UAPI_ACRN_H
>> > > +#define _UAPI_ACRN_H
>> > > +
>> > > +#include <linux/types.h>
>> > > +
>> > > +/**
>> > > + * struct acrn_vm_creation - Info to create a User VM
>> > > + * @vmid: User VM ID returned from the hypervisor
>> > > + * @reserved0: Reserved
>> > > + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
>> > > + * @reserved1: Reserved
>> > > + * @uuid: UUID of the VM. Pass to hypervisor directly.
>> > > + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
>> > > + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
>> > > + * hypervisor directly.
>> > > + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
>> > > + * @reserved2: Reserved
>> >
>> > Reserved and must be 0?
>>
>> Not a must.
>
>That's guaranteed to come back and bite you in the end.

OK. I can fill them with zero before passing them to hypervisor.

>You all have read the "how to write a good api" document, right?

Is it Documentation/driver-api/ioctl.rst? Or i missed..

>
>> > What are they reserved for?
>> >
>> > Same for all of the reserved fields, why?
>>
>> Some reserved fields are to map layout in the hypervisor side, others
>> are for future use.
>
>ioctls should not have these, again, please read the documentation. If
>you need something new in the future, just make a new ioctl.

OK. I will remove some reserved fields for scalability. Though i can
keep some reserved fields for alignment (and to keep same data structure
layout with the hypervisor), right?
Documentation/driver-api/ioctl.rst says that explicit reserved fields
could be used.

>
>> > > + */
>> > > +struct acrn_vm_creation {
>> > > + __u16 vmid;
>> > > + __u16 reserved0;
>> > > + __u16 vcpu_num;
>> > > + __u16 reserved1;
>> > > + __u8 uuid[16];
>> >
>> > We have a userspace-visable uid structure in include/uapi/uuid.h, why
>> > not use that?
>>
>> we just pass the uuid data from user space to hypervisor. So, we can
>> remove a header dependeny with using raw data format.
>
>I do not understand this, please use the built-in kernel types we have.

OK. I will use that.

Thanks
shuo

2020-11-05 08:30:10

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu, Nov 05, 2020 at 03:35:45PM +0800, Shuo A Liu wrote:
> On Thu 5.Nov'20 at 7:29:07 +0100, Greg Kroah-Hartman wrote:
> > On Thu, Nov 05, 2020 at 11:10:29AM +0800, Shuo A Liu wrote:
> > > On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
> > > > On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
> > > > > --- /dev/null
> > > > > +++ b/include/uapi/linux/acrn.h
> > > > > @@ -0,0 +1,56 @@
> > > > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > > +/*
> > > > > + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
> > > > > + *
> > > > > + * This file can be used by applications that need to communicate with the HSM
> > > > > + * via the ioctl interface.
> > > > > + */
> > > > > +
> > > > > +#ifndef _UAPI_ACRN_H
> > > > > +#define _UAPI_ACRN_H
> > > > > +
> > > > > +#include <linux/types.h>
> > > > > +
> > > > > +/**
> > > > > + * struct acrn_vm_creation - Info to create a User VM
> > > > > + * @vmid: User VM ID returned from the hypervisor
> > > > > + * @reserved0: Reserved
> > > > > + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
> > > > > + * @reserved1: Reserved
> > > > > + * @uuid: UUID of the VM. Pass to hypervisor directly.
> > > > > + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
> > > > > + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
> > > > > + * hypervisor directly.
> > > > > + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
> > > > > + * @reserved2: Reserved
> > > >
> > > > Reserved and must be 0?
> > >
> > > Not a must.
> >
> > That's guaranteed to come back and bite you in the end.
>
> OK. I can fill them with zero before passing them to hypervisor.
>
> > You all have read the "how to write a good api" document, right?
>
> Is it Documentation/driver-api/ioctl.rst? Or i missed..

That's one good document, but no, not what I was referring to. I was
thinking of Documentation/process/adding-syscalls.rst, which is what you
are doing here implicitly with these new ioctls (every ioctl is a brand
new syscall.)

> > > > What are they reserved for?
> > > >
> > > > Same for all of the reserved fields, why?
> > >
> > > Some reserved fields are to map layout in the hypervisor side, others
> > > are for future use.
> >
> > ioctls should not have these, again, please read the documentation. If
> > you need something new in the future, just make a new ioctl.
>
> OK. I will remove some reserved fields for scalability.

"scalability" should have nothing to do with any of this, right? What
am I missing?

> Though i can
> keep some reserved fields for alignment (and to keep same data structure
> layout with the hypervisor), right?
> Documentation/driver-api/ioctl.rst says that explicit reserved fields
> could be used.

If you need alignment, yes, that is fine, but that's not what you are
saying these are for. And if you need alignment, why not move things
around so they are properly aligned.

And this structure has nothing to do with the hypervisor structure,
that's a internal-kernel structure, not a userspace-visable thing if you
are doing things correctly.

As an example of all of this type of review and conversation, please
refer to the review of the recent nitro_enclaves code that got merged.
All of the discussions there about ioctls are also relevant here.

thanks,

greg k-h

2020-11-05 09:05:06

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu 5.Nov'20 at 9:26:39 +0100, Greg Kroah-Hartman wrote:
>On Thu, Nov 05, 2020 at 03:35:45PM +0800, Shuo A Liu wrote:
>> On Thu 5.Nov'20 at 7:29:07 +0100, Greg Kroah-Hartman wrote:
>> > On Thu, Nov 05, 2020 at 11:10:29AM +0800, Shuo A Liu wrote:
>> > > On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
>> > > > On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
>> > > > > --- /dev/null
>> > > > > +++ b/include/uapi/linux/acrn.h
>> > > > > @@ -0,0 +1,56 @@
>> > > > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > > > > +/*
>> > > > > + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
>> > > > > + *
>> > > > > + * This file can be used by applications that need to communicate with the HSM
>> > > > > + * via the ioctl interface.
>> > > > > + */
>> > > > > +
>> > > > > +#ifndef _UAPI_ACRN_H
>> > > > > +#define _UAPI_ACRN_H
>> > > > > +
>> > > > > +#include <linux/types.h>
>> > > > > +
>> > > > > +/**
>> > > > > + * struct acrn_vm_creation - Info to create a User VM
>> > > > > + * @vmid: User VM ID returned from the hypervisor
>> > > > > + * @reserved0: Reserved
>> > > > > + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
>> > > > > + * @reserved1: Reserved
>> > > > > + * @uuid: UUID of the VM. Pass to hypervisor directly.
>> > > > > + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
>> > > > > + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
>> > > > > + * hypervisor directly.
>> > > > > + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
>> > > > > + * @reserved2: Reserved
>> > > >
>> > > > Reserved and must be 0?
>> > >
>> > > Not a must.
>> >
>> > That's guaranteed to come back and bite you in the end.
>>
>> OK. I can fill them with zero before passing them to hypervisor.
>>
>> > You all have read the "how to write a good api" document, right?
>>
>> Is it Documentation/driver-api/ioctl.rst? Or i missed..
>
>That's one good document, but no, not what I was referring to. I was
>thinking of Documentation/process/adding-syscalls.rst, which is what you
>are doing here implicitly with these new ioctls (every ioctl is a brand
>new syscall.)

I will read it as well. Thanks.

>
>> > > > What are they reserved for?
>> > > >
>> > > > Same for all of the reserved fields, why?
>> > >
>> > > Some reserved fields are to map layout in the hypervisor side, others
>> > > are for future use.
>> >
>> > ioctls should not have these, again, please read the documentation. If
>> > you need something new in the future, just make a new ioctl.
>>
>> OK. I will remove some reserved fields for scalability.
>
>"scalability" should have nothing to do with any of this, right? What
>am I missing?

Sorry, i meant reserved fields for future use.

>
>> Though i can
>> keep some reserved fields for alignment (and to keep same data structure
>> layout with the hypervisor), right?
>> Documentation/driver-api/ioctl.rst says that explicit reserved fields
>> could be used.
>
>If you need alignment, yes, that is fine, but that's not what you are
>saying these are for. And if you need alignment, why not move things
>around so they are properly aligned.
>
>And this structure has nothing to do with the hypervisor structure,
>that's a internal-kernel structure, not a userspace-visable thing if you
>are doing things correctly.

It's the same structure with the one in hypervisor. HSM driver
doesn't maintain the VM much, it just pass the data for VM creation from
userspace to hypervisor.

>
>As an example of all of this type of review and conversation, please
>refer to the review of the recent nitro_enclaves code that got merged.
>All of the discussions there about ioctls are also relevant here.

I will. Thanks very much.

Thanks
shuo

2020-11-05 09:19:37

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu, Nov 05, 2020 at 05:02:00PM +0800, Shuo A Liu wrote:
> On Thu 5.Nov'20 at 9:26:39 +0100, Greg Kroah-Hartman wrote:
> > On Thu, Nov 05, 2020 at 03:35:45PM +0800, Shuo A Liu wrote:
> > > On Thu 5.Nov'20 at 7:29:07 +0100, Greg Kroah-Hartman wrote:
> > > > On Thu, Nov 05, 2020 at 11:10:29AM +0800, Shuo A Liu wrote:
> > > > > On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
> > > > > > On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
> > > > > > > --- /dev/null
> > > > > > > +++ b/include/uapi/linux/acrn.h
> > > > > > > @@ -0,0 +1,56 @@
> > > > > > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > > > > +/*
> > > > > > > + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
> > > > > > > + *
> > > > > > > + * This file can be used by applications that need to communicate with the HSM
> > > > > > > + * via the ioctl interface.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#ifndef _UAPI_ACRN_H
> > > > > > > +#define _UAPI_ACRN_H
> > > > > > > +
> > > > > > > +#include <linux/types.h>
> > > > > > > +
> > > > > > > +/**
> > > > > > > + * struct acrn_vm_creation - Info to create a User VM
> > > > > > > + * @vmid: User VM ID returned from the hypervisor
> > > > > > > + * @reserved0: Reserved
> > > > > > > + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
> > > > > > > + * @reserved1: Reserved
> > > > > > > + * @uuid: UUID of the VM. Pass to hypervisor directly.
> > > > > > > + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
> > > > > > > + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
> > > > > > > + * hypervisor directly.
> > > > > > > + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
> > > > > > > + * @reserved2: Reserved
> > > > > >
> > > > > > Reserved and must be 0?
> > > > >
> > > > > Not a must.
> > > >
> > > > That's guaranteed to come back and bite you in the end.
> > >
> > > OK. I can fill them with zero before passing them to hypervisor.
> > >
> > > > You all have read the "how to write a good api" document, right?
> > >
> > > Is it Documentation/driver-api/ioctl.rst? Or i missed..
> >
> > That's one good document, but no, not what I was referring to. I was
> > thinking of Documentation/process/adding-syscalls.rst, which is what you
> > are doing here implicitly with these new ioctls (every ioctl is a brand
> > new syscall.)
>
> I will read it as well. Thanks.
>
> >
> > > > > > What are they reserved for?
> > > > > >
> > > > > > Same for all of the reserved fields, why?
> > > > >
> > > > > Some reserved fields are to map layout in the hypervisor side, others
> > > > > are for future use.
> > > >
> > > > ioctls should not have these, again, please read the documentation. If
> > > > you need something new in the future, just make a new ioctl.
> > >
> > > OK. I will remove some reserved fields for scalability.
> >
> > "scalability" should have nothing to do with any of this, right? What
> > am I missing?
>
> Sorry, i meant reserved fields for future use.

Again, this is not how you do that at all. If you need something "in
the future", create it then. What you are doing here ensures that you
will never be able to do it then either, so don't even pretend :)

Read the syscall document for why this is the case.

> > > Though i can
> > > keep some reserved fields for alignment (and to keep same data structure
> > > layout with the hypervisor), right?
> > > Documentation/driver-api/ioctl.rst says that explicit reserved fields
> > > could be used.
> >
> > If you need alignment, yes, that is fine, but that's not what you are
> > saying these are for. And if you need alignment, why not move things
> > around so they are properly aligned.
> >
> > And this structure has nothing to do with the hypervisor structure,
> > that's a internal-kernel structure, not a userspace-visable thing if you
> > are doing things correctly.
>
> It's the same structure with the one in hypervisor. HSM driver
> doesn't maintain the VM much, it just pass the data for VM creation from
> userspace to hypervisor.

That sounds ripe for abuse, good luck!

greg k-h

2020-11-05 12:50:43

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu 5.Nov'20 at 10:16:45 +0100, Greg Kroah-Hartman wrote:
>On Thu, Nov 05, 2020 at 05:02:00PM +0800, Shuo A Liu wrote:
>> On Thu 5.Nov'20 at 9:26:39 +0100, Greg Kroah-Hartman wrote:
>> > On Thu, Nov 05, 2020 at 03:35:45PM +0800, Shuo A Liu wrote:
>> > > On Thu 5.Nov'20 at 7:29:07 +0100, Greg Kroah-Hartman wrote:
>> > > > On Thu, Nov 05, 2020 at 11:10:29AM +0800, Shuo A Liu wrote:
>> > > > > On Wed 4.Nov'20 at 20:02:35 +0100, Greg Kroah-Hartman wrote:
>> > > > > > On Mon, Oct 19, 2020 at 02:17:52PM +0800, [email protected] wrote:
>> > > > > > > --- /dev/null
>> > > > > > > +++ b/include/uapi/linux/acrn.h
>> > > > > > > @@ -0,0 +1,56 @@
>> > > > > > > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > > > > > > +/*
>> > > > > > > + * Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
>> > > > > > > + *
>> > > > > > > + * This file can be used by applications that need to communicate with the HSM
>> > > > > > > + * via the ioctl interface.
>> > > > > > > + */
>> > > > > > > +
>> > > > > > > +#ifndef _UAPI_ACRN_H
>> > > > > > > +#define _UAPI_ACRN_H
>> > > > > > > +
>> > > > > > > +#include <linux/types.h>
>> > > > > > > +
>> > > > > > > +/**
>> > > > > > > + * struct acrn_vm_creation - Info to create a User VM
>> > > > > > > + * @vmid: User VM ID returned from the hypervisor
>> > > > > > > + * @reserved0: Reserved
>> > > > > > > + * @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
>> > > > > > > + * @reserved1: Reserved
>> > > > > > > + * @uuid: UUID of the VM. Pass to hypervisor directly.
>> > > > > > > + * @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
>> > > > > > > + * @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
>> > > > > > > + * hypervisor directly.
>> > > > > > > + * @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
>> > > > > > > + * @reserved2: Reserved
>> > > > > >
>> > > > > > Reserved and must be 0?
>> > > > >
>> > > > > Not a must.
>> > > >
>> > > > That's guaranteed to come back and bite you in the end.
>> > >
>> > > OK. I can fill them with zero before passing them to hypervisor.
>> > >
>> > > > You all have read the "how to write a good api" document, right?
>> > >
>> > > Is it Documentation/driver-api/ioctl.rst? Or i missed..
>> >
>> > That's one good document, but no, not what I was referring to. I was
>> > thinking of Documentation/process/adding-syscalls.rst, which is what you
>> > are doing here implicitly with these new ioctls (every ioctl is a brand
>> > new syscall.)
>>
>> I will read it as well. Thanks.
>>
>> >
>> > > > > > What are they reserved for?
>> > > > > >
>> > > > > > Same for all of the reserved fields, why?
>> > > > >
>> > > > > Some reserved fields are to map layout in the hypervisor side, others
>> > > > > are for future use.
>> > > >
>> > > > ioctls should not have these, again, please read the documentation. If
>> > > > you need something new in the future, just make a new ioctl.
>> > >
>> > > OK. I will remove some reserved fields for scalability.
>> >
>> > "scalability" should have nothing to do with any of this, right? What
>> > am I missing?
>>
>> Sorry, i meant reserved fields for future use.
>
>Again, this is not how you do that at all. If you need something "in
>the future", create it then. What you are doing here ensures that you
>will never be able to do it then either, so don't even pretend :)
>
>Read the syscall document for why this is the case.

Alright. I will remove that type of reserved fields. Thank you.

>
>> > > Though i can
>> > > keep some reserved fields for alignment (and to keep same data structure
>> > > layout with the hypervisor), right?
>> > > Documentation/driver-api/ioctl.rst says that explicit reserved fields
>> > > could be used.
>> >
>> > If you need alignment, yes, that is fine, but that's not what you are
>> > saying these are for. And if you need alignment, why not move things
>> > around so they are properly aligned.
>> >
>> > And this structure has nothing to do with the hypervisor structure,
>> > that's a internal-kernel structure, not a userspace-visable thing if you
>> > are doing things correctly.
>>
>> It's the same structure with the one in hypervisor. HSM driver
>> doesn't maintain the VM much, it just pass the data for VM creation from
>> userspace to hypervisor.
>
>That sounds ripe for abuse, good luck!

The hypervisor will do the sanity check. In this case, HSM driver can be
kept simple.

Thanks
shuo

2020-11-05 13:07:00

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 06/17] virt: acrn: Introduce VM management interfaces

On Thu, Nov 05, 2020 at 08:48:22PM +0800, Shuo A Liu wrote:
> > > > > Though i can
> > > > > keep some reserved fields for alignment (and to keep same data structure
> > > > > layout with the hypervisor), right?
> > > > > Documentation/driver-api/ioctl.rst says that explicit reserved fields
> > > > > could be used.
> > > >
> > > > If you need alignment, yes, that is fine, but that's not what you are
> > > > saying these are for. And if you need alignment, why not move things
> > > > around so they are properly aligned.
> > > >
> > > > And this structure has nothing to do with the hypervisor structure,
> > > > that's a internal-kernel structure, not a userspace-visable thing if you
> > > > are doing things correctly.
> > >
> > > It's the same structure with the one in hypervisor. HSM driver
> > > doesn't maintain the VM much, it just pass the data for VM creation from
> > > userspace to hypervisor.
> >
> > That sounds ripe for abuse, good luck!
>
> The hypervisor will do the sanity check. In this case, HSM driver can be
> kept simple.

Hah, good luck with the fuzzers, crashing a hypervisor will be fun for
them!

greg k-h

2020-11-09 17:10:46

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Mon, Oct 19, 2020 at 02:17:53PM +0800, [email protected] wrote:
> From: Shuo Liu <[email protected]>
>
> A virtual CPU of User VM has different context due to the different
> registers state. ACRN userspace needs to set the virtual CPU
> registers state (e.g. giving a initial registers state to a virtual
> BSP of a User VM).
>
> HSM provides an ioctl ACRN_IOCTL_SET_VCPU_REGS to do the virtual CPU
> registers state setting. The ioctl passes the registers state from ACRN
> userspace to the hypervisor directly.
>
> Signed-off-by: Shuo Liu <[email protected]>
> Reviewed-by: Zhi Wang <[email protected]>
> Reviewed-by: Reinette Chatre <[email protected]>
> Cc: Zhi Wang <[email protected]>
> Cc: Zhenyu Wang <[email protected]>
> Cc: Yu Wang <[email protected]>
> Cc: Reinette Chatre <[email protected]>
> Cc: Greg Kroah-Hartman <[email protected]>
> ---
> drivers/virt/acrn/hsm.c | 15 ++++++++
> drivers/virt/acrn/hypercall.h | 13 +++++++
> include/uapi/linux/acrn.h | 71 +++++++++++++++++++++++++++++++++++
> 3 files changed, 99 insertions(+)
>
> diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
> index cbda67d4eb89..58ceb02e82db 100644
> --- a/drivers/virt/acrn/hsm.c
> +++ b/drivers/virt/acrn/hsm.c
> @@ -9,6 +9,7 @@
> * Yakui Zhao <[email protected]>
> */
>
> +#include <linux/io.h>
> #include <linux/mm.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> @@ -46,6 +47,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
> {
> struct acrn_vm *vm = filp->private_data;
> struct acrn_vm_creation *vm_param;
> + struct acrn_vcpu_regs *cpu_regs;
> int ret = 0;
>
> if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) {
> @@ -97,6 +99,19 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
> case ACRN_IOCTL_DESTROY_VM:
> ret = acrn_vm_destroy(vm);
> break;
> + case ACRN_IOCTL_SET_VCPU_REGS:
> + cpu_regs = memdup_user((void __user *)ioctl_param,
> + sizeof(struct acrn_vcpu_regs));
> + if (IS_ERR(cpu_regs))
> + return PTR_ERR(cpu_regs);
> +
> + ret = hcall_set_vcpu_regs(vm->vmid, virt_to_phys(cpu_regs));

Why the virt_to_phys() call here? And there really is no validation of
any fields?

> + if (ret < 0)
> + dev_dbg(acrn_dev.this_device,

Wait, a global, static device? Where did I miss that? That feels odd,
why is there just one?



> + "Failed to set regs state of VM%u!\n",
> + vm->vmid);
> + kfree(cpu_regs);
> + break;
> default:
> dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd);
> ret = -ENOTTY;
> diff --git a/drivers/virt/acrn/hypercall.h b/drivers/virt/acrn/hypercall.h
> index 426b66cadb1f..f29cfae08862 100644
> --- a/drivers/virt/acrn/hypercall.h
> +++ b/drivers/virt/acrn/hypercall.h
> @@ -19,6 +19,7 @@
> #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_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)
>
> /**
> * hcall_create_vm() - Create a User VM
> @@ -75,4 +76,16 @@ static inline long hcall_reset_vm(u64 vmid)
> return acrn_hypercall1(HC_RESET_VM, vmid);
> }
>
> +/**
> + * hcall_set_vcpu_regs() - Set up registers of virtual CPU of a User VM
> + * @vmid: User VM ID
> + * @regs_state: Service VM GPA of registers state
> + *
> + * Return: 0 on success, <0 on failure
> + */
> +static inline long hcall_set_vcpu_regs(u64 vmid, u64 regs_state)
> +{
> + return acrn_hypercall2(HC_SET_VCPU_REGS, vmid, regs_state);
> +}
> +
> #endif /* __ACRN_HSM_HYPERCALL_H */
> diff --git a/include/uapi/linux/acrn.h b/include/uapi/linux/acrn.h
> index 364b1a783074..1d5b82e154fb 100644
> --- a/include/uapi/linux/acrn.h
> +++ b/include/uapi/linux/acrn.h
> @@ -36,6 +36,75 @@ struct acrn_vm_creation {
> __u8 reserved2[8];
> } __attribute__((aligned(8)));
>
> +struct acrn_gp_regs {
> + __u64 rax;
> + __u64 rcx;
> + __u64 rdx;
> + __u64 rbx;
> + __u64 rsp;
> + __u64 rbp;
> + __u64 rsi;
> + __u64 rdi;
> + __u64 r8;
> + __u64 r9;
> + __u64 r10;
> + __u64 r11;
> + __u64 r12;
> + __u64 r13;
> + __u64 r14;
> + __u64 r15;
> +};
> +
> +struct acrn_descriptor_ptr {
> + __u16 limit;
> + __u64 base;
> + __u16 reserved[3];
> +} __attribute__ ((__packed__));
> +
> +struct acrn_regs {
> + struct acrn_gp_regs gprs;
> + struct acrn_descriptor_ptr gdt;
> + struct acrn_descriptor_ptr idt;
> +
> + __u64 rip;

As these are all crossing the user/kernel boundry and then on to
somewhere "else", you have to specify the endian of all of these, right?

if not, why not?



> + __u64 cs_base;
> + __u64 cr0;
> + __u64 cr4;
> + __u64 cr3;
> + __u64 ia32_efer;
> + __u64 rflags;
> + __u64 reserved_64[4];
> +
> + __u32 cs_ar;
> + __u32 cs_limit;
> + __u32 reserved_32[3];
> +
> + __u16 cs_sel;
> + __u16 ss_sel;
> + __u16 ds_sel;
> + __u16 es_sel;
> + __u16 fs_sel;
> + __u16 gs_sel;
> + __u16 ldt_sel;
> + __u16 tr_sel;
> +
> + __u16 reserved_16[4];
> +};
> +
> +/**
> + * struct acrn_vcpu_regs - Info of vCPU registers state
> + * @vcpu_id: vCPU ID
> + * @reserved0: Reserved
> + * @vcpu_regs: vCPU registers state
> + *
> + * This structure will be passed to hypervisor directly.
> + */
> +struct acrn_vcpu_regs {
> + __u16 vcpu_id;

Endian?

> + __u16 reserved0[3];

What does the reserved fields do?

Is there a pointer to a public document for all of these structures
somewhere?

> + struct acrn_regs vcpu_regs;
> +} __attribute__((aligned(8)));

What does the alignment do here?

thanks,

greg k-h

2020-11-10 13:18:36

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

Hi Greg,

On Mon 9.Nov'20 at 18:09:40 +0100, Greg Kroah-Hartman wrote:
>On Mon, Oct 19, 2020 at 02:17:53PM +0800, [email protected] wrote:
>> From: Shuo Liu <[email protected]>
>>
>> A virtual CPU of User VM has different context due to the different
>> registers state. ACRN userspace needs to set the virtual CPU
>> registers state (e.g. giving a initial registers state to a virtual
>> BSP of a User VM).
>>
>> HSM provides an ioctl ACRN_IOCTL_SET_VCPU_REGS to do the virtual CPU
>> registers state setting. The ioctl passes the registers state from ACRN
>> userspace to the hypervisor directly.
>>
>> Signed-off-by: Shuo Liu <[email protected]>
>> Reviewed-by: Zhi Wang <[email protected]>
>> Reviewed-by: Reinette Chatre <[email protected]>
>> Cc: Zhi Wang <[email protected]>
>> Cc: Zhenyu Wang <[email protected]>
>> Cc: Yu Wang <[email protected]>
>> Cc: Reinette Chatre <[email protected]>
>> Cc: Greg Kroah-Hartman <[email protected]>
>> ---
>> drivers/virt/acrn/hsm.c | 15 ++++++++
>> drivers/virt/acrn/hypercall.h | 13 +++++++
>> include/uapi/linux/acrn.h | 71 +++++++++++++++++++++++++++++++++++
>> 3 files changed, 99 insertions(+)
>>
>> diff --git a/drivers/virt/acrn/hsm.c b/drivers/virt/acrn/hsm.c
>> index cbda67d4eb89..58ceb02e82db 100644
>> --- a/drivers/virt/acrn/hsm.c
>> +++ b/drivers/virt/acrn/hsm.c
>> @@ -9,6 +9,7 @@
>> * Yakui Zhao <[email protected]>
>> */
>>
>> +#include <linux/io.h>
>> #include <linux/mm.h>
>> #include <linux/module.h>
>> #include <linux/slab.h>
>> @@ -46,6 +47,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
>> {
>> struct acrn_vm *vm = filp->private_data;
>> struct acrn_vm_creation *vm_param;
>> + struct acrn_vcpu_regs *cpu_regs;
>> int ret = 0;
>>
>> if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) {
>> @@ -97,6 +99,19 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
>> case ACRN_IOCTL_DESTROY_VM:
>> ret = acrn_vm_destroy(vm);
>> break;
>> + case ACRN_IOCTL_SET_VCPU_REGS:
>> + cpu_regs = memdup_user((void __user *)ioctl_param,
>> + sizeof(struct acrn_vcpu_regs));
>> + if (IS_ERR(cpu_regs))
>> + return PTR_ERR(cpu_regs);
>> +
>> + ret = hcall_set_vcpu_regs(vm->vmid, virt_to_phys(cpu_regs));
>
>Why the virt_to_phys() call here?

The hypervisor need a Guest Physical Address to access the data, so
virt_to_phys() is used here.

>And there really is no validation of
>any fields?

Yes. Because HSM driver has little knowledge to do the validation.

>
>> + if (ret < 0)
>> + dev_dbg(acrn_dev.this_device,
>
>Wait, a global, static device? Where did I miss that? That feels odd,
>why is there just one?

The device is just for dev_*() usage. The driver links all active VMs in
a global list acrn_vm_list. And also the notification interrupt
(hypervisor to Service VM) is global. So, there is only one device.

>
>
>
>> + "Failed to set regs state of VM%u!\n",
>> + vm->vmid);
>> + kfree(cpu_regs);
>> + break;
>> default:
>> dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd);
>> ret = -ENOTTY;
>> diff --git a/drivers/virt/acrn/hypercall.h b/drivers/virt/acrn/hypercall.h
>> index 426b66cadb1f..f29cfae08862 100644
>> --- a/drivers/virt/acrn/hypercall.h
>> +++ b/drivers/virt/acrn/hypercall.h
>> @@ -19,6 +19,7 @@
>> #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_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)
>>
>> /**
>> * hcall_create_vm() - Create a User VM
>> @@ -75,4 +76,16 @@ static inline long hcall_reset_vm(u64 vmid)
>> return acrn_hypercall1(HC_RESET_VM, vmid);
>> }
>>
>> +/**
>> + * hcall_set_vcpu_regs() - Set up registers of virtual CPU of a User VM
>> + * @vmid: User VM ID
>> + * @regs_state: Service VM GPA of registers state
>> + *
>> + * Return: 0 on success, <0 on failure
>> + */
>> +static inline long hcall_set_vcpu_regs(u64 vmid, u64 regs_state)
>> +{
>> + return acrn_hypercall2(HC_SET_VCPU_REGS, vmid, regs_state);
>> +}
>> +
>> #endif /* __ACRN_HSM_HYPERCALL_H */
>> diff --git a/include/uapi/linux/acrn.h b/include/uapi/linux/acrn.h
>> index 364b1a783074..1d5b82e154fb 100644
>> --- a/include/uapi/linux/acrn.h
>> +++ b/include/uapi/linux/acrn.h
>> @@ -36,6 +36,75 @@ struct acrn_vm_creation {
>> __u8 reserved2[8];
>> } __attribute__((aligned(8)));
>>
>> +struct acrn_gp_regs {
>> + __u64 rax;
>> + __u64 rcx;
>> + __u64 rdx;
>> + __u64 rbx;
>> + __u64 rsp;
>> + __u64 rbp;
>> + __u64 rsi;
>> + __u64 rdi;
>> + __u64 r8;
>> + __u64 r9;
>> + __u64 r10;
>> + __u64 r11;
>> + __u64 r12;
>> + __u64 r13;
>> + __u64 r14;
>> + __u64 r15;
>> +};
>> +
>> +struct acrn_descriptor_ptr {
>> + __u16 limit;
>> + __u64 base;
>> + __u16 reserved[3];
>> +} __attribute__ ((__packed__));
>> +
>> +struct acrn_regs {
>> + struct acrn_gp_regs gprs;
>> + struct acrn_descriptor_ptr gdt;
>> + struct acrn_descriptor_ptr idt;
>> +
>> + __u64 rip;
>
>As these are all crossing the user/kernel boundry and then on to
>somewhere "else", you have to specify the endian of all of these, right?
>
>if not, why not?

The hypervisor and the driver only support X86_64 platform for now. So, the
endian should be certain.

>
>
>
>> + __u64 cs_base;
>> + __u64 cr0;
>> + __u64 cr4;
>> + __u64 cr3;
>> + __u64 ia32_efer;
>> + __u64 rflags;
>> + __u64 reserved_64[4];
>> +
>> + __u32 cs_ar;
>> + __u32 cs_limit;
>> + __u32 reserved_32[3];
>> +
>> + __u16 cs_sel;
>> + __u16 ss_sel;
>> + __u16 ds_sel;
>> + __u16 es_sel;
>> + __u16 fs_sel;
>> + __u16 gs_sel;
>> + __u16 ldt_sel;
>> + __u16 tr_sel;
>> +
>> + __u16 reserved_16[4];
>> +};
>> +
>> +/**
>> + * struct acrn_vcpu_regs - Info of vCPU registers state
>> + * @vcpu_id: vCPU ID
>> + * @reserved0: Reserved
>> + * @vcpu_regs: vCPU registers state
>> + *
>> + * This structure will be passed to hypervisor directly.
>> + */
>> +struct acrn_vcpu_regs {
>> + __u16 vcpu_id;
>
>Endian?
>
>> + __u16 reserved0[3];
>
>What does the reserved fields do?

To keep same layout with the hypervisor. Because the structure will be
passed to hypervisor directly.

>
>Is there a pointer to a public document for all of these structures
>somewhere?

Unfortunately, no. I have added some documents for some strutures
in the code via kernel-doc format.

>
>> + struct acrn_regs vcpu_regs;
>> +} __attribute__((aligned(8)));
>
>What does the alignment do here?

The hypervisor wants to access aligned data block to improve the
efficiency. Currently, the hypervisor only runs on x86_64 platform.


Thanks
shuo

2020-11-10 14:55:36

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Tue, Nov 10, 2020 at 09:14:19PM +0800, Shuo A Liu wrote:
> > And there really is no validation of
> > any fields?
>
> Yes. Because HSM driver has little knowledge to do the validation.

What is "HSM driver"? And you all are ready for fuzzers to break this
into small pieces, right? No validation of any input parameters feels
really really wrong. Best of luck!

> > > +struct acrn_regs {
> > > + struct acrn_gp_regs gprs;
> > > + struct acrn_descriptor_ptr gdt;
> > > + struct acrn_descriptor_ptr idt;
> > > +
> > > + __u64 rip;
> >
> > As these are all crossing the user/kernel boundry and then on to
> > somewhere "else", you have to specify the endian of all of these, right?
> >
> > if not, why not?
>
> The hypervisor and the driver only support X86_64 platform for now. So, the
> endian should be certain.

Then specify it please.

> > > + __u16 reserved0[3];
> >
> > What does the reserved fields do?
>
> To keep same layout with the hypervisor. Because the structure will be
> passed to hypervisor directly.
>
> >
> > Is there a pointer to a public document for all of these structures
> > somewhere?
>
> Unfortunately, no. I have added some documents for some strutures
> in the code via kernel-doc format.

Is this not the hypervisor that this code is for:
https://projectacrn.org/
?

If not, what is this thing?

If so, how is there not documentation for it?

> > > + struct acrn_regs vcpu_regs;
> > > +} __attribute__((aligned(8)));
> >
> > What does the alignment do here?
>
> The hypervisor wants to access aligned data block to improve the
> efficiency. Currently, the hypervisor only runs on x86_64 platform.

That's nice, but what do you think that adding this attribute to a
structure provides you? Have you tested this really is doing what you
think it is doing?

thanks,

greg k-h

2020-11-11 09:57:07

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Tue 10.Nov'20 at 15:54:26 +0100, Greg Kroah-Hartman wrote:
>On Tue, Nov 10, 2020 at 09:14:19PM +0800, Shuo A Liu wrote:
>> > And there really is no validation of
>> > any fields?
>>
>> Yes. Because HSM driver has little knowledge to do the validation.
>
>What is "HSM driver"? And you all are ready for fuzzers to break this
>into small pieces, right? No validation of any input parameters feels
>really really wrong. Best of luck!

This driver is HSM (Hypervisor Service Module) driver.
Take this hypercall for example. The register values are set by user, we
can do nothing to verify them. If the values are wrong, the VM will
crash and the hypervisor will handle that.

>
>> > > +struct acrn_regs {
>> > > + struct acrn_gp_regs gprs;
>> > > + struct acrn_descriptor_ptr gdt;
>> > > + struct acrn_descriptor_ptr idt;
>> > > +
>> > > + __u64 rip;
>> >
>> > As these are all crossing the user/kernel boundry and then on to
>> > somewhere "else", you have to specify the endian of all of these, right?
>> >
>> > if not, why not?
>>
>> The hypervisor and the driver only support X86_64 platform for now. So, the
>> endian should be certain.
>
>Then specify it please.

Ok. Will be __le64. I will also fix other instances in this file.

>
>> > > + __u16 reserved0[3];
>> >
>> > What does the reserved fields do?
>>
>> To keep same layout with the hypervisor. Because the structure will be
>> passed to hypervisor directly.
>>
>> >
>> > Is there a pointer to a public document for all of these structures
>> > somewhere?
>>
>> Unfortunately, no. I have added some documents for some strutures
>> in the code via kernel-doc format.
>
>Is this not the hypervisor that this code is for:
> https://projectacrn.org/
>?
>
>If not, what is this thing?
>
>If so, how is there not documentation for it?

Oh, yes. We have the structures documentation on the website. Pls refer
https://projectacrn.github.io/latest/api/hypercall_api.html#
I meant that some fields of structures might be lack of explanation.

>
>> > > + struct acrn_regs vcpu_regs;
>> > > +} __attribute__((aligned(8)));
>> >
>> > What does the alignment do here?
>>
>> The hypervisor wants to access aligned data block to improve the
>> efficiency. Currently, the hypervisor only runs on x86_64 platform.
>
>That's nice, but what do you think that adding this attribute to a
>structure provides you? Have you tested this really is doing what you
>think it is doing?

It could make the compiler put the data structure at aligned address.
In the kernel the structures are almost from kmalloc, so the attribute
might be not meaningful. But in the hypervisor, there are many such data
structures in stack or in static pool, this attribute can make sure the
data structures are located at the aligned address.

Thanks
shuo

2020-11-11 10:29:59

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Wed, Nov 11, 2020 at 05:54:31PM +0800, Shuo A Liu wrote:
> On Tue 10.Nov'20 at 15:54:26 +0100, Greg Kroah-Hartman wrote:
> > On Tue, Nov 10, 2020 at 09:14:19PM +0800, Shuo A Liu wrote:
> > > > And there really is no validation of
> > > > any fields?
> > >
> > > Yes. Because HSM driver has little knowledge to do the validation.
> >
> > What is "HSM driver"? And you all are ready for fuzzers to break this
> > into small pieces, right? No validation of any input parameters feels
> > really really wrong. Best of luck!
>
> This driver is HSM (Hypervisor Service Module) driver.
> Take this hypercall for example. The register values are set by user, we
> can do nothing to verify them. If the values are wrong, the VM will
> crash and the hypervisor will handle that.

Ah, nice, so you are creating a situation where any user can crash the
VM, what can go wrong :(

> > > >
> > > > Is there a pointer to a public document for all of these structures
> > > > somewhere?
> > >
> > > Unfortunately, no. I have added some documents for some strutures
> > > in the code via kernel-doc format.
> >
> > Is this not the hypervisor that this code is for:
> > https://projectacrn.org/
> > ?
> >
> > If not, what is this thing?
> >
> > If so, how is there not documentation for it?
>
> Oh, yes. We have the structures documentation on the website. Pls refer
> https://projectacrn.github.io/latest/api/hypercall_api.html#
> I meant that some fields of structures might be lack of explanation.

Please work on the documentation of the fields, otherwise it doesn't
really make much sense what is happening here, right?

Along these lines, where is the userspace code that makes all of these
ioctls? Surely the fields must be documented there, right?

> > > > > + struct acrn_regs vcpu_regs;
> > > > > +} __attribute__((aligned(8)));
> > > >
> > > > What does the alignment do here?
> > >
> > > The hypervisor wants to access aligned data block to improve the
> > > efficiency. Currently, the hypervisor only runs on x86_64 platform.
> >
> > That's nice, but what do you think that adding this attribute to a
> > structure provides you? Have you tested this really is doing what you
> > think it is doing?
>
> It could make the compiler put the data structure at aligned address.

Are you sure this is the correct way to do that?

> In the kernel the structures are almost from kmalloc, so the attribute
> might be not meaningful. But in the hypervisor, there are many such data
> structures in stack or in static pool, this attribute can make sure the
> data structures are located at the aligned address.

This is kernel data, not hypervisor data, in kernel memory. If you
require the hypervisor to get the structures at a specific alignment in
memory, you better check that in the kernel code, otherwise how can you
ensure it?

thanks,

greg k-h

2020-11-11 12:09:03

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Wed 11.Nov'20 at 11:28:40 +0100, Greg Kroah-Hartman wrote:
>On Wed, Nov 11, 2020 at 05:54:31PM +0800, Shuo A Liu wrote:
>> On Tue 10.Nov'20 at 15:54:26 +0100, Greg Kroah-Hartman wrote:
>> > On Tue, Nov 10, 2020 at 09:14:19PM +0800, Shuo A Liu wrote:
>> > > > And there really is no validation of
>> > > > any fields?
>> > >
>> > > Yes. Because HSM driver has little knowledge to do the validation.
>> >
>> > What is "HSM driver"? And you all are ready for fuzzers to break this
>> > into small pieces, right? No validation of any input parameters feels
>> > really really wrong. Best of luck!
>>
>> This driver is HSM (Hypervisor Service Module) driver.
>> Take this hypercall for example. The register values are set by user, we
>> can do nothing to verify them. If the values are wrong, the VM will
>> crash and the hypervisor will handle that.
>
>Ah, nice, so you are creating a situation where any user can crash the
>VM, what can go wrong :(

Not any user, only the one who create the VM. Others cannot access the
same VM. Let me list a piece of pesudo code of the device usage:

fd = open the /dev/acrn_hsm, HSM driver binds a VM with the fd
ioctl (fd, CREATE_VM, SET_VCPU_REGS, START_VM ...)
close fd

The one who create the VM should have full control of the VM.

>
>> > > >
>> > > > Is there a pointer to a public document for all of these structures
>> > > > somewhere?
>> > >
>> > > Unfortunately, no. I have added some documents for some strutures
>> > > in the code via kernel-doc format.
>> >
>> > Is this not the hypervisor that this code is for:
>> > https://projectacrn.org/
>> > ?
>> >
>> > If not, what is this thing?
>> >
>> > If so, how is there not documentation for it?
>>
>> Oh, yes. We have the structures documentation on the website. Pls refer
>> https://projectacrn.github.io/latest/api/hypercall_api.html#
>> I meant that some fields of structures might be lack of explanation.
>
>Please work on the documentation of the fields, otherwise it doesn't
>really make much sense what is happening here, right?

Right. We will try to enrich them.

>
>Along these lines, where is the userspace code that makes all of these
>ioctls? Surely the fields must be documented there, right?

A userspace tool uses the ioctls, you can find the source from:
https://github.com/projectacrn/acrn-hypervisor/blob/master/devicemodel/core/vmmapi.c
There is a bit difference with the version i posted as i did some
polish for upstream.

>
>> > > > > + struct acrn_regs vcpu_regs;
>> > > > > +} __attribute__((aligned(8)));
>> > > >
>> > > > What does the alignment do here?
>> > >
>> > > The hypervisor wants to access aligned data block to improve the
>> > > efficiency. Currently, the hypervisor only runs on x86_64 platform.
>> >
>> > That's nice, but what do you think that adding this attribute to a
>> > structure provides you? Have you tested this really is doing what you
>> > think it is doing?
>>
>> It could make the compiler put the data structure at aligned address.
>
>Are you sure this is the correct way to do that?

I tried the attribute it works.

test.c:

struct foo_256_aligned {
int a;
unsigned char b;
} __attribute__((aligned(256)));

struct foo {
int a;
unsigned char b;
};
int main(int argc, char** argv) {
struct foo_256_aligned a;
struct foo b;
printf("%p %p\n", &a, &b);
}

# gcc -o test test.c && ./test
0x7ffe2af04b00 0x7ffe2af04af8

>
>> In the kernel the structures are almost from kmalloc, so the attribute
>> might be not meaningful. But in the hypervisor, there are many such data
>> structures in stack or in static pool, this attribute can make sure the
>> data structures are located at the aligned address.
>
>This is kernel data, not hypervisor data, in kernel memory. If you
>require the hypervisor to get the structures at a specific alignment in
>memory, you better check that in the kernel code, otherwise how can you
>ensure it?

Oh, this is a public header file which will be used by the hypervisor as
well. For kernel data from kmalloc, it should be also ok even if it
isn't 8 bytes aligned. The hypervisor will copy them if need keep
persistent.

Thanks
shuo

2020-11-11 12:32:15

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Wed, Nov 11, 2020 at 08:03:48PM +0800, Shuo A Liu wrote:
> On Wed 11.Nov'20 at 11:28:40 +0100, Greg Kroah-Hartman wrote:
> > On Wed, Nov 11, 2020 at 05:54:31PM +0800, Shuo A Liu wrote:
> > > On Tue 10.Nov'20 at 15:54:26 +0100, Greg Kroah-Hartman wrote:
> > > > On Tue, Nov 10, 2020 at 09:14:19PM +0800, Shuo A Liu wrote:
> > > > > > And there really is no validation of
> > > > > > any fields?
> > > > >
> > > > > Yes. Because HSM driver has little knowledge to do the validation.
> > > >
> > > > What is "HSM driver"? And you all are ready for fuzzers to break this
> > > > into small pieces, right? No validation of any input parameters feels
> > > > really really wrong. Best of luck!
> > >
> > > This driver is HSM (Hypervisor Service Module) driver.
> > > Take this hypercall for example. The register values are set by user, we
> > > can do nothing to verify them. If the values are wrong, the VM will
> > > crash and the hypervisor will handle that.
> >
> > Ah, nice, so you are creating a situation where any user can crash the
> > VM, what can go wrong :(
>
> Not any user, only the one who create the VM. Others cannot access the
> same VM. Let me list a piece of pesudo code of the device usage:
>
> fd = open the /dev/acrn_hsm, HSM driver binds a VM with the fd
> ioctl (fd, CREATE_VM, SET_VCPU_REGS, START_VM ...)
> close fd
>
> The one who create the VM should have full control of the VM.

Including crashing it and potentially corrupting the hypervisor? Great,
remind me to never use this code :)

> > > > > >
> > > > > > Is there a pointer to a public document for all of these structures
> > > > > > somewhere?
> > > > >
> > > > > Unfortunately, no. I have added some documents for some strutures
> > > > > in the code via kernel-doc format.
> > > >
> > > > Is this not the hypervisor that this code is for:
> > > > https://projectacrn.org/
> > > > ?
> > > >
> > > > If not, what is this thing?
> > > >
> > > > If so, how is there not documentation for it?
> > >
> > > Oh, yes. We have the structures documentation on the website. Pls refer
> > > https://projectacrn.github.io/latest/api/hypercall_api.html#
> > > I meant that some fields of structures might be lack of explanation.
> >
> > Please work on the documentation of the fields, otherwise it doesn't
> > really make much sense what is happening here, right?
>
> Right. We will try to enrich them.
>
> >
> > Along these lines, where is the userspace code that makes all of these
> > ioctls? Surely the fields must be documented there, right?
>
> A userspace tool uses the ioctls, you can find the source from:
> https://github.com/projectacrn/acrn-hypervisor/blob/master/devicemodel/core/vmmapi.c
> There is a bit difference with the version i posted as i did some polish for
> upstream.

I do not understand, this isn't your version? Where is the "correct"
implementation? Shouldn't that be part of the patch series
documentation? Or was it and I missed it as this thread is so long?

> > > > > > > + struct acrn_regs vcpu_regs;
> > > > > > > +} __attribute__((aligned(8)));
> > > > > >
> > > > > > What does the alignment do here?
> > > > >
> > > > > The hypervisor wants to access aligned data block to improve the
> > > > > efficiency. Currently, the hypervisor only runs on x86_64 platform.
> > > >
> > > > That's nice, but what do you think that adding this attribute to a
> > > > structure provides you? Have you tested this really is doing what you
> > > > think it is doing?
> > >
> > > It could make the compiler put the data structure at aligned address.
> >
> > Are you sure this is the correct way to do that?
>
> I tried the attribute it works.
>
> test.c:
>
> struct foo_256_aligned {
> int a;
> unsigned char b;
> } __attribute__((aligned(256)));
>
> struct foo {
> int a;
> unsigned char b;
> };
> int main(int argc, char** argv) {
> struct foo_256_aligned a;
> struct foo b;
> printf("%p %p\n", &a, &b);
> }
>
> # gcc -o test test.c && ./test
> 0x7ffe2af04b00 0x7ffe2af04af8

But you will not have these data structures defined on the stack like
this in the kernel source.

You will be assigning the structure to some chunk of memory you
dynamically allocate, right? That's my main point here, if this is
something that you HAVE to have right, then you HAVE to test and verify
it is true when the structure is sent to you.

To just assume that a compiler marking will somehow enforce this
alignment on random chunks of allocated memory is very odd.

> > > In the kernel the structures are almost from kmalloc, so the attribute
> > > might be not meaningful. But in the hypervisor, there are many such data
> > > structures in stack or in static pool, this attribute can make sure the
> > > data structures are located at the aligned address.
> >
> > This is kernel data, not hypervisor data, in kernel memory. If you
> > require the hypervisor to get the structures at a specific alignment in
> > memory, you better check that in the kernel code, otherwise how can you
> > ensure it?
>
> Oh, this is a public header file which will be used by the hypervisor as
> well.

Then you HAVE to use the proper user/kernel structures for it.

> For kernel data from kmalloc, it should be also ok even if it
> isn't 8 bytes aligned. The hypervisor will copy them if need keep
> persistent.

See, your compiler marking didn't work :)

greg k-h

2020-11-11 16:57:09

by Shuo Liu

[permalink] [raw]
Subject: Re: [PATCH v5 07/17] virt: acrn: Introduce an ioctl to set vCPU registers state

On Wed 11.Nov'20 at 13:29:18 +0100, Greg Kroah-Hartman wrote:
>On Wed, Nov 11, 2020 at 08:03:48PM +0800, Shuo A Liu wrote:
>> On Wed 11.Nov'20 at 11:28:40 +0100, Greg Kroah-Hartman wrote:
>> > On Wed, Nov 11, 2020 at 05:54:31PM +0800, Shuo A Liu wrote:
>> > > On Tue 10.Nov'20 at 15:54:26 +0100, Greg Kroah-Hartman wrote:
>> > > > On Tue, Nov 10, 2020 at 09:14:19PM +0800, Shuo A Liu wrote:
>> > > > > > And there really is no validation of
>> > > > > > any fields?
>> > > > >
>> > > > > Yes. Because HSM driver has little knowledge to do the validation.
>> > > >
>> > > > What is "HSM driver"? And you all are ready for fuzzers to break this
>> > > > into small pieces, right? No validation of any input parameters feels
>> > > > really really wrong. Best of luck!
>> > >
>> > > This driver is HSM (Hypervisor Service Module) driver.
>> > > Take this hypercall for example. The register values are set by user, we
>> > > can do nothing to verify them. If the values are wrong, the VM will
>> > > crash and the hypervisor will handle that.
>> >
>> > Ah, nice, so you are creating a situation where any user can crash the
>> > VM, what can go wrong :(
>>
>> Not any user, only the one who create the VM. Others cannot access the
>> same VM. Let me list a piece of pesudo code of the device usage:
>>
>> fd = open the /dev/acrn_hsm, HSM driver binds a VM with the fd
>> ioctl (fd, CREATE_VM, SET_VCPU_REGS, START_VM ...)
>> close fd
>>
>> The one who create the VM should have full control of the VM.
>
>Including crashing it and potentially corrupting the hypervisor? Great,
>remind me to never use this code :)

The crashing here is within guest VM itself. It should not affect the
hypervisor, else bug appears. The hypervisor should handle such case
correctly (e.g. add more validataion in hypervisor) :)

>
>> > > > > >
>> > > > > > Is there a pointer to a public document for all of these structures
>> > > > > > somewhere?
>> > > > >
>> > > > > Unfortunately, no. I have added some documents for some strutures
>> > > > > in the code via kernel-doc format.
>> > > >
>> > > > Is this not the hypervisor that this code is for:
>> > > > https://projectacrn.org/
>> > > > ?
>> > > >
>> > > > If not, what is this thing?
>> > > >
>> > > > If so, how is there not documentation for it?
>> > >
>> > > Oh, yes. We have the structures documentation on the website. Pls refer
>> > > https://projectacrn.github.io/latest/api/hypercall_api.html#
>> > > I meant that some fields of structures might be lack of explanation.
>> >
>> > Please work on the documentation of the fields, otherwise it doesn't
>> > really make much sense what is happening here, right?
>>
>> Right. We will try to enrich them.
>>
>> >
>> > Along these lines, where is the userspace code that makes all of these
>> > ioctls? Surely the fields must be documented there, right?
>>
>> A userspace tool uses the ioctls, you can find the source from:
>> https://github.com/projectacrn/acrn-hypervisor/blob/master/devicemodel/core/vmmapi.c
>> There is a bit difference with the version i posted as i did some polish for
>> upstream.
>
>I do not understand, this isn't your version? Where is the "correct"
>implementation? Shouldn't that be part of the patch series
>documentation? Or was it and I missed it as this thread is so long?

You didn't miss that. The link i pasted above is from a userspace
application (named devicemodel in ACRN project) that using this driver
on ACRN hypervisor (like QEMU on KVM). I didn't put it in the patch,
because it's a huge program. There are some difference of the
ioctl definition within this patchset (changing of name and definition),
because we are using that currently for daily development. When the
upstreaming patch got merged, they will be updated.

So, it seems you wanted a brief example code of driver usage in
documentation, am i right? If yes, i can try to make one. But it
might only show a brief flow of VM creating, memory setup, vcpu setup,
VM starting, maybe IO handling, VM destroy, ..etc. Is that ok?

>
>> > > > > > > + struct acrn_regs vcpu_regs;
>> > > > > > > +} __attribute__((aligned(8)));
>> > > > > >
>> > > > > > What does the alignment do here?
>> > > > >
>> > > > > The hypervisor wants to access aligned data block to improve the
>> > > > > efficiency. Currently, the hypervisor only runs on x86_64 platform.
>> > > >
>> > > > That's nice, but what do you think that adding this attribute to a
>> > > > structure provides you? Have you tested this really is doing what you
>> > > > think it is doing?
>> > >
>> > > It could make the compiler put the data structure at aligned address.
>> >
>> > Are you sure this is the correct way to do that?
>>
>> I tried the attribute it works.
>>
>> test.c:
>>
>> struct foo_256_aligned {
>> int a;
>> unsigned char b;
>> } __attribute__((aligned(256)));
>>
>> struct foo {
>> int a;
>> unsigned char b;
>> };
>> int main(int argc, char** argv) {
>> struct foo_256_aligned a;
>> struct foo b;
>> printf("%p %p\n", &a, &b);
>> }
>>
>> # gcc -o test test.c && ./test
>> 0x7ffe2af04b00 0x7ffe2af04af8
>
>But you will not have these data structures defined on the stack like
>this in the kernel source.
>
>You will be assigning the structure to some chunk of memory you
>dynamically allocate, right? That's my main point here, if this is

Understand.

>something that you HAVE to have right, then you HAVE to test and verify
>it is true when the structure is sent to you.
>
>To just assume that a compiler marking will somehow enforce this
>alignment on random chunks of allocated memory is very odd.
>
>> > > In the kernel the structures are almost from kmalloc, so the attribute
>> > > might be not meaningful. But in the hypervisor, there are many such data
>> > > structures in stack or in static pool, this attribute can make sure the
>> > > data structures are located at the aligned address.
>> >
>> > This is kernel data, not hypervisor data, in kernel memory. If you
>> > require the hypervisor to get the structures at a specific alignment in
>> > memory, you better check that in the kernel code, otherwise how can you
>> > ensure it?
>>
>> Oh, this is a public header file which will be used by the hypervisor as
>> well.
>
>Then you HAVE to use the proper user/kernel structures for it.

Sorry, i didn't follow here. The structures are used in

* devicemodel (userspace application, like QEMU in KVM)
* HSM (this driver, pass the data from devicemodel to hypervisor)
* hypervisor

They all should be compiled with the same public header from kernel, is
my understanding right? If hypervisor source wants to use the compiler
marking, need i only duplicate one header with the modification for
that?


Thanks
shuo