blob: a98787a18c3607c6386dffa1fb6a6e0732658439 [file] [log] [blame]
/* 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 <linux/const.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#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__ */