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+
25+enum {
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+
34+enum {
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+ */
50+struct 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+
64+struct mshv_create_vp {
65+ __u32 vp_index;
66+};
67+
68+enum {
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+ */
95+struct mshv_user_mem_region {
96+ __u64 size;
97+ __u64 guest_pfn;
98+ __u64 userspace_addr;
99+ __u8 flags;
100+ __u8 rsvd[7];
101+};
102+
103+enum {
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+
111+struct mshv_user_irqfd {
112+ __s32 fd;
113+ __s32 resamplefd;
114+ __u32 gsi;
115+ __u32 flags;
116+};
117+
118+enum {
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+
127+struct 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+
136+struct mshv_user_irq_entry {
137+ __u32 gsi;
138+ __u32 address_lo;
139+ __u32 address_hi;
140+ __u32 data;
141+};
142+
143+struct mshv_user_irq_table {
144+ __u32 nr;
145+ __u32 rsvd; /* MBZ */
146+ struct mshv_user_irq_entry entries[];
147+};
148+
149+enum {
150+ MSHV_GPAP_ACCESS_TYPE_ACCESSED,
151+ MSHV_GPAP_ACCESS_TYPE_DIRTY,
152+ MSHV_GPAP_ACCESS_TYPE_COUNT /* Count of enum members */
153+};
154+
155+enum {
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+ */
177+struct 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+ */
200+struct 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+ */
240+enum {
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+ */
252+struct mshv_run_vp {
253+ __u8 msg_buf[MSHV_RUN_VP_BUF_SZ];
254+};
255+
256+enum {
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+ */
274+struct 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