Skip to content

Commit 9c5137a

Browse files
Shuo Liugregkh
authored andcommitted
virt: acrn: Introduce VM management interfaces
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. 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]> Reviewed-by: Zhi Wang <[email protected]> Reviewed-by: Reinette Chatre <[email protected]> Signed-off-by: Shuo Liu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 666834c commit 9c5137a

File tree

8 files changed

+301
-4
lines changed

8 files changed

+301
-4
lines changed

Documentation/userspace-api/ioctl/ioctl-number.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ Code Seq# Include File Comments
320320
0xA0 all linux/sdp/sdp.h Industrial Device Project
321321
322322
0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver
323+
0xA2 all uapi/linux/acrn.h ACRN hypervisor
323324
0xA3 80-8F Port ACL in development:
324325
325326
0xA3 90-9F linux/dtlk.h

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ S: Supported
443443
W: https://projectacrn.org
444444
F: Documentation/virt/acrn/
445445
F: drivers/virt/acrn/
446+
F: include/uapi/linux/acrn.h
446447

447448
AD1889 ALSA SOUND DRIVER
448449

drivers/virt/acrn/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_ACRN_HSM) := acrn.o
3-
acrn-y := hsm.o
3+
acrn-y := hsm.o vm.o

drivers/virt/acrn/acrn_drv.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,35 @@
33
#ifndef __ACRN_HSM_DRV_H
44
#define __ACRN_HSM_DRV_H
55

6+
#include <linux/acrn.h>
7+
#include <linux/dev_printk.h>
8+
#include <linux/miscdevice.h>
69
#include <linux/types.h>
710

11+
#include "hypercall.h"
12+
13+
extern struct miscdevice acrn_dev;
14+
815
#define ACRN_INVALID_VMID (0xffffU)
916

17+
#define ACRN_VM_FLAG_DESTROYED 0U
1018
/**
1119
* struct acrn_vm - Properties of ACRN User VM.
20+
* @list: Entry within global list of all VMs
1221
* @vmid: User VM ID
22+
* @vcpu_num: Number of virtual CPUs in the VM
23+
* @flags: Flags (ACRN_VM_FLAG_*) of the VM. This is VM flag management
24+
* in HSM which is different from the &acrn_vm_creation.vm_flag.
1325
*/
1426
struct acrn_vm {
15-
u16 vmid;
27+
struct list_head list;
28+
u16 vmid;
29+
int vcpu_num;
30+
unsigned long flags;
1631
};
1732

33+
struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
34+
struct acrn_vm_creation *vm_param);
35+
int acrn_vm_destroy(struct acrn_vm *vm);
36+
1837
#endif /* __ACRN_HSM_DRV_H */

drivers/virt/acrn/hsm.c

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
* Yakui Zhao <[email protected]>
1010
*/
1111

12-
#include <linux/miscdevice.h>
1312
#include <linux/mm.h>
1413
#include <linux/module.h>
1514
#include <linux/slab.h>
@@ -38,10 +37,82 @@ static int acrn_dev_open(struct inode *inode, struct file *filp)
3837
return 0;
3938
}
4039

40+
/*
41+
* HSM relies on hypercall layer of the ACRN hypervisor to do the
42+
* sanity check against the input parameters.
43+
*/
44+
static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
45+
unsigned long ioctl_param)
46+
{
47+
struct acrn_vm *vm = filp->private_data;
48+
struct acrn_vm_creation *vm_param;
49+
int ret = 0;
50+
51+
if (vm->vmid == ACRN_INVALID_VMID && cmd != ACRN_IOCTL_CREATE_VM) {
52+
dev_dbg(acrn_dev.this_device,
53+
"ioctl 0x%x: Invalid VM state!\n", cmd);
54+
return -EINVAL;
55+
}
56+
57+
switch (cmd) {
58+
case ACRN_IOCTL_CREATE_VM:
59+
vm_param = memdup_user((void __user *)ioctl_param,
60+
sizeof(struct acrn_vm_creation));
61+
if (IS_ERR(vm_param))
62+
return PTR_ERR(vm_param);
63+
64+
if ((vm_param->reserved0 | vm_param->reserved1) != 0)
65+
return -EINVAL;
66+
67+
vm = acrn_vm_create(vm, vm_param);
68+
if (!vm) {
69+
ret = -EINVAL;
70+
kfree(vm_param);
71+
break;
72+
}
73+
74+
if (copy_to_user((void __user *)ioctl_param, vm_param,
75+
sizeof(struct acrn_vm_creation))) {
76+
acrn_vm_destroy(vm);
77+
ret = -EFAULT;
78+
}
79+
80+
kfree(vm_param);
81+
break;
82+
case ACRN_IOCTL_START_VM:
83+
ret = hcall_start_vm(vm->vmid);
84+
if (ret < 0)
85+
dev_dbg(acrn_dev.this_device,
86+
"Failed to start VM %u!\n", vm->vmid);
87+
break;
88+
case ACRN_IOCTL_PAUSE_VM:
89+
ret = hcall_pause_vm(vm->vmid);
90+
if (ret < 0)
91+
dev_dbg(acrn_dev.this_device,
92+
"Failed to pause VM %u!\n", vm->vmid);
93+
break;
94+
case ACRN_IOCTL_RESET_VM:
95+
ret = hcall_reset_vm(vm->vmid);
96+
if (ret < 0)
97+
dev_dbg(acrn_dev.this_device,
98+
"Failed to restart VM %u!\n", vm->vmid);
99+
break;
100+
case ACRN_IOCTL_DESTROY_VM:
101+
ret = acrn_vm_destroy(vm);
102+
break;
103+
default:
104+
dev_dbg(acrn_dev.this_device, "Unknown IOCTL 0x%x!\n", cmd);
105+
ret = -ENOTTY;
106+
}
107+
108+
return ret;
109+
}
110+
41111
static int acrn_dev_release(struct inode *inode, struct file *filp)
42112
{
43113
struct acrn_vm *vm = filp->private_data;
44114

115+
acrn_vm_destroy(vm);
45116
kfree(vm);
46117
return 0;
47118
}
@@ -50,9 +121,10 @@ static const struct file_operations acrn_fops = {
50121
.owner = THIS_MODULE,
51122
.open = acrn_dev_open,
52123
.release = acrn_dev_release,
124+
.unlocked_ioctl = acrn_dev_ioctl,
53125
};
54126

