/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * Copyright (c) 2023 MediaTek Inc. */ /** * DOC: UAPI of GenieZone Hypervisor * * This file declares common data structure shared among user space, * kernel space, and GenieZone hypervisor. */ #ifndef __GZVM_H__ #define __GZVM_H__ #include #include #include #define GZVM_CAP_VM_GPA_SIZE 0xa5 #define GZVM_CAP_PROTECTED_VM 0xffbadab1 /* query hypervisor supported block-based demand page */ #define GZVM_CAP_BLOCK_BASED_DEMAND_PAGING 0x9201 /* sub-commands put in args[0] for GZVM_CAP_PROTECTED_VM */ #define GZVM_CAP_PVM_SET_PVMFW_GPA 0 #define GZVM_CAP_PVM_GET_PVMFW_SIZE 1 /* GZVM_CAP_PVM_SET_PROTECTED_VM only sets protected but not load pvmfw */ #define GZVM_CAP_PVM_SET_PROTECTED_VM 2 /* * Architecture specific registers are to be defined and ORed with * the arch identifier. */ #define GZVM_REG_ARCH_ARM64 0x6000000000000000ULL #define GZVM_REG_ARCH_MASK 0xff00000000000000ULL /* * Reg size = BIT((reg.id & GZVM_REG_SIZE_MASK) >> GZVM_REG_SIZE_SHIFT) bytes */ #define GZVM_REG_SIZE_SHIFT 52 #define GZVM_REG_SIZE_MASK 0x00f0000000000000ULL #define GZVM_REG_SIZE_U8 0x0000000000000000ULL #define GZVM_REG_SIZE_U16 0x0010000000000000ULL #define GZVM_REG_SIZE_U32 0x0020000000000000ULL #define GZVM_REG_SIZE_U64 0x0030000000000000ULL #define GZVM_REG_SIZE_U128 0x0040000000000000ULL #define GZVM_REG_SIZE_U256 0x0050000000000000ULL #define GZVM_REG_SIZE_U512 0x0060000000000000ULL #define GZVM_REG_SIZE_U1024 0x0070000000000000ULL #define GZVM_REG_SIZE_U2048 0x0080000000000000ULL /* Register type definitions */ #define GZVM_REG_TYPE_SHIFT 16 /* Register type: general purpose */ #define GZVM_REG_TYPE_GENERAL (0x10 << GZVM_REG_TYPE_SHIFT) /* GZVM ioctls */ #define GZVM_IOC_MAGIC 0x92 /* gz */ /* ioctls for /dev/gzvm fds */ #define GZVM_CREATE_VM _IO(GZVM_IOC_MAGIC, 0x01) /* Returns a Geniezone VM fd */ /* * Check if the given capability is supported or not. * The argument is capability. Ex. GZVM_CAP_PROTECTED_VM or GZVM_CAP_VM_GPA_SIZE * return is 0 (supported, no error) * return is -EOPNOTSUPP (unsupported) * return is -EFAULT (failed to get the argument from userspace) */ #define GZVM_CHECK_EXTENSION _IO(GZVM_IOC_MAGIC, 0x03) /* ioctls for VM fds */ /* for GZVM_SET_MEMORY_REGION */ struct gzvm_memory_region { __u32 slot; __u32 flags; __u64 guest_phys_addr; __u64 memory_size; /* bytes */ }; #define GZVM_SET_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x40, \ struct gzvm_memory_region) /* * GZVM_CREATE_VCPU receives as a parameter the vcpu slot, * and returns a vcpu fd. */ #define GZVM_CREATE_VCPU _IO(GZVM_IOC_MAGIC, 0x41) /* for GZVM_SET_USER_MEMORY_REGION */ struct gzvm_userspace_memory_region { __u32 slot; __u32 flags; __u64 guest_phys_addr; /* bytes */ __u64 memory_size; /* start of the userspace allocated memory */ __u64 userspace_addr; }; #define GZVM_SET_USER_MEMORY_REGION _IOW(GZVM_IOC_MAGIC, 0x46, \ struct gzvm_userspace_memory_region) /* for GZVM_IRQ_LINE, irq field index values */ #define GZVM_IRQ_VCPU_MASK 0xff #define GZVM_IRQ_LINE_TYPE GENMASK(27, 24) #define GZVM_IRQ_LINE_VCPU GENMASK(23, 16) #define GZVM_IRQ_LINE_VCPU2 GENMASK(31, 28) #define GZVM_IRQ_LINE_NUM GENMASK(15, 0) /* irq_type field */ #define GZVM_IRQ_TYPE_CPU 0 #define GZVM_IRQ_TYPE_SPI 1 #define GZVM_IRQ_TYPE_PPI 2 /* out-of-kernel GIC cpu interrupt injection irq_number field */ #define GZVM_IRQ_CPU_IRQ 0 #define GZVM_IRQ_CPU_FIQ 1 struct gzvm_irq_level { union { __u32 irq; __s32 status; }; __u32 level; }; #define GZVM_IRQ_LINE _IOW(GZVM_IOC_MAGIC, 0x61, \ struct gzvm_irq_level) enum gzvm_device_type { GZVM_DEV_TYPE_ARM_VGIC_V3_DIST = 0, GZVM_DEV_TYPE_ARM_VGIC_V3_REDIST = 1, GZVM_DEV_TYPE_MAX, }; /** * struct gzvm_create_device: For GZVM_CREATE_DEVICE. * @dev_type: Device type. * @id: Device id. * @flags: Bypass to hypervisor to handle them and these are flags of virtual * devices. * @dev_addr: Device ipa address in VM's view. * @dev_reg_size: Device register range size. * @attr_addr: If user -> kernel, this is user virtual address of device * specific attributes (if needed). If kernel->hypervisor, * this is ipa. * @attr_size: This attr_size is the buffer size in bytes of each attribute * needed from various devices. The attribute here refers to the * additional data passed from VMM(e.g. Crosvm) to GenieZone * hypervisor when virtual devices were to be created. Thus, * we need attr_addr and attr_size in the gzvm_create_device * structure to keep track of the attribute mentioned. * * Store information needed to create device. */ struct gzvm_create_device { __u32 dev_type; __u32 id; __u64 flags; __u64 dev_addr; __u64 dev_reg_size; __u64 attr_addr; __u64 attr_size; }; #define GZVM_CREATE_DEVICE _IOWR(GZVM_IOC_MAGIC, 0xe0, \ struct gzvm_create_device) /* * ioctls for vcpu fds */ #define GZVM_RUN _IO(GZVM_IOC_MAGIC, 0x80) /* VM exit reason */ enum { GZVM_EXIT_UNKNOWN = 0x92920000, GZVM_EXIT_MMIO = 0x92920001, GZVM_EXIT_HYPERCALL = 0x92920002, GZVM_EXIT_IRQ = 0x92920003, GZVM_EXIT_EXCEPTION = 0x92920004, GZVM_EXIT_DEBUG = 0x92920005, GZVM_EXIT_FAIL_ENTRY = 0x92920006, GZVM_EXIT_INTERNAL_ERROR = 0x92920007, GZVM_EXIT_SYSTEM_EVENT = 0x92920008, GZVM_EXIT_SHUTDOWN = 0x92920009, GZVM_EXIT_GZ = 0x9292000a, }; /* exception definitions of GZVM_EXIT_EXCEPTION */ enum { GZVM_EXCEPTION_UNKNOWN = 0x0, GZVM_EXCEPTION_PAGE_FAULT = 0x1, }; /* hypercall definitions of GZVM_EXIT_HYPERCALL */ enum { GZVM_HVC_MEM_RELINQUISH = 0xc6000009, }; /** * struct gzvm_vcpu_run: Same purpose as kvm_run, this struct is * shared between userspace, kernel and * GenieZone hypervisor * @exit_reason: The reason why gzvm_vcpu_run has stopped running the vCPU * @immediate_exit: Polled when the vcpu is scheduled. * If set, immediately returns -EINTR * @padding1: Reserved for future-proof and must be zero filled * @mmio: The nested struct in anonymous union. Handle mmio in host side * @phys_addr: The address guest tries to access * @data: The value to be written (is_write is 1) or * be filled by user for reads (is_write is 0) * @size: The size of written data. * Only the first `size` bytes of `data` are handled * @reg_nr: The register number where the data is stored * @is_write: 1 for VM to perform a write or 0 for VM to perform a read * @fail_entry: The nested struct in anonymous union. * Handle invalid entry address at the first run * @hardware_entry_failure_reason: The reason codes about hardware entry failure * @cpu: The current processor number via smp_processor_id() * @exception: The nested struct in anonymous union. * Handle exception occurred in VM * @exception: Which exception vector * @error_code: Exception error codes * @fault_gpa: Fault GPA (guest physical address or IPA in ARM) * @reserved: Future-proof reservation and reset to zero in hypervisor. * Fill up to the union size, 256 bytes. * @hypercall: The nested struct in anonymous union. * Some hypercalls issued from VM must be handled * @args: The hypercall's arguments * @internal: The nested struct in anonymous union. The errors from hypervisor * @suberror: The errors codes about GZVM_EXIT_INTERNAL_ERROR * @ndata: The number of elements used in data[] * @data: Keep the detailed information about GZVM_EXIT_INTERNAL_ERROR * @system_event: The nested struct in anonymous union. * VM's PSCI must be handled by host * @type: System event type. * Ex. GZVM_SYSTEM_EVENT_SHUTDOWN or GZVM_SYSTEM_EVENT_RESET...etc. * @ndata: The number of elements used in data[] * @data: Keep the detailed information about GZVM_EXIT_SYSTEM_EVENT * @padding: Fix it to a reasonable size future-proof for keeping the same * struct size when adding new variables in the union is needed * * Keep identical layout between the 3 modules */ struct gzvm_vcpu_run { /* to userspace */ __u32 exit_reason; __u8 immediate_exit; __u8 padding1[3]; /* union structure of collection of guest exit reason */ union { /* GZVM_EXIT_MMIO */ struct { /* from FAR_EL2 */ __u64 phys_addr; __u8 data[8]; /* from ESR_EL2 as */ __u64 size; /* from ESR_EL2 */ __u32 reg_nr; /* from ESR_EL2 */ __u8 is_write; } mmio; /* GZVM_EXIT_FAIL_ENTRY */ struct { __u64 hardware_entry_failure_reason; __u32 cpu; } fail_entry; /* GZVM_EXIT_EXCEPTION */ struct { __u32 exception; __u32 error_code; __u64 fault_gpa; __u64 reserved[30]; } exception; /* GZVM_EXIT_HYPERCALL */ struct { __u64 args[8]; /* in-out */ } hypercall; /* GZVM_EXIT_INTERNAL_ERROR */ struct { __u32 suberror; __u32 ndata; __u64 data[16]; } internal; /* GZVM_EXIT_SYSTEM_EVENT */ struct { #define GZVM_SYSTEM_EVENT_SHUTDOWN 1 #define GZVM_SYSTEM_EVENT_RESET 2 #define GZVM_SYSTEM_EVENT_CRASH 3 #define GZVM_SYSTEM_EVENT_WAKEUP 4 #define GZVM_SYSTEM_EVENT_SUSPEND 5 #define GZVM_SYSTEM_EVENT_SEV_TERM 6 #define GZVM_SYSTEM_EVENT_S2IDLE 7 __u32 type; __u32 ndata; __u64 data[16]; } system_event; char padding[256]; }; }; /** * struct gzvm_enable_cap: The `capability support` on GenieZone hypervisor * @cap: `GZVM_CAP_ARM_PROTECTED_VM` or `GZVM_CAP_ARM_VM_IPA_SIZE` * @args: x3-x7 registers can be used for additional args */ struct gzvm_enable_cap { __u64 cap; __u64 args[5]; }; #define GZVM_ENABLE_CAP _IOW(GZVM_IOC_MAGIC, 0xa3, \ struct gzvm_enable_cap) /* for GZVM_GET/SET_ONE_REG */ struct gzvm_one_reg { __u64 id; __u64 addr; }; #define GZVM_GET_ONE_REG _IOW(GZVM_IOC_MAGIC, 0xab, \ struct gzvm_one_reg) #define GZVM_SET_ONE_REG _IOW(GZVM_IOC_MAGIC, 0xac, \ struct gzvm_one_reg) #define GZVM_REG_GENERIC 0x0000000000000000ULL #define GZVM_IRQFD_FLAG_DEASSIGN BIT(0) /* * GZVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies * the irqfd to operate in resampling mode for level triggered interrupt * emulation. */ #define GZVM_IRQFD_FLAG_RESAMPLE BIT(1) /** * struct gzvm_irqfd: gzvm irqfd descriptor * @fd: File descriptor. * @gsi: Used for level IRQ fast-path. * @flags: FLAG_DEASSIGN or FLAG_RESAMPLE. * @resamplefd: The file descriptor of the resampler. * @pad: Reserved for future-proof. */ struct gzvm_irqfd { __u32 fd; __u32 gsi; __u32 flags; __u32 resamplefd; __u8 pad[16]; }; #define GZVM_IRQFD _IOW(GZVM_IOC_MAGIC, 0x76, struct gzvm_irqfd) enum { gzvm_ioeventfd_flag_nr_datamatch = 0, gzvm_ioeventfd_flag_nr_pio = 1, gzvm_ioeventfd_flag_nr_deassign = 2, gzvm_ioeventfd_flag_nr_max, }; #define GZVM_IOEVENTFD_FLAG_DATAMATCH (1 << gzvm_ioeventfd_flag_nr_datamatch) #define GZVM_IOEVENTFD_FLAG_PIO (1 << gzvm_ioeventfd_flag_nr_pio) #define GZVM_IOEVENTFD_FLAG_DEASSIGN (1 << gzvm_ioeventfd_flag_nr_deassign) #define GZVM_IOEVENTFD_VALID_FLAG_MASK ((1 << gzvm_ioeventfd_flag_nr_max) - 1) struct gzvm_ioeventfd { __u64 datamatch; /* private: legal pio/mmio address */ __u64 addr; /* private: 1, 2, 4, or 8 bytes; or 0 to ignore length */ __u32 len; __s32 fd; __u32 flags; __u8 pad[36]; }; #define GZVM_IOEVENTFD _IOW(GZVM_IOC_MAGIC, 0x79, struct gzvm_ioeventfd) /** * struct gzvm_dtb_config: store address and size of dtb passed from userspace * * @dtb_addr: dtb address set by VMM (guset memory) * @dtb_size: dtb size */ struct gzvm_dtb_config { __u64 dtb_addr; __u64 dtb_size; }; #define GZVM_SET_DTB_CONFIG _IOW(GZVM_IOC_MAGIC, 0xff, \ struct gzvm_dtb_config) #endif /* __GZVM_H__ */