/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _UAPI_LINUX_GUNYAH_H #define _UAPI_LINUX_GUNYAH_H /* * Userspace interface for /dev/gunyah - gunyah based virtual machine */ #include #include #define GH_IOCTL_TYPE 'G' /* * ioctls for /dev/gunyah fds: */ #define GH_CREATE_VM _IO(GH_IOCTL_TYPE, 0x0) /* Returns a Gunyah VM fd */ /* * ioctls for VM fds */ /** * enum gh_mem_flags - Possible flags on &struct gh_userspace_memory_region * @GH_MEM_ALLOW_READ: Allow guest to read the memory * @GH_MEM_ALLOW_WRITE: Allow guest to write to the memory * @GH_MEM_ALLOW_EXEC: Allow guest to execute instructions in the memory */ enum gh_mem_flags { GH_MEM_ALLOW_READ = 1UL << 0, GH_MEM_ALLOW_WRITE = 1UL << 1, GH_MEM_ALLOW_EXEC = 1UL << 2, }; /** * struct gh_userspace_memory_region - Userspace memory descripion for GH_VM_SET_USER_MEM_REGION * @label: Identifer to the region which is unique to the VM. * @flags: Flags for memory parcel behavior. See &enum gh_mem_flags. * @guest_phys_addr: Location of the memory region in guest's memory space (page-aligned) * @memory_size: Size of the region (page-aligned) * @userspace_addr: Location of the memory region in caller (userspace)'s memory * * See Documentation/virt/gunyah/vm-manager.rst for further details. */ struct gh_userspace_memory_region { __u32 label; __u32 flags; __u64 guest_phys_addr; __u64 memory_size; __u64 userspace_addr; }; #define GH_VM_SET_USER_MEM_REGION _IOW(GH_IOCTL_TYPE, 0x1, \ struct gh_userspace_memory_region) /** * struct gh_vm_dtb_config - Set the location of the VM's devicetree blob * @guest_phys_addr: Address of the VM's devicetree in guest memory. * @size: Maximum size of the devicetree including space for overlays. * Resource manager applies an overlay to the DTB and dtb_size should * include room for the overlay. A page of memory is typicaly plenty. */ struct gh_vm_dtb_config { __u64 guest_phys_addr; __u64 size; }; #define GH_VM_SET_DTB_CONFIG _IOW(GH_IOCTL_TYPE, 0x2, struct gh_vm_dtb_config) #define GH_VM_START _IO(GH_IOCTL_TYPE, 0x3) /** * enum gh_fn_type - Valid types of Gunyah VM functions * @GH_FN_VCPU: create a vCPU instance to control a vCPU * &struct gh_fn_desc.arg is a pointer to &struct gh_fn_vcpu_arg * Return: file descriptor to manipulate the vcpu. * @GH_FN_IRQFD: register eventfd to assert a Gunyah doorbell * &struct gh_fn_desc.arg is a pointer to &struct gh_fn_irqfd_arg * @GH_FN_IOEVENTFD: register ioeventfd to trigger when VM faults on parameter * &struct gh_fn_desc.arg is a pointer to &struct gh_fn_ioeventfd_arg */ enum gh_fn_type { GH_FN_VCPU = 1, GH_FN_IRQFD, GH_FN_IOEVENTFD, }; #define GH_FN_MAX_ARG_SIZE 256 /** * struct gh_fn_vcpu_arg - Arguments to create a vCPU. * @id: vcpu id * * Create this function with &GH_VM_ADD_FUNCTION using type &GH_FN_VCPU. * * The vcpu type will register with the VM Manager to expect to control * vCPU number `vcpu_id`. It returns a file descriptor allowing interaction with * the vCPU. See the Gunyah vCPU API description sections for interacting with * the Gunyah vCPU file descriptors. */ struct gh_fn_vcpu_arg { __u32 id; }; /** * enum gh_irqfd_flags - flags for use in gh_fn_irqfd_arg * @GH_IRQFD_FLAGS_LEVEL: make the interrupt operate like a level triggered * interrupt on guest side. Triggering IRQFD before * guest handles the interrupt causes interrupt to * stay asserted. */ enum gh_irqfd_flags { GH_IRQFD_FLAGS_LEVEL = 1UL << 0, }; /** * struct gh_fn_irqfd_arg - Arguments to create an irqfd function. * * Create this function with &GH_VM_ADD_FUNCTION using type &GH_FN_IRQFD. * * Allows setting an eventfd to directly trigger a guest interrupt. * irqfd.fd specifies the file descriptor to use as the eventfd. * irqfd.label corresponds to the doorbell label used in the guest VM's devicetree. * * @fd: an eventfd which when written to will raise a doorbell * @label: Label of the doorbell created on the guest VM * @flags: see &enum gh_irqfd_flags * @padding: padding bytes */ struct gh_fn_irqfd_arg { __u32 fd; __u32 label; __u32 flags; __u32 padding; }; /** * enum gh_ioeventfd_flags - flags for use in gh_fn_ioeventfd_arg * @GH_IOEVENTFD_FLAGS_DATAMATCH: the event will be signaled only if the * written value to the registered address is * equal to &struct gh_fn_ioeventfd_arg.datamatch */ enum gh_ioeventfd_flags { GH_IOEVENTFD_FLAGS_DATAMATCH = 1UL << 0, }; /** * struct gh_fn_ioeventfd_arg - Arguments to create an ioeventfd function * @datamatch: data used when GH_IOEVENTFD_DATAMATCH is set * @addr: Address in guest memory * @len: Length of access * @fd: When ioeventfd is matched, this eventfd is written * @flags: See &enum gh_ioeventfd_flags * @padding: padding bytes * * Create this function with &GH_VM_ADD_FUNCTION using type &GH_FN_IOEVENTFD. * * Attaches an ioeventfd to a legal mmio address within the guest. A guest write * in the registered address will signal the provided event instead of triggering * an exit on the GH_VCPU_RUN ioctl. */ struct gh_fn_ioeventfd_arg { __u64 datamatch; __u64 addr; /* legal mmio address */ __u32 len; /* 1, 2, 4, or 8 bytes; or 0 to ignore length */ __s32 fd; __u32 flags; __u32 padding; }; /** * struct gh_fn_desc - Arguments to create a VM function * @type: Type of the function. See &enum gh_fn_type. * @arg_size: Size of argument to pass to the function. arg_size <= GH_FN_MAX_ARG_SIZE * @arg: Pointer to argument given to the function. See &enum gh_fn_type for expected * arguments for a function type. */ struct gh_fn_desc { __u32 type; __u32 arg_size; __u64 arg; }; #define GH_VM_ADD_FUNCTION _IOW(GH_IOCTL_TYPE, 0x4, struct gh_fn_desc) #define GH_VM_REMOVE_FUNCTION _IOW(GH_IOCTL_TYPE, 0x7, struct gh_fn_desc) /* * ioctls for vCPU fds */ /** * enum gh_vm_status - Stores status reason why VM is not runnable (exited). * @GH_VM_STATUS_LOAD_FAILED: VM didn't start because it couldn't be loaded. * @GH_VM_STATUS_EXITED: VM requested shutdown/reboot. * Use &struct gh_vm_exit_info.reason for further details. * @GH_VM_STATUS_CRASHED: VM state is unknown and has crashed. */ enum gh_vm_status { GH_VM_STATUS_LOAD_FAILED = 1, GH_VM_STATUS_EXITED = 2, GH_VM_STATUS_CRASHED = 3, }; /* * Gunyah presently sends max 4 bytes of exit_reason. * If that changes, this macro can be safely increased without breaking * userspace so long as struct gh_vcpu_run < PAGE_SIZE. */ #define GH_VM_MAX_EXIT_REASON_SIZE 8u /** * struct gh_vm_exit_info - Reason for VM exit as reported by Gunyah * See Gunyah documentation for values. * @type: Describes how VM exited * @padding: padding bytes * @reason_size: Number of bytes valid for `reason` * @reason: See Gunyah documentation for interpretation. Note: these values are * not interpreted by Linux and need to be converted from little-endian * as applicable. */ struct gh_vm_exit_info { __u16 type; __u16 padding; __u32 reason_size; __u8 reason[GH_VM_MAX_EXIT_REASON_SIZE]; }; /** * enum gh_vcpu_exit - Stores reason why &GH_VCPU_RUN ioctl recently exited with status 0 * @GH_VCPU_EXIT_UNKNOWN: Not used, status != 0 * @GH_VCPU_EXIT_MMIO: vCPU performed a read or write that could not be handled * by hypervisor or Linux. Use @struct gh_vcpu_run.mmio for * details of the read/write. * @GH_VCPU_EXIT_STATUS: vCPU not able to run because the VM has exited. * Use @struct gh_vcpu_run.status for why VM has exited. */ enum gh_vcpu_exit { GH_VCPU_EXIT_UNKNOWN, GH_VCPU_EXIT_MMIO, GH_VCPU_EXIT_STATUS, }; /** * struct gh_vcpu_run - Application code obtains a pointer to the gh_vcpu_run * structure by mmap()ing a vcpu fd. * @immediate_exit: polled when scheduling the vcpu. If set, immediately returns -EINTR. * @padding: padding bytes * @exit_reason: Set when GH_VCPU_RUN returns successfully and gives reason why * GH_VCPU_RUN has stopped running the vCPU. See &enum gh_vcpu_exit. * @mmio: Used when exit_reason == GH_VCPU_EXIT_MMIO * The guest has faulted on an memory-mapped I/O instruction that * couldn't be satisfied by gunyah. * @mmio.phys_addr: Address guest tried to access * @mmio.data: the value that was written if `is_write == 1`. Filled by * user for reads (`is_write == 0`). * @mmio.len: Length of write. Only the first `len` bytes of `data` * are considered by Gunyah. * @mmio.is_write: 1 if VM tried to perform a write, 0 for a read * @status: Used when exit_reason == GH_VCPU_EXIT_STATUS. * The guest VM is no longer runnable. This struct informs why. * @status.status: See &enum gh_vm_status for possible values * @status.exit_info: Used when status == GH_VM_STATUS_EXITED */ struct gh_vcpu_run { /* in */ __u8 immediate_exit; __u8 padding[7]; /* out */ __u32 exit_reason; union { struct { __u64 phys_addr; __u8 data[8]; __u32 len; __u8 is_write; } mmio; struct { enum gh_vm_status status; struct gh_vm_exit_info exit_info; } status; }; }; #define GH_VCPU_RUN _IO(GH_IOCTL_TYPE, 0x5) #define GH_VCPU_MMAP_SIZE _IO(GH_IOCTL_TYPE, 0x6) /** * ANDROID: android14-6.1 unfortunately contains UAPI that won't be carried * in kernel.org. Expose orthogonal ioctls that will never conflict with * kernel.org for these UAPIs. See b/268234781. */ #define GH_ANDROID_IOCTL_TYPE 'A' #define GH_VM_ANDROID_LEND_USER_MEM _IOW(GH_ANDROID_IOCTL_TYPE, 0x11, \ struct gh_userspace_memory_region) struct gh_vm_firmware_config { __u64 guest_phys_addr; __u64 size; }; #define GH_VM_ANDROID_SET_FW_CONFIG _IOW(GH_ANDROID_IOCTL_TYPE, 0x12, \ struct gh_vm_firmware_config) #endif