1e7818584SSudeep Holla /* SPDX-License-Identifier: GPL-2.0-only */ 2e7818584SSudeep Holla /* 3e7818584SSudeep Holla * Copyright (C) 2021 ARM Ltd. 4e7818584SSudeep Holla */ 5e7818584SSudeep Holla 6e7818584SSudeep Holla #ifndef _LINUX_ARM_FFA_H 7e7818584SSudeep Holla #define _LINUX_ARM_FFA_H 8e7818584SSudeep Holla 9e7818584SSudeep Holla #include <linux/device.h> 10e7818584SSudeep Holla #include <linux/module.h> 11e7818584SSudeep Holla #include <linux/types.h> 12e7818584SSudeep Holla #include <linux/uuid.h> 13e7818584SSudeep Holla 14e7818584SSudeep Holla /* FFA Bus/Device/Driver related */ 15e7818584SSudeep Holla struct ffa_device { 16e7818584SSudeep Holla int vm_id; 17d0c0bce8SSudeep Holla bool mode_32bit; 18e7818584SSudeep Holla uuid_t uuid; 19e7818584SSudeep Holla struct device dev; 20*d01387fcSSudeep Holla const struct ffa_dev_ops *ops; 21e7818584SSudeep Holla }; 22e7818584SSudeep Holla 23e7818584SSudeep Holla #define to_ffa_dev(d) container_of(d, struct ffa_device, dev) 24e7818584SSudeep Holla 25e7818584SSudeep Holla struct ffa_device_id { 26e7818584SSudeep Holla uuid_t uuid; 27e7818584SSudeep Holla }; 28e7818584SSudeep Holla 29e7818584SSudeep Holla struct ffa_driver { 30e7818584SSudeep Holla const char *name; 31e7818584SSudeep Holla int (*probe)(struct ffa_device *sdev); 32e7818584SSudeep Holla void (*remove)(struct ffa_device *sdev); 33e7818584SSudeep Holla const struct ffa_device_id *id_table; 34e7818584SSudeep Holla 35e7818584SSudeep Holla struct device_driver driver; 36e7818584SSudeep Holla }; 37e7818584SSudeep Holla 38e7818584SSudeep Holla #define to_ffa_driver(d) container_of(d, struct ffa_driver, driver) 39e7818584SSudeep Holla 40e7818584SSudeep Holla static inline void ffa_dev_set_drvdata(struct ffa_device *fdev, void *data) 41e7818584SSudeep Holla { 42498af8d1SSudeep Holla dev_set_drvdata(&fdev->dev, data); 43498af8d1SSudeep Holla } 44498af8d1SSudeep Holla 45498af8d1SSudeep Holla static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev) 46498af8d1SSudeep Holla { 47498af8d1SSudeep Holla return dev_get_drvdata(&fdev->dev); 48e7818584SSudeep Holla } 49e7818584SSudeep Holla 50e7818584SSudeep Holla #if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT) 51*d01387fcSSudeep Holla struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, 52*d01387fcSSudeep Holla const struct ffa_dev_ops *ops); 53e7818584SSudeep Holla void ffa_device_unregister(struct ffa_device *ffa_dev); 54e7818584SSudeep Holla int ffa_driver_register(struct ffa_driver *driver, struct module *owner, 55e7818584SSudeep Holla const char *mod_name); 56e7818584SSudeep Holla void ffa_driver_unregister(struct ffa_driver *driver); 57e7818584SSudeep Holla bool ffa_device_is_valid(struct ffa_device *ffa_dev); 58d0c0bce8SSudeep Holla const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev); 59e7818584SSudeep Holla 60e7818584SSudeep Holla #else 61e7818584SSudeep Holla static inline 62*d01387fcSSudeep Holla struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, 63*d01387fcSSudeep Holla const struct ffa_dev_ops *ops) 64e7818584SSudeep Holla { 65e7818584SSudeep Holla return NULL; 66e7818584SSudeep Holla } 67e7818584SSudeep Holla 68e7818584SSudeep Holla static inline void ffa_device_unregister(struct ffa_device *dev) {} 69e7818584SSudeep Holla 70e7818584SSudeep Holla static inline int 71e7818584SSudeep Holla ffa_driver_register(struct ffa_driver *driver, struct module *owner, 72e7818584SSudeep Holla const char *mod_name) 73e7818584SSudeep Holla { 74e7818584SSudeep Holla return -EINVAL; 75e7818584SSudeep Holla } 76e7818584SSudeep Holla 77e7818584SSudeep Holla static inline void ffa_driver_unregister(struct ffa_driver *driver) {} 78e7818584SSudeep Holla 79e7818584SSudeep Holla static inline 80e7818584SSudeep Holla bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; } 81e7818584SSudeep Holla 82d0c0bce8SSudeep Holla static inline 83d0c0bce8SSudeep Holla const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev) 84d0c0bce8SSudeep Holla { 85d0c0bce8SSudeep Holla return NULL; 86d0c0bce8SSudeep Holla } 87e7818584SSudeep Holla #endif /* CONFIG_ARM_FFA_TRANSPORT */ 88e7818584SSudeep Holla 89e7818584SSudeep Holla #define ffa_register(driver) \ 90e7818584SSudeep Holla ffa_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) 91e7818584SSudeep Holla #define ffa_unregister(driver) \ 92e7818584SSudeep Holla ffa_driver_unregister(driver) 93e7818584SSudeep Holla 94e7818584SSudeep Holla /** 95e7818584SSudeep Holla * module_ffa_driver() - Helper macro for registering a psa_ffa driver 96e7818584SSudeep Holla * @__ffa_driver: ffa_driver structure 97e7818584SSudeep Holla * 98e7818584SSudeep Holla * Helper macro for psa_ffa drivers to set up proper module init / exit 99e7818584SSudeep Holla * functions. Replaces module_init() and module_exit() and keeps people from 100e7818584SSudeep Holla * printing pointless things to the kernel log when their driver is loaded. 101e7818584SSudeep Holla */ 102e7818584SSudeep Holla #define module_ffa_driver(__ffa_driver) \ 103e7818584SSudeep Holla module_driver(__ffa_driver, ffa_register, ffa_unregister) 104e7818584SSudeep Holla 105d0c0bce8SSudeep Holla /* FFA transport related */ 106d0c0bce8SSudeep Holla struct ffa_partition_info { 107d0c0bce8SSudeep Holla u16 id; 108d0c0bce8SSudeep Holla u16 exec_ctxt; 109d0c0bce8SSudeep Holla /* partition supports receipt of direct requests */ 110d0c0bce8SSudeep Holla #define FFA_PARTITION_DIRECT_RECV BIT(0) 111d0c0bce8SSudeep Holla /* partition can send direct requests. */ 112d0c0bce8SSudeep Holla #define FFA_PARTITION_DIRECT_SEND BIT(1) 113d0c0bce8SSudeep Holla /* partition can send and receive indirect messages. */ 114d0c0bce8SSudeep Holla #define FFA_PARTITION_INDIRECT_MSG BIT(2) 115d0c0bce8SSudeep Holla u32 properties; 116d0c0bce8SSudeep Holla }; 117d0c0bce8SSudeep Holla 118d0c0bce8SSudeep Holla /* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */ 119d0c0bce8SSudeep Holla struct ffa_send_direct_data { 120d0c0bce8SSudeep Holla unsigned long data0; /* w3/x3 */ 121d0c0bce8SSudeep Holla unsigned long data1; /* w4/x4 */ 122d0c0bce8SSudeep Holla unsigned long data2; /* w5/x5 */ 123d0c0bce8SSudeep Holla unsigned long data3; /* w6/x6 */ 124d0c0bce8SSudeep Holla unsigned long data4; /* w7/x7 */ 125d0c0bce8SSudeep Holla }; 126d0c0bce8SSudeep Holla 127cc2195feSSudeep Holla struct ffa_mem_region_addr_range { 128cc2195feSSudeep Holla /* The base IPA of the constituent memory region, aligned to 4 kiB */ 129cc2195feSSudeep Holla u64 address; 130cc2195feSSudeep Holla /* The number of 4 kiB pages in the constituent memory region. */ 131cc2195feSSudeep Holla u32 pg_cnt; 132cc2195feSSudeep Holla u32 reserved; 133cc2195feSSudeep Holla }; 134cc2195feSSudeep Holla 135cc2195feSSudeep Holla struct ffa_composite_mem_region { 136cc2195feSSudeep Holla /* 137cc2195feSSudeep Holla * The total number of 4 kiB pages included in this memory region. This 138cc2195feSSudeep Holla * must be equal to the sum of page counts specified in each 139cc2195feSSudeep Holla * `struct ffa_mem_region_addr_range`. 140cc2195feSSudeep Holla */ 141cc2195feSSudeep Holla u32 total_pg_cnt; 142cc2195feSSudeep Holla /* The number of constituents included in this memory region range */ 143cc2195feSSudeep Holla u32 addr_range_cnt; 144cc2195feSSudeep Holla u64 reserved; 145cc2195feSSudeep Holla /** An array of `addr_range_cnt` memory region constituents. */ 146cc2195feSSudeep Holla struct ffa_mem_region_addr_range constituents[]; 147cc2195feSSudeep Holla }; 148cc2195feSSudeep Holla 149cc2195feSSudeep Holla struct ffa_mem_region_attributes { 150cc2195feSSudeep Holla /* The ID of the VM to which the memory is being given or shared. */ 151cc2195feSSudeep Holla u16 receiver; 152cc2195feSSudeep Holla /* 153cc2195feSSudeep Holla * The permissions with which the memory region should be mapped in the 154cc2195feSSudeep Holla * receiver's page table. 155cc2195feSSudeep Holla */ 156cc2195feSSudeep Holla #define FFA_MEM_EXEC BIT(3) 157cc2195feSSudeep Holla #define FFA_MEM_NO_EXEC BIT(2) 158cc2195feSSudeep Holla #define FFA_MEM_RW BIT(1) 159cc2195feSSudeep Holla #define FFA_MEM_RO BIT(0) 160cc2195feSSudeep Holla u8 attrs; 161cc2195feSSudeep Holla /* 162cc2195feSSudeep Holla * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP 163cc2195feSSudeep Holla * for memory regions with multiple borrowers. 164cc2195feSSudeep Holla */ 165cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_SELF_BORROWER BIT(0) 166cc2195feSSudeep Holla u8 flag; 167cc2195feSSudeep Holla u32 composite_off; 168cc2195feSSudeep Holla /* 169cc2195feSSudeep Holla * Offset in bytes from the start of the outer `ffa_memory_region` to 170cc2195feSSudeep Holla * an `struct ffa_mem_region_addr_range`. 171cc2195feSSudeep Holla */ 172cc2195feSSudeep Holla u64 reserved; 173cc2195feSSudeep Holla }; 174cc2195feSSudeep Holla 175cc2195feSSudeep Holla struct ffa_mem_region { 176cc2195feSSudeep Holla /* The ID of the VM/owner which originally sent the memory region */ 177cc2195feSSudeep Holla u16 sender_id; 178cc2195feSSudeep Holla #define FFA_MEM_NORMAL BIT(5) 179cc2195feSSudeep Holla #define FFA_MEM_DEVICE BIT(4) 180cc2195feSSudeep Holla 181cc2195feSSudeep Holla #define FFA_MEM_WRITE_BACK (3 << 2) 182cc2195feSSudeep Holla #define FFA_MEM_NON_CACHEABLE (1 << 2) 183cc2195feSSudeep Holla 184cc2195feSSudeep Holla #define FFA_DEV_nGnRnE (0 << 2) 185cc2195feSSudeep Holla #define FFA_DEV_nGnRE (1 << 2) 186cc2195feSSudeep Holla #define FFA_DEV_nGRE (2 << 2) 187cc2195feSSudeep Holla #define FFA_DEV_GRE (3 << 2) 188cc2195feSSudeep Holla 189cc2195feSSudeep Holla #define FFA_MEM_NON_SHAREABLE (0) 190cc2195feSSudeep Holla #define FFA_MEM_OUTER_SHAREABLE (2) 191cc2195feSSudeep Holla #define FFA_MEM_INNER_SHAREABLE (3) 192cc2195feSSudeep Holla u8 attributes; 193cc2195feSSudeep Holla u8 reserved_0; 194cc2195feSSudeep Holla /* 195cc2195feSSudeep Holla * Clear memory region contents after unmapping it from the sender and 196cc2195feSSudeep Holla * before mapping it for any receiver. 197cc2195feSSudeep Holla */ 198cc2195feSSudeep Holla #define FFA_MEM_CLEAR BIT(0) 199cc2195feSSudeep Holla /* 200cc2195feSSudeep Holla * Whether the hypervisor may time slice the memory sharing or retrieval 201cc2195feSSudeep Holla * operation. 202cc2195feSSudeep Holla */ 203cc2195feSSudeep Holla #define FFA_TIME_SLICE_ENABLE BIT(1) 204cc2195feSSudeep Holla 205cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_TYPE_IN_RESP (0 << 3) 206cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_TYPE_SHARE (1 << 3) 207cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_TYPE_LEND (2 << 3) 208cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_TYPE_DONATE (3 << 3) 209cc2195feSSudeep Holla 210cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_ADDR_ALIGN_HINT BIT(9) 211cc2195feSSudeep Holla #define FFA_MEM_RETRIEVE_ADDR_ALIGN(x) ((x) << 5) 212cc2195feSSudeep Holla /* Flags to control behaviour of the transaction. */ 213cc2195feSSudeep Holla u32 flags; 214cc2195feSSudeep Holla #define HANDLE_LOW_MASK GENMASK_ULL(31, 0) 215cc2195feSSudeep Holla #define HANDLE_HIGH_MASK GENMASK_ULL(63, 32) 216cc2195feSSudeep Holla #define HANDLE_LOW(x) ((u32)(FIELD_GET(HANDLE_LOW_MASK, (x)))) 217cc2195feSSudeep Holla #define HANDLE_HIGH(x) ((u32)(FIELD_GET(HANDLE_HIGH_MASK, (x)))) 218cc2195feSSudeep Holla 219cc2195feSSudeep Holla #define PACK_HANDLE(l, h) \ 220cc2195feSSudeep Holla (FIELD_PREP(HANDLE_LOW_MASK, (l)) | FIELD_PREP(HANDLE_HIGH_MASK, (h))) 221cc2195feSSudeep Holla /* 222cc2195feSSudeep Holla * A globally-unique ID assigned by the hypervisor for a region 223cc2195feSSudeep Holla * of memory being sent between VMs. 224cc2195feSSudeep Holla */ 225cc2195feSSudeep Holla u64 handle; 226cc2195feSSudeep Holla /* 227cc2195feSSudeep Holla * An implementation defined value associated with the receiver and the 228cc2195feSSudeep Holla * memory region. 229cc2195feSSudeep Holla */ 230cc2195feSSudeep Holla u64 tag; 231cc2195feSSudeep Holla u32 reserved_1; 232cc2195feSSudeep Holla /* 233cc2195feSSudeep Holla * The number of `ffa_mem_region_attributes` entries included in this 234cc2195feSSudeep Holla * transaction. 235cc2195feSSudeep Holla */ 236cc2195feSSudeep Holla u32 ep_count; 237cc2195feSSudeep Holla /* 238cc2195feSSudeep Holla * An array of endpoint memory access descriptors. 239cc2195feSSudeep Holla * Each one specifies a memory region offset, an endpoint and the 240cc2195feSSudeep Holla * attributes with which this memory region should be mapped in that 241cc2195feSSudeep Holla * endpoint's page table. 242cc2195feSSudeep Holla */ 243cc2195feSSudeep Holla struct ffa_mem_region_attributes ep_mem_access[]; 244cc2195feSSudeep Holla }; 245cc2195feSSudeep Holla 246cc2195feSSudeep Holla #define COMPOSITE_OFFSET(x) \ 247cc2195feSSudeep Holla (offsetof(struct ffa_mem_region, ep_mem_access[x])) 248cc2195feSSudeep Holla #define CONSTITUENTS_OFFSET(x) \ 249cc2195feSSudeep Holla (offsetof(struct ffa_composite_mem_region, constituents[x])) 250cc2195feSSudeep Holla #define COMPOSITE_CONSTITUENTS_OFFSET(x, y) \ 251cc2195feSSudeep Holla (COMPOSITE_OFFSET(x) + CONSTITUENTS_OFFSET(y)) 252cc2195feSSudeep Holla 253cc2195feSSudeep Holla struct ffa_mem_ops_args { 254cc2195feSSudeep Holla bool use_txbuf; 255cc2195feSSudeep Holla u32 nattrs; 256cc2195feSSudeep Holla u32 flags; 257cc2195feSSudeep Holla u64 tag; 258cc2195feSSudeep Holla u64 g_handle; 259cc2195feSSudeep Holla struct scatterlist *sg; 260cc2195feSSudeep Holla struct ffa_mem_region_attributes *attrs; 261cc2195feSSudeep Holla }; 262cc2195feSSudeep Holla 263d0c0bce8SSudeep Holla struct ffa_dev_ops { 264d0c0bce8SSudeep Holla u32 (*api_version_get)(void); 265d0c0bce8SSudeep Holla int (*partition_info_get)(const char *uuid_str, 266d0c0bce8SSudeep Holla struct ffa_partition_info *buffer); 267d0c0bce8SSudeep Holla void (*mode_32bit_set)(struct ffa_device *dev); 268d0c0bce8SSudeep Holla int (*sync_send_receive)(struct ffa_device *dev, 269d0c0bce8SSudeep Holla struct ffa_send_direct_data *data); 270cc2195feSSudeep Holla int (*memory_reclaim)(u64 g_handle, u32 flags); 271cc2195feSSudeep Holla int (*memory_share)(struct ffa_device *dev, 272cc2195feSSudeep Holla struct ffa_mem_ops_args *args); 27382a8daaeSMarc Bonnici int (*memory_lend)(struct ffa_device *dev, 27482a8daaeSMarc Bonnici struct ffa_mem_ops_args *args); 275d0c0bce8SSudeep Holla }; 276d0c0bce8SSudeep Holla 277e7818584SSudeep Holla #endif /* _LINUX_ARM_FFA_H */ 278