55-
static struct miscdevice acrn_dev = {
127+
struct miscdevice acrn_dev = {
56128
.minor = MISC_DYNAMIC_MINOR,
57129
.name = "acrn_hsm",
58130
.fops = &acrn_fops,

drivers/virt/acrn/hypercall.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* ACRN HSM: hypercalls of ACRN Hypervisor
4+
*/
5+
#ifndef __ACRN_HSM_HYPERCALL_H
6+
#define __ACRN_HSM_HYPERCALL_H
7+
#include <asm/acrn.h>
8+
9+
/*
10+
* Hypercall IDs of the ACRN Hypervisor
11+
*/
12+
#define _HC_ID(x, y) (((x) << 24) | (y))
13+
14+
#define HC_ID 0x80UL
15+
16+
#define HC_ID_VM_BASE 0x10UL
17+
#define HC_CREATE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x00)
18+
#define HC_DESTROY_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x01)
19+
#define HC_START_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x02)
20+
#define HC_PAUSE_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x03)
21+
#define HC_RESET_VM _HC_ID(HC_ID, HC_ID_VM_BASE + 0x05)
22+
23+
/**
24+
* hcall_create_vm() - Create a User VM
25+
* @vminfo: Service VM GPA of info of User VM creation
26+
*
27+
* Return: 0 on success, <0 on failure
28+
*/
29+
static inline long hcall_create_vm(u64 vminfo)
30+
{
31+
return acrn_hypercall1(HC_CREATE_VM, vminfo);
32+
}
33+
34+
/**
35+
* hcall_start_vm() - Start a User VM
36+
* @vmid: User VM ID
37+
*
38+
* Return: 0 on success, <0 on failure
39+
*/
40+
static inline long hcall_start_vm(u64 vmid)
41+
{
42+
return acrn_hypercall1(HC_START_VM, vmid);
43+
}
44+
45+
/**
46+
* hcall_pause_vm() - Pause a User VM
47+
* @vmid: User VM ID
48+
*
49+
* Return: 0 on success, <0 on failure
50+
*/
51+
static inline long hcall_pause_vm(u64 vmid)
52+
{
53+
return acrn_hypercall1(HC_PAUSE_VM, vmid);
54+
}
55+
56+
/**
57+
* hcall_destroy_vm() - Destroy a User VM
58+
* @vmid: User VM ID
59+
*
60+
* Return: 0 on success, <0 on failure
61+
*/
62+
static inline long hcall_destroy_vm(u64 vmid)
63+
{
64+
return acrn_hypercall1(HC_DESTROY_VM, vmid);
65+
}
66+
67+
/**
68+
* hcall_reset_vm() - Reset a User VM
69+
* @vmid: User VM ID
70+
*
71+
* Return: 0 on success, <0 on failure
72+
*/
73+
static inline long hcall_reset_vm(u64 vmid)
74+
{
75+
return acrn_hypercall1(HC_RESET_VM, vmid);
76+
}
77+
78+
#endif /* __ACRN_HSM_HYPERCALL_H */

drivers/virt/acrn/vm.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* ACRN_HSM: Virtual Machine management
4+
*
5+
* Copyright (C) 2020 Intel Corporation. All rights reserved.
6+
*
7+
* Authors:
8+
* Jason Chen CJ <[email protected]>
9+
* Yakui Zhao <[email protected]>
10+
*/
11+
#include <linux/io.h>
12+
#include <linux/mm.h>
13+
#include <linux/slab.h>
14+
15+
#include "acrn_drv.h"
16+
17+
/* List of VMs */
18+
static LIST_HEAD(acrn_vm_list);
19+
/* To protect acrn_vm_list */
20+
static DEFINE_MUTEX(acrn_vm_list_lock);
21+
22+
struct acrn_vm *acrn_vm_create(struct acrn_vm *vm,
23+
struct acrn_vm_creation *vm_param)
24+
{
25+
int ret;
26+
27+
ret = hcall_create_vm(virt_to_phys(vm_param));
28+
if (ret < 0 || vm_param->vmid == ACRN_INVALID_VMID) {
29+
dev_err(acrn_dev.this_device,
30+
"Failed to create VM! Error: %d\n", ret);
31+
return NULL;
32+
}
33+
34+
vm->vmid = vm_param->vmid;
35+
vm->vcpu_num = vm_param->vcpu_num;
36+
37+
mutex_lock(&acrn_vm_list_lock);
38+
list_add(&vm->list, &acrn_vm_list);
39+
mutex_unlock(&acrn_vm_list_lock);
40+
41+
dev_dbg(acrn_dev.this_device, "VM %u created.\n", vm->vmid);
42+
return vm;
43+
}
44+
45+
int acrn_vm_destroy(struct acrn_vm *vm)
46+
{
47+
int ret;
48+
49+
if (vm->vmid == ACRN_INVALID_VMID ||
50+
test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags))
51+
return 0;
52+
53+
/* Remove from global VM list */
54+
mutex_lock(&acrn_vm_list_lock);
55+
list_del_init(&vm->list);
56+
mutex_unlock(&acrn_vm_list_lock);
57+
58+
ret = hcall_destroy_vm(vm->vmid);
59+
if (ret < 0) {
60+
dev_err(acrn_dev.this_device,
61+
"Failed to destroy VM %u\n", vm->vmid);
62+
clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags);
63+
return ret;
64+
}
65+
dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid);
66+
vm->vmid = ACRN_INVALID_VMID;
67+
return 0;
68+
}

