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