Hypervisor might need to know the accurate address and size of dtb passed from userspace. And then hypervisor would parse the dtb and get vm information. Change-Id: I23194d45f5c60555ba7fde9dd8d393443fd41310 Signed-off-by: Jerry Wang <ze-yu.wang@mediatek.com> Signed-off-by: Liju-clr Chen <liju-clr.chen@mediatek.com> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com> Bug: 280363874 Link: https://lore.kernel.org/lkml/20230727080005.14474-10-yi-de.wu@mediatek.com/
343 lines
9.7 KiB
C
343 lines
9.7 KiB
C
/* 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>
|
|
|
|
#include <asm/gzvm_arch.h>
|
|
|
|
/* 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_ARM_PROTECTED_VM or GZVM_CAP_ARM_VM_IPA_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,
|
|
};
|
|
|
|
/**
|
|
* 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
|
|
* @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;
|
|
} 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];
|
|
};
|
|
};
|
|
|
|
/* for GZVM_ENABLE_CAP */
|
|
struct gzvm_enable_cap {
|
|
/* in */
|
|
__u64 cap;
|
|
/**
|
|
* we have total 5 (8 - 3) registers can be used for
|
|
* additional args
|
|
*/
|
|
__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__ */
|