History

Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs

Provide a set of IOCTLs for creating and managing child partitions when running as root partition on Hyper-V. The new driver is enabled via CONFIG_MSHV_ROOT. A brief overview of the interface: MSHV_CREATE_PARTITION is the entry point, returning a file descriptor representing a child partition. IOCTLs on this fd can be used to map memory, create VPs, etc. Creating a VP returns another file descriptor representing that VP which in turn has another set of corresponding IOCTLs for running the VP, getting/setting state, etc. MSHV_ROOT_HVCALL is a generic "passthrough" hypercall IOCTL which can be used for a number of partition or VP hypercalls. This is for hypercalls that do not affect any state in the kernel driver, such as getting and setting VP registers and partition properties, translating addresses, etc. It is "passthrough" because the binary input and output for the hypercall is only interpreted by the VMM - the kernel driver does nothing but insert the VP and partition id where necessary (which are always in the same place), and execute the hypercall.

Nuno Das Neves committed 1 year ago

Commit 621191d1 parent 0bd921a14 files · +5732 −1Browse files

Showing the changes to include/uapi (1 of 14 files). Show all

Unified · Split

include/uapi/linux/mshv.h+291−0
@@ -0,0 +1,291 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * Userspace interfaces for /dev/mshv* devices and derived fds
4 *
5 * This file is divided into sections containing data structures and IOCTLs for
6 * a particular set of related devices or derived file descriptors.
7 *
8 * The IOCTL definitions are at the end of each section. They are grouped by
9 * device/fd, so that new IOCTLs can easily be added with a monotonically
10 * increasing number.
11 */
12#ifndef _UAPI_LINUX_MSHV_H
13#define _UAPI_LINUX_MSHV_H
14
15#include <linux/types.h>
16
17#define MSHV_IOCTL 0xB8
18
19/*
20 *******************************************
21 * Entry point to main VMM APIs: /dev/mshv *
22 *******************************************
23 */
24
25enum {
26 MSHV_PT_BIT_LAPIC,
27 MSHV_PT_BIT_X2APIC,
28 MSHV_PT_BIT_GPA_SUPER_PAGES,
29 MSHV_PT_BIT_COUNT,
30};
31
32#define MSHV_PT_FLAGS_MASK ((1 << MSHV_PT_BIT_COUNT) - 1)
33
34enum {
35 MSHV_PT_ISOLATION_NONE,
36 MSHV_PT_ISOLATION_COUNT,
37};
38
39/**
40 * struct mshv_create_partition - arguments for MSHV_CREATE_PARTITION
41 * @pt_flags: Bitmask of 1 << MSHV_PT_BIT_*
42 * @pt_isolation: MSHV_PT_ISOLATION_*
43 *
44 * Returns a file descriptor to act as a handle to a guest partition.
45 * At this point the partition is not yet initialized in the hypervisor.
46 * Some operations must be done with the partition in this state, e.g. setting
47 * so-called "early" partition properties. The partition can then be
48 * initialized with MSHV_INITIALIZE_PARTITION.
49 */
50struct mshv_create_partition {
51 __u64 pt_flags;
52 __u64 pt_isolation;
53};
54
55/* /dev/mshv */
56#define MSHV_CREATE_PARTITION _IOW(MSHV_IOCTL, 0x00, struct mshv_create_partition)
57
58/*
59 ************************
60 * Child partition APIs *
61 ************************
62 */
63
64struct mshv_create_vp {
65 __u32 vp_index;
66};
67
68enum {
69 MSHV_SET_MEM_BIT_WRITABLE,
70 MSHV_SET_MEM_BIT_EXECUTABLE,
71 MSHV_SET_MEM_BIT_UNMAP,
72 MSHV_SET_MEM_BIT_COUNT
73};
74
75#define MSHV_SET_MEM_FLAGS_MASK ((1 << MSHV_SET_MEM_BIT_COUNT) - 1)
76
77/* The hypervisor's "native" page size */
78#define MSHV_HV_PAGE_SIZE 0x1000
79
80/**
81 * struct mshv_user_mem_region - arguments for MSHV_SET_GUEST_MEMORY
82 * @size: Size of the memory region (bytes). Must be aligned to
83 * MSHV_HV_PAGE_SIZE
84 * @guest_pfn: Base guest page number to map
85 * @userspace_addr: Base address of userspace memory. Must be aligned to
86 * MSHV_HV_PAGE_SIZE
87 * @flags: Bitmask of 1 << MSHV_SET_MEM_BIT_*. If (1 << MSHV_SET_MEM_BIT_UNMAP)
88 * is set, ignore other bits.
89 * @rsvd: MBZ
90 *
91 * Map or unmap a region of userspace memory to Guest Physical Addresses (GPA).
92 * Mappings can't overlap in GPA space or userspace.
93 * To unmap, these fields must match an existing mapping.
94 */
95struct mshv_user_mem_region {
96 __u64 size;
97 __u64 guest_pfn;
98 __u64 userspace_addr;
99 __u8 flags;
100 __u8 rsvd[7];
101};
102
103enum {
104 MSHV_IRQFD_BIT_DEASSIGN,
105 MSHV_IRQFD_BIT_RESAMPLE,
106 MSHV_IRQFD_BIT_COUNT,
107};
108
109#define MSHV_IRQFD_FLAGS_MASK ((1 << MSHV_IRQFD_BIT_COUNT) - 1)
110
111struct mshv_user_irqfd {
112 __s32 fd;
113 __s32 resamplefd;
114 __u32 gsi;
115 __u32 flags;
116};
117
118enum {
119 MSHV_IOEVENTFD_BIT_DATAMATCH,
120 MSHV_IOEVENTFD_BIT_PIO,
121 MSHV_IOEVENTFD_BIT_DEASSIGN,
122 MSHV_IOEVENTFD_BIT_COUNT,
123};
124
125#define MSHV_IOEVENTFD_FLAGS_MASK ((1 << MSHV_IOEVENTFD_BIT_COUNT) - 1)
126
127struct mshv_user_ioeventfd {
128 __u64 datamatch;
129 __u64 addr; /* legal pio/mmio address */
130 __u32 len; /* 1, 2, 4, or 8 bytes */
131 __s32 fd;
132 __u32 flags;
133 __u8 rsvd[4];
134};
135
136struct mshv_user_irq_entry {
137 __u32 gsi;
138 __u32 address_lo;
139 __u32 address_hi;
140 __u32 data;
141};
142
143struct mshv_user_irq_table {
144 __u32 nr;
145 __u32 rsvd; /* MBZ */
146 struct mshv_user_irq_entry entries[];
147};
148
149enum {
150 MSHV_GPAP_ACCESS_TYPE_ACCESSED,
151 MSHV_GPAP_ACCESS_TYPE_DIRTY,
152 MSHV_GPAP_ACCESS_TYPE_COUNT /* Count of enum members */
153};
154
155enum {
156 MSHV_GPAP_ACCESS_OP_NOOP,
157 MSHV_GPAP_ACCESS_OP_CLEAR,
158 MSHV_GPAP_ACCESS_OP_SET,
159 MSHV_GPAP_ACCESS_OP_COUNT /* Count of enum members */
160};
161
162/**
163 * struct mshv_gpap_access_bitmap - arguments for MSHV_GET_GPAP_ACCESS_BITMAP
164 * @access_type: MSHV_GPAP_ACCESS_TYPE_* - The type of access to record in the
165 * bitmap
166 * @access_op: MSHV_GPAP_ACCESS_OP_* - Allows an optional clear or set of all
167 * the access states in the range, after retrieving the current
168 * states.
169 * @rsvd: MBZ
170 * @page_count: Number of pages
171 * @gpap_base: Base gpa page number
172 * @bitmap_ptr: Output buffer for bitmap, at least (page_count + 7) / 8 bytes
173 *
174 * Retrieve a bitmap of either ACCESSED or DIRTY bits for a given range of guest
175 * memory, and optionally clear or set the bits.
176 */
177struct mshv_gpap_access_bitmap {
178 __u8 access_type;
179 __u8 access_op;
180 __u8 rsvd[6];
181 __u64 page_count;
182 __u64 gpap_base;
183 __u64 bitmap_ptr;
184};
185
186/**
187 * struct mshv_root_hvcall - arguments for MSHV_ROOT_HVCALL
188 * @code: Hypercall code (HVCALL_*)
189 * @reps: in: Rep count ('repcount')
190 * out: Reps completed ('repcomp'). MBZ unless rep hvcall
191 * @in_sz: Size of input incl rep data. <= MSHV_HV_PAGE_SIZE
192 * @out_sz: Size of output buffer. <= MSHV_HV_PAGE_SIZE. MBZ if out_ptr is 0
193 * @status: in: MBZ
194 * out: HV_STATUS_* from hypercall
195 * @rsvd: MBZ
196 * @in_ptr: Input data buffer (struct hv_input_*). If used with partition or
197 * vp fd, partition id field is populated by kernel.
198 * @out_ptr: Output data buffer (optional)
199 */
200struct mshv_root_hvcall {
201 __u16 code;
202 __u16 reps;
203 __u16 in_sz;
204 __u16 out_sz;
205 __u16 status;
206 __u8 rsvd[6];
207 __u64 in_ptr;
208 __u64 out_ptr;
209};
210
211/* Partition fds created with MSHV_CREATE_PARTITION */
212#define MSHV_INITIALIZE_PARTITION _IO(MSHV_IOCTL, 0x00)
213#define MSHV_CREATE_VP _IOW(MSHV_IOCTL, 0x01, struct mshv_create_vp)
214#define MSHV_SET_GUEST_MEMORY _IOW(MSHV_IOCTL, 0x02, struct mshv_user_mem_region)
215#define MSHV_IRQFD _IOW(MSHV_IOCTL, 0x03, struct mshv_user_irqfd)
216#define MSHV_IOEVENTFD _IOW(MSHV_IOCTL, 0x04, struct mshv_user_ioeventfd)
217#define MSHV_SET_MSI_ROUTING _IOW(MSHV_IOCTL, 0x05, struct mshv_user_irq_table)
218#define MSHV_GET_GPAP_ACCESS_BITMAP _IOWR(MSHV_IOCTL, 0x06, struct mshv_gpap_access_bitmap)
219/* Generic hypercall */
220#define MSHV_ROOT_HVCALL _IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall)
221
222/*
223 ********************************
224 * VP APIs for child partitions *
225 ********************************
226 */
227
228#define MSHV_RUN_VP_BUF_SZ 256
229
230/*
231 * VP state pages may be mapped to userspace via mmap().
232 * To specify which state page, use MSHV_VP_MMAP_OFFSET_ values multiplied by
233 * the system page size.
234 * e.g.
235 * long page_size = sysconf(_SC_PAGE_SIZE);
236 * void *reg_page = mmap(NULL, MSHV_HV_PAGE_SIZE, PROT_READ|PROT_WRITE,
237 * MAP_SHARED, vp_fd,
238 * MSHV_VP_MMAP_OFFSET_REGISTERS * page_size);
239 */
240enum {
241 MSHV_VP_MMAP_OFFSET_REGISTERS,
242 MSHV_VP_MMAP_OFFSET_INTERCEPT_MESSAGE,
243 MSHV_VP_MMAP_OFFSET_GHCB,
244 MSHV_VP_MMAP_OFFSET_COUNT
245};
246
247/**
248 * struct mshv_run_vp - argument for MSHV_RUN_VP
249 * @msg_buf: On success, the intercept message is copied here. It can be
250 * interpreted using the relevant hypervisor definitions.
251 */
252struct mshv_run_vp {
253 __u8 msg_buf[MSHV_RUN_VP_BUF_SZ];
254};
255
256enum {
257 MSHV_VP_STATE_LAPIC, /* Local interrupt controller state (either arch) */
258 MSHV_VP_STATE_XSAVE, /* XSAVE data in compacted form (x86_64) */
259 MSHV_VP_STATE_SIMP,
260 MSHV_VP_STATE_SIEFP,
261 MSHV_VP_STATE_SYNTHETIC_TIMERS,
262 MSHV_VP_STATE_COUNT,
263};
264
265/**
266 * struct mshv_get_set_vp_state - arguments for MSHV_[GET,SET]_VP_STATE
267 * @type: MSHV_VP_STATE_*
268 * @rsvd: MBZ
269 * @buf_sz: in: 4k page-aligned size of buffer
270 * out: Actual size of data (on EINVAL, check this to see if buffer
271 * was too small)
272 * @buf_ptr: 4k page-aligned data buffer
273 */
274struct mshv_get_set_vp_state {
275 __u8 type;
276 __u8 rsvd[3];
277 __u32 buf_sz;
278 __u64 buf_ptr;
279};
280
281/* VP fds created with MSHV_CREATE_VP */
282#define MSHV_RUN_VP _IOR(MSHV_IOCTL, 0x00, struct mshv_run_vp)
283#define MSHV_GET_VP_STATE _IOWR(MSHV_IOCTL, 0x01, struct mshv_get_set_vp_state)
284#define MSHV_SET_VP_STATE _IOWR(MSHV_IOCTL, 0x02, struct mshv_get_set_vp_state)
285/*
286 * Generic hypercall
287 * Defined above in partition IOCTLs, avoid redefining it here
288 * #define MSHV_ROOT_HVCALL _IOWR(MSHV_IOCTL, 0x07, struct mshv_root_hvcall)
289 */
290
291#endif