include/uapi/linux/acrn.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+
/*
3+
* Userspace interface for /dev/acrn_hsm - ACRN Hypervisor Service Module
4+
*
5+
* This file can be used by applications that need to communicate with the HSM
6+
* via the ioctl interface.
7+
*
8+
* Copyright (C) 2021 Intel Corporation. All rights reserved.
9+
*/
10+
11+
#ifndef _UAPI_ACRN_H
12+
#define _UAPI_ACRN_H
13+
14+
#include <linux/types.h>
15+
#include <linux/uuid.h>
16+
17+
/**
18+
* struct acrn_vm_creation - Info to create a User VM
19+
* @vmid: User VM ID returned from the hypervisor
20+
* @reserved0: Reserved and must be 0
21+
* @vcpu_num: Number of vCPU in the VM. Return from hypervisor.
22+
* @reserved1: Reserved and must be 0
23+
* @uuid: UUID of the VM. Pass to hypervisor directly.
24+
* @vm_flag: Flag of the VM creating. Pass to hypervisor directly.
25+
* @ioreq_buf: Service VM GPA of I/O request buffer. Pass to
26+
* hypervisor directly.
27+
* @cpu_affinity: CPU affinity of the VM. Pass to hypervisor directly.
28+
* It's a bitmap which indicates CPUs used by the VM.
29+
*/
30+
struct acrn_vm_creation {
31+
__u16 vmid;
32+
__u16 reserved0;
33+
__u16 vcpu_num;
34+
__u16 reserved1;
35+
guid_t uuid;
36+
__u64 vm_flag;
37+
__u64 ioreq_buf;
38+
__u64 cpu_affinity;
39+
};
40+
41+
/* The ioctl type, documented in ioctl-number.rst */
42+
#define ACRN_IOCTL_TYPE 0xA2
43+
44+
/*
45+
* Common IOCTL IDs definition for ACRN userspace
46+
*/
47+
#define ACRN_IOCTL_CREATE_VM \
48+
_IOWR(ACRN_IOCTL_TYPE, 0x10, struct acrn_vm_creation)
49+
#define ACRN_IOCTL_DESTROY_VM \
50+
_IO(ACRN_IOCTL_TYPE, 0x11)
51+
#define ACRN_IOCTL_START_VM \
52+
_IO(ACRN_IOCTL_TYPE, 0x12)
53+
#define ACRN_IOCTL_PAUSE_VM \
54+
_IO(ACRN_IOCTL_TYPE, 0x13)
55+
#define ACRN_IOCTL_RESET_VM \
56+
_IO(ACRN_IOCTL_TYPE, 0x15)
57+
58+
#endif /* _UAPI_ACRN_H */

0 commit comments

Comments
 (0)