android_kernel_msm-6.1_noth.../include/uapi/linux/gzvm.h
Yi-De Wu 7cc3767c2a FROMLIST: virt: geniezone: Add block-based demand paging support
To balance memory usage and performance, GenieZone supports larger
granularity demand paging, called block-based demand paging.
Gzvm driver uses enable_cap to query the hypervisor if it supports
block-based demand paging and the given granularity or not. Meanwhile,
the gzvm driver allocates a shared buffer for storing the physical
pages later.

If the hypervisor supports, every time the gzvm driver handles guest
page faults, it allocates more memory in advance (default: 2MB) for
demand paging. And fills those physical pages into the allocated shared
memory, then calls the hypervisor to map to guest's memory.

The physical pages allocated for block-based demand paging is not
necessary to be contiguous because in many cases, 2MB block is not
followed. 1st, the memory is allocated because of VMM's page fault
(VMM loads kernel image to guest memory before running). In this case,
the page is allocated by the host kernel and using PAGE_SIZE. 2nd is
that guest may return memory to host via ballooning and that is still
4KB (or PAGE_SIZE) granularity. Therefore, we do not have to allocate
physically contiguous 2MB pages.

Change-Id: Id101da5a8ff73dbf5c9a3ab03526cdf5d2f6006e
Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: kevenny hsieh <kevenny.hsieh@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: 301179926
Link: https://lore.kernel.org/all/20230919111210.19615-16-yi-de.wu@mediatek.com/
2023-10-20 16:31:15 +00:00

390 lines
12 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>
#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,
};
/**
* 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__ */