• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
2 /*
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  */
5 
6 #ifndef _UAPI_LINUX_GUNYAH_H
7 #define _UAPI_LINUX_GUNYAH_H
8 
9 /*
10  * Userspace interface for /dev/gunyah - gunyah based virtual machine
11  */
12 
13 #include <linux/types.h>
14 #include <linux/ioctl.h>
15 
16 #define GUNYAH_IOCTL_TYPE 'G'
17 
18 /*
19  * ioctls for /dev/gunyah fds:
20  */
21 #define GUNYAH_CREATE_VM _IO(GUNYAH_IOCTL_TYPE, 0x0) /* Returns a Gunyah VM fd */
22 
23 /*
24  * ioctls for gunyah-vm fds (returned by GUNYAH_CREATE_VM)
25  */
26 
27 /**
28  * struct gunyah_vm_dtb_config - Set the location of the VM's devicetree blob
29  * @guest_phys_addr: Address of the VM's devicetree in guest memory.
30  * @size: Maximum size of the devicetree including space for overlays.
31  *        Resource manager applies an overlay to the DTB and dtb_size should
32  *        include room for the overlay. A page of memory is typicaly plenty.
33  */
34 struct gunyah_vm_dtb_config {
35 	__u64 guest_phys_addr;
36 	__u64 size;
37 };
38 #define GUNYAH_VM_SET_DTB_CONFIG	_IOW(GUNYAH_IOCTL_TYPE, 0x2, struct gunyah_vm_dtb_config)
39 
40 #define GUNYAH_VM_START		_IO(GUNYAH_IOCTL_TYPE, 0x3)
41 
42 /**
43  * enum gunyah_fn_type - Valid types of Gunyah VM functions
44  * @GUNYAH_FN_VCPU: create a vCPU instance to control a vCPU
45  *              &struct gunyah_fn_desc.arg is a pointer to &struct gunyah_fn_vcpu_arg
46  *              Return: file descriptor to manipulate the vcpu.
47  * @GUNYAH_FN_IRQFD: register eventfd to assert a Gunyah doorbell
48  *               &struct gunyah_fn_desc.arg is a pointer to &struct gunyah_fn_irqfd_arg
49  * @GUNYAH_FN_IOEVENTFD: register ioeventfd to trigger when VM faults on parameter
50  *                   &struct gunyah_fn_desc.arg is a pointer to &struct gunyah_fn_ioeventfd_arg
51  */
52 enum gunyah_fn_type {
53 	GUNYAH_FN_VCPU = 1,
54 	GUNYAH_FN_IRQFD,
55 	GUNYAH_FN_IOEVENTFD,
56 };
57 
58 #define GUNYAH_FN_MAX_ARG_SIZE		256
59 
60 /**
61  * struct gunyah_fn_vcpu_arg - Arguments to create a vCPU.
62  * @id: vcpu id
63  *
64  * Create this function with &GUNYAH_VM_ADD_FUNCTION using type &GUNYAH_FN_VCPU.
65  *
66  * The vcpu type will register with the VM Manager to expect to control
67  * vCPU number `vcpu_id`. It returns a file descriptor allowing interaction with
68  * the vCPU. See the Gunyah vCPU API description sections for interacting with
69  * the Gunyah vCPU file descriptors.
70  */
71 struct gunyah_fn_vcpu_arg {
72 	__u32 id;
73 };
74 
75 /**
76  * enum gunyah_irqfd_flags - flags for use in gunyah_fn_irqfd_arg
77  * @GUNYAH_IRQFD_FLAGS_LEVEL: make the interrupt operate like a level triggered
78  *                        interrupt on guest side. Triggering IRQFD before
79  *                        guest handles the interrupt causes interrupt to
80  *                        stay asserted.
81  */
82 enum gunyah_irqfd_flags {
83 	GUNYAH_IRQFD_FLAGS_LEVEL		= 1UL << 0,
84 };
85 
86 /**
87  * struct gunyah_fn_irqfd_arg - Arguments to create an irqfd function.
88  *
89  * Create this function with &GUNYAH_VM_ADD_FUNCTION using type &GUNYAH_FN_IRQFD.
90  *
91  * Allows setting an eventfd to directly trigger a guest interrupt.
92  * irqfd.fd specifies the file descriptor to use as the eventfd.
93  * irqfd.label corresponds to the doorbell label used in the guest VM's devicetree.
94  *
95  * @fd: an eventfd which when written to will raise a doorbell
96  * @label: Label of the doorbell created on the guest VM
97  * @flags: see &enum gunyah_irqfd_flags
98  * @padding: padding bytes
99  */
100 struct gunyah_fn_irqfd_arg {
101 	__u32 fd;
102 	__u32 label;
103 	__u32 flags;
104 	__u32 padding;
105 };
106 
107 /**
108  * enum gunyah_ioeventfd_flags - flags for use in gunyah_fn_ioeventfd_arg
109  * @GUNYAH_IOEVENTFD_FLAGS_DATAMATCH: the event will be signaled only if the
110  *                                written value to the registered address is
111  *                                equal to &struct gunyah_fn_ioeventfd_arg.datamatch
112  */
113 enum gunyah_ioeventfd_flags {
114 	GUNYAH_IOEVENTFD_FLAGS_DATAMATCH	= 1UL << 0,
115 };
116 
117 /**
118  * struct gunyah_fn_ioeventfd_arg - Arguments to create an ioeventfd function
119  * @datamatch: data used when GUNYAH_IOEVENTFD_DATAMATCH is set
120  * @addr: Address in guest memory
121  * @len: Length of access
122  * @fd: When ioeventfd is matched, this eventfd is written
123  * @flags: See &enum gunyah_ioeventfd_flags
124  * @padding: padding bytes
125  *
126  * Create this function with &GUNYAH_VM_ADD_FUNCTION using type &GUNYAH_FN_IOEVENTFD.
127  *
128  * Attaches an ioeventfd to a legal mmio address within the guest. A guest write
129  * in the registered address will signal the provided event instead of triggering
130  * an exit on the GUNYAH_VCPU_RUN ioctl.
131  */
132 struct gunyah_fn_ioeventfd_arg {
133 	__u64 datamatch;
134 	__u64 addr;        /* legal mmio address */
135 	__u32 len;         /* 1, 2, 4, or 8 bytes; or 0 to ignore length */
136 	__s32 fd;
137 	__u32 flags;
138 	__u32 padding;
139 };
140 
141 /**
142  * struct gunyah_fn_desc - Arguments to create a VM function
143  * @type: Type of the function. See &enum gunyah_fn_type.
144  * @arg_size: Size of argument to pass to the function. arg_size <= GUNYAH_FN_MAX_ARG_SIZE
145  * @arg: Pointer to argument given to the function. See &enum gunyah_fn_type for expected
146  *       arguments for a function type.
147  */
148 struct gunyah_fn_desc {
149 	__u32 type;
150 	__u32 arg_size;
151 	__u64 arg;
152 };
153 
154 #define GUNYAH_VM_ADD_FUNCTION	_IOW(GUNYAH_IOCTL_TYPE, 0x4, struct gunyah_fn_desc)
155 #define GUNYAH_VM_REMOVE_FUNCTION	_IOW(GUNYAH_IOCTL_TYPE, 0x7, struct gunyah_fn_desc)
156 
157 /**
158  * enum gunyah_map_flags- Possible flags on &struct gunyah_map_mem_args
159  * @GUNYAH_MEM_DEFAULT_SHARE: Use default host access for the VM type
160  * @GUNYAH_MEM_FORCE_LEND: Force unmapping the memory once the guest starts to use
161  * @GUNYAH_MEM_FORCE_SHARE: Allow host to continue accessing memory when guest starts to use
162  * @GUNYAH_MEM_ALLOW_READ: Allow guest to read memory
163  * @GUNYAH_MEM_ALLOW_WRITE: Allow guest to write to the memory
164  * @GUNYAH_MEM_ALLOW_EXEC: Allow guest to execute instructions in the memory
165  */
166 enum gunyah_map_flags {
167 	GUNYAH_MEM_ALLOW_READ = 1UL << 0,
168 	GUNYAH_MEM_ALLOW_WRITE = 1UL << 1,
169 	GUNYAH_MEM_ALLOW_EXEC = 1UL << 2,
170 	GUNYAH_MEM_ALLOW_RWX =
171 		(GUNYAH_MEM_ALLOW_READ | GUNYAH_MEM_ALLOW_WRITE | GUNYAH_MEM_ALLOW_EXEC),
172 	GUNYAH_MEM_DEFAULT_ACCESS = 0x00,
173 	GUNYAH_MEM_FORCE_LEND = 0x10,
174 	GUNYAH_MEM_FORCE_SHARE = 0x20,
175 #define GUNYAH_MEM_ACCESS_MASK 0x70
176 
177 	GUNYAH_MEM_UNMAP = 1UL << 8,
178 };
179 
180 /**
181  * struct gunyah_map_mem_args - Description to provide guest memory into a VM
182  * @guest_addr: Location in guest address space to place the memory
183  * @flags: See &enum gunyah_map_flags.
184  * @guest_mem_fd: File descriptor created by GUNYAH_CREATE_GUEST_MEM
185  * @offset: Offset into the guest memory file
186  */
187 struct gunyah_map_mem_args {
188 	__u64 guest_addr;
189 	__u32 flags;
190 	__u32 guest_mem_fd;
191 	__u64 offset;
192 	__u64 size;
193 };
194 
195 #define GUNYAH_VM_MAP_MEM _IOW(GUNYAH_IOCTL_TYPE, 0x9, struct gunyah_map_mem_args)
196 
197 enum gunyah_vm_boot_context_reg {
198 	REG_SET_X		= 0,
199 	REG_SET_PC		= 1,
200 	REG_SET_SP		= 2,
201 };
202 
203 #define GUNYAH_VM_BOOT_CONTEXT_REG_SHIFT	8
204 #define GUNYAH_VM_BOOT_CONTEXT_REG(reg, idx) (((reg & 0xff) << GUNYAH_VM_BOOT_CONTEXT_REG_SHIFT) |\
205 					      (idx & 0xff))
206 
207 /**
208  * struct gunyah_vm_boot_context - Set an initial register for the VM
209  * @reg: Register to set. See GUNYAH_VM_BOOT_CONTEXT_REG_* macros
210  * @reserved: reserved for alignment
211  * @value: value to fill in the register
212  */
213 struct gunyah_vm_boot_context {
214 	__u32 reg;
215 	__u32 reserved;
216 	__u64 value;
217 };
218 #define GUNYAH_VM_SET_BOOT_CONTEXT	_IOW(GUNYAH_IOCTL_TYPE, 0xa, struct gunyah_vm_boot_context)
219 
220 /*
221  * ioctls for vCPU fds
222  */
223 
224 /**
225  * enum gunyah_vm_status - Stores status reason why VM is not runnable (exited).
226  * @GUNYAH_VM_STATUS_LOAD_FAILED: VM didn't start because it couldn't be loaded.
227  * @GUNYAH_VM_STATUS_EXITED: VM requested shutdown/reboot.
228  *                       Use &struct gunyah_vm_exit_info.reason for further details.
229  * @GUNYAH_VM_STATUS_CRASHED: VM state is unknown and has crashed.
230  */
231 enum gunyah_vm_status {
232 	GUNYAH_VM_STATUS_LOAD_FAILED	= 1,
233 	GUNYAH_VM_STATUS_EXITED		= 2,
234 	GUNYAH_VM_STATUS_CRASHED		= 3,
235 };
236 
237 /*
238  * Gunyah presently sends max 4 bytes of exit_reason.
239  * If that changes, this macro can be safely increased without breaking
240  * userspace so long as struct gunyah_vcpu_run < PAGE_SIZE.
241  */
242 #define GUNYAH_VM_MAX_EXIT_REASON_SIZE	8u
243 
244 /**
245  * struct gunyah_vm_exit_info - Reason for VM exit as reported by Gunyah
246  * See Gunyah documentation for values.
247  * @type: Describes how VM exited
248  * @padding: padding bytes
249  * @reason_size: Number of bytes valid for `reason`
250  * @reason: See Gunyah documentation for interpretation. Note: these values are
251  *          not interpreted by Linux and need to be converted from little-endian
252  *          as applicable.
253  */
254 struct gunyah_vm_exit_info {
255 	__u16 type;
256 	__u16 padding;
257 	__u32 reason_size;
258 	__u8 reason[GUNYAH_VM_MAX_EXIT_REASON_SIZE];
259 };
260 
261 /**
262  * enum gunyah_vcpu_exit - Stores reason why &GUNYAH_VCPU_RUN ioctl recently exited with status 0
263  * @GUNYAH_VCPU_EXIT_UNKNOWN: Not used, status != 0
264  * @GUNYAH_VCPU_EXIT_MMIO: vCPU performed a read or write that could not be handled
265  *                     by hypervisor or Linux. Use @struct gunyah_vcpu_run.mmio for
266  *                     details of the read/write.
267  * @GUNYAH_VCPU_EXIT_STATUS: vCPU not able to run because the VM has exited.
268  *                       Use @struct gunyah_vcpu_run.status for why VM has exited.
269  * @GUNYAH_VCPU_EXIT_PAGE_FAULT: vCPU tried to execute an instruction at an address
270  *                               for which memory hasn't been provided. Use
271  *                               @struct gunyah_vcpu_run.page_fault for details.
272  */
273 enum gunyah_vcpu_exit {
274 	GUNYAH_VCPU_EXIT_UNKNOWN,
275 	GUNYAH_VCPU_EXIT_MMIO,
276 	GUNYAH_VCPU_EXIT_STATUS,
277 	GUNYAH_VCPU_EXIT_PAGE_FAULT,
278 };
279 
280 /**
281  * enum gunyah_vcpu_resume_action - Provide resume action after an MMIO or page fault
282  * @GUNYAH_VCPU_RESUME_HANDLED: The mmio or page fault has been handled, continue
283  *                              normal operation of vCPU
284  * @GUNYAH_VCPU_RESUME_FAULT: The mmio or page fault could not be satisfied and
285  *                            inject the original fault back to the guest.
286  * @GUNYAH_VCPU_RESUME_RETRY: Retry the faulting instruction. Perhaps you added
287  *                            memory binding to satisfy the request.
288  */
289 enum gunyah_vcpu_resume_action {
290 	GUNYAH_VCPU_RESUME_HANDLED = 0,
291 	GUNYAH_VCPU_RESUME_FAULT,
292 	GUNYAH_VCPU_RESUME_RETRY,
293 };
294 
295 /**
296  * struct gunyah_vcpu_run - Application code obtains a pointer to the gunyah_vcpu_run
297  *                      structure by mmap()ing a vcpu fd.
298  * @immediate_exit: polled when scheduling the vcpu. If set, immediately returns -EINTR.
299  * @padding: padding bytes
300  * @exit_reason: Set when GUNYAH_VCPU_RUN returns successfully and gives reason why
301  *               GUNYAH_VCPU_RUN has stopped running the vCPU. See &enum gunyah_vcpu_exit.
302  * @mmio: Used when exit_reason == GUNYAH_VCPU_EXIT_MMIO
303  *        The guest has faulted on an memory-mapped I/O that
304  *        couldn't be satisfied by gunyah.
305  * @mmio.phys_addr: Address guest tried to access
306  * @mmio.data: the value that was written if `is_write == 1`. Filled by
307  *        user for reads (`is_write == 0`).
308  * @mmio.len: Length of write. Only the first `len` bytes of `data`
309  *       are considered by Gunyah.
310  * @mmio.is_write: 1 if VM tried to perform a write, 0 for a read
311  * @mmio.resume_action: See &enum gunyah_vcpu_resume_action
312  * @status: Used when exit_reason == GUNYAH_VCPU_EXIT_STATUS.
313  *          The guest VM is no longer runnable. This struct informs why.
314  * @status.status: See &enum gunyah_vm_status for possible values
315  * @status.exit_info: Used when status == GUNYAH_VM_STATUS_EXITED
316  * @page_fault: Used when EXIT_REASON == GUNYAH_VCPU_EXIT_PAGE_FAULT
317  *              The guest has faulted on a region that can only be provided
318  *              by mapping memory at phys_addr.
319  * @page_fault.phys_addr: Address guest tried to access.
320  * @page_fault.attempt: Error code why Linux wasn't able to handle fault itself
321  *                      Typically, if no memory was mapped: -ENOENT,
322  *                      If permission bits weren't what the VM wanted: -EPERM
323  * @page_fault.resume_action: See &enum gunyah_vcpu_resume_action
324  */
325 struct gunyah_vcpu_run {
326 	/* in */
327 	__u8 immediate_exit;
328 	__u8 padding[7];
329 
330 	/* out */
331 	__u32 exit_reason;
332 
333 	union {
334 		struct {
335 			__u64 phys_addr;
336 			__u8  data[8];
337 			__u32 len;
338 			__u8  is_write;
339 			__u8  resume_action;
340 		} mmio;
341 
342 		struct {
343 			enum gunyah_vm_status status;
344 			struct gunyah_vm_exit_info exit_info;
345 		} status;
346 
347 		struct {
348 			__u64 phys_addr;
349 			__s32 attempt;
350 			__u8  resume_action;
351 		} page_fault;
352 	};
353 };
354 
355 #define GUNYAH_VCPU_RUN		_IO(GUNYAH_IOCTL_TYPE, 0x5)
356 #define GUNYAH_VCPU_MMAP_SIZE	_IO(GUNYAH_IOCTL_TYPE, 0x6)
357 
358 /**
359  * struct gunyah_userspace_memory_region - Userspace memory descripion for GH_VM_SET_USER_MEM_REGION
360  * @label: Identifer to the region which is unique to the VM.
361  * @flags: Flags for memory parcel behavior. See &enum gh_mem_flags.
362  * @guest_phys_addr: Location of the memory region in guest's memory space (page-aligned)
363  * @memory_size: Size of the region (page-aligned)
364  * @userspace_addr: Location of the memory region in caller (userspace)'s memory
365  *
366  * See Documentation/virt/gunyah/vm-manager.rst for further details.
367  */
368 struct gunyah_userspace_memory_region {
369 	__u32 label;
370 	__u32 flags;
371 	__u64 guest_phys_addr;
372 	__u64 memory_size;
373 	__u64 userspace_addr;
374 };
375 
376 #define GH_VM_SET_USER_MEM_REGION	_IOW(GUNYAH_IOCTL_TYPE, 0x1, \
377 						struct gunyah_userspace_memory_region)
378 #define GH_ANDROID_IOCTL_TYPE		'A'
379 
380 #define GH_VM_ANDROID_LEND_USER_MEM	_IOW(GH_ANDROID_IOCTL_TYPE, 0x11, \
381 						struct gunyah_userspace_memory_region)
382 
383 struct gunyah_vm_firmware_config {
384 	__u64 guest_phys_addr;
385 	__u64 size;
386 };
387 
388 #define GH_VM_ANDROID_SET_FW_CONFIG	_IOW(GH_ANDROID_IOCTL_TYPE, 0x12, \
389 						struct gunyah_vm_firmware_config)
390 
391 struct gunyah_address_range {
392 	__u64 guest_phys_addr;
393 	__u64 size;
394 };
395 
396 #define GH_VM_RECLAIM_REGION		_IOW(GH_ANDROID_IOCTL_TYPE, 0x13, \
397 						struct gunyah_address_range)
398 
399 
400 /**
401  * Obtain an fd for the CMA backed file.
402  */
403 #define GH_ANDROID_CREATE_CMA_MEM_FD _IO(GH_ANDROID_IOCTL_TYPE, 0x14)
404 
405 /**
406  * struct gunyah_map_cma_mem_args - Description to provide CMA based guest memory into a VM
407  * @guest_addr: Location in guest address space to place the memory
408  * @flags: See &enum gunyah_map_flags.
409  * @guest_mem_fd: File descriptor created by GH_ANDROID_CREATE_CMA_MEM_FD
410  * @offset: Offset into the guest memory file
411  * @size: Size of the region to be mapped.
412  */
413 struct gunyah_map_cma_mem_args {
414 	__u32 label;
415 	__u64 guest_addr;
416 	__u32 flags;
417 	__u32 guest_mem_fd;
418 	__u64 offset;
419 	__u64 size;
420 };
421 
422 #define GH_VM_ANDROID_MAP_CMA_MEM _IOW(GH_ANDROID_IOCTL_TYPE, 0x15, struct gunyah_map_cma_mem_args)
423 
424 /**
425  * enum gunyah_auth_type - Valid types of authentication supported by Gunyah
426  */
427 enum gunyah_auth_type {
428 	GUNYAH_QCOM_TRUSTED_VM_TYPE = 1,
429 };
430 
431 /**
432  * struct gunyah_qtvm_auth_arg - Argument to QTVM auth vm manager
433  * @vm_id: The VM ID that Gunyah associates with the QTVM.
434  * @peripheral_id: Also called pas_id which firmware needs for authenticating the QTVM.
435  * @guest_phys_addr: Address where the VM image should be mapped to.
436  * @size: Size of the VM image
437  */
438 struct gunyah_qtvm_auth_arg {
439 	__u16 vm_id;
440 	__u32 peripheral_id;
441 	__u64 guest_phys_addr;
442 	__u64 size;
443 };
444 
445 /**
446  * struct gunyah_auth_desc - Arguments to match with an auth vm manager
447  * @type: Type of the authentication mechanism. See &enum gunyah_auth_type.
448  * @arg_size: Size of argument to pass to the auth vm mgr. arg_size <= GUNYAH_FN_MAX_ARG_SIZE
449  * @arg: Pointer to argument given to the auth vm mgr. See &enum gunyah_auth_type for expected
450  *       arguments for a function type.
451  */
452 struct gunyah_auth_desc {
453 	__u32 type;
454 	__u32 arg_size;
455 	__u64 arg;
456 };
457 #define GH_VM_ANDROID_SET_AUTH_TYPE		_IOW(GH_ANDROID_IOCTL_TYPE, 0x16, \
458 							struct gunyah_auth_desc)
459 #endif
460