+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_SMC_32(func_id),
+ .a1 = total_length,
+ .a2 = total_length,
+ .a3 = 0, /* the TX buffer is used */
+ .a4 = 0, /* the TX buffer is used */
+ },
+ &res
+ );
+
+ if (res.a0 != FFA_SMC_32(FFA_SUCCESS)) {
+ ffa_errno = res.a2;
+ ffa_print_error_log(func_id, ffa_errno);
+ return ffa_to_std_errno(ffa_errno);
+ }
+
+ args->g_handle = PACK_HANDLE(res.a2, res.a3);
+ return 0;
+}
+
+/**
+ * ffa_memory_ops() - wrapper for the memory management ABIs
+ * @dev: The FF-A bus device
+ * @func_id: An integer identifying the function
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Verify the use of the TX buffer then call ffa_setup_and_transmit().
+ * Currently we support FFA_MEM_SHARE only.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_memory_ops(struct udevice *dev, u32 func_id,
+ struct ffa_mem_ops_args *args)
+{
+ void *buffer;
+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ if (!args->use_txbuf) {
+ log_err("only TX buffer supported\n");
+ return -EPROTONOSUPPORT;
+ }
+
+ buffer = uc_priv->pair.txbuf;
+
+ if (!buffer || !args->attrs || !args->address)
+ return -EINVAL;
+
+ return ffa_setup_and_transmit(dev, func_id, buffer, args);
+}
+
+/**
+ * ffa_memory_share_hdlr() - FFA_MEM_SHARE handler function
+ * @dev: The FF-A bus device
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Implement FFA_MEM_SHARE FF-A function
+ * to grant access to a memory region to one or more Borrowers.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args)
+{
+ return ffa_memory_ops(dev, FFA_MEM_SHARE, args);
+}
+
/* FF-A driver operations (used by clients for communicating with FF-A)*/
/**
@@ -1006,6 +1191,31 @@ int ffa_rxtx_unmap(struct udevice *dev)
return ops->rxtx_unmap(dev);
}
+/**
+ * ffa_memory_share() - FFA_MEM_SHARE driver operation
+ * @dev: The FF-A bus device
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Driver operation for FFA_MEM_SHARE.
+ * Please see ffa_memory_share_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args)
+{
+ struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+ if (!args)
+ return -EINVAL;
+
+ if (!ops->memory_share)
+ return -ENOSYS;
+
+ return ops->memory_share(dev, args);
+}
+
/**
* ffa_do_probe() - probing FF-A framework
* @dev: the FF-A bus device (arm_ffa)
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c
b/drivers/firmware/arm-ffa/arm-ffa.c
index 94e6105cb38..df904cae412 100644
--- a/drivers/firmware/arm-ffa/arm-ffa.c
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2022-2023 Arm Limited and/or its affiliates
<open-source-off...@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates
<open-source-off...@arm.com>
*
* Authors:
* Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
@@ -84,6 +84,7 @@ static const struct ffa_bus_ops ffa_ops = {
.partition_info_get = ffa_get_partitions_info_hdlr,
.sync_send_receive = ffa_msg_send_direct_req_hdlr,
.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
+ .memory_share = ffa_memory_share_hdlr,
};
/* Registering the FF-A driver as an SMCCC feature driver */
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index 2994d8ee3ae..b91b0279371 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright 2022-2023 Arm Limited and/or its affiliates
<open-source-off...@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates
<open-source-off...@arm.com>
*
* Authors:
* Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
@@ -81,11 +81,74 @@ struct ffa_send_direct_data {
struct udevice;
+/**
+ * struct ffa_mem_region_attributes - Endpoint memory access descriptor
+ *
+ * The data structure used in memory management transactions to create an
+ * association between an endpoint, memory access permissions and a composite
+ * memory region description.
+ *
+ * For more details, please refer to Table 5.16 and Table 5.15 in the FF-A
+ * specification v1.0.
+ *
+ * This structure was taken from Linux.
+ */
+struct ffa_mem_region_attributes {
+ /* The ID of the VM to which the memory is being given or shared. */
+ u16 receiver;
+ /*
+ * The permissions with which the memory region should be mapped in the
+ * receiver's page table.
+ */
+#define FFA_MEM_EXEC BIT(3)
+#define FFA_MEM_NO_EXEC BIT(2)
+#define FFA_MEM_RW BIT(1)
+#define FFA_MEM_RO BIT(0)
+ u8 attrs;
+ /*
+ * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP
+ * for memory regions with multiple borrowers.
+ */
+#define FFA_MEM_RETRIEVE_SELF_BORROWER BIT(0)
+ u8 flag;
+ /*
+ * Offset in bytes from the start of the outer `ffa_memory_region` to
+ * an `struct ffa_mem_region_addr_range`.
+ */
+ u32 composite_off;
+ u64 reserved;
+};
+
+/**
+ * struct ffa_mem_ops_args - User arguments to the memory management ABIs
+ * @use_txbuf: Whether to use the TX buffer for the memory transaction
+ * @nattrs: Number of the borrowers
+ * @flags: Memory transaction flags
+ * @tag: The tag associated with the transaction
+ * @g_handle: Globally unique Handle to identify the memory region (out)
+ * @address: Virtual address of the memory region
+ * @attrs: Memory access permissions of each borrower
+ *
+ * The structured filled by the user and passed to the memory
+ * management ABIs (e.g: FFA_MEM_SHARE)
+ */
+struct ffa_mem_ops_args {
+ bool use_txbuf;
+ u32 nattrs;
+ u32 flags;
+ u64 tag;
+ u64 g_handle;
+ void *address;
+ u32 pg_cnt;
+ struct ffa_mem_region_attributes *attrs;
+};
+
/**
* struct ffa_bus_ops - Operations for FF-A
* @partition_info_get: callback for the FFA_PARTITION_INFO_GET
* @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
* @rxtx_unmap: callback for the FFA_RXTX_UNMAP
+ * @memory_share: callback for the FFA_MEM_SHARE
*
* The data structure providing all the operations supported by the driver.
* This structure is EFI runtime resident.
@@ -97,6 +160,7 @@ struct ffa_bus_ops {
struct ffa_send_direct_data *msg,
bool is_smc64);
int (*rxtx_unmap)(struct udevice *dev);
+ int (*memory_share)(struct udevice *dev, struct ffa_mem_ops_args *args);
};
#define ffa_get_ops(dev) ((struct ffa_bus_ops *)(dev)->driver->ops)
@@ -196,6 +260,26 @@ int ffa_partition_info_get(struct udevice *dev, const char
*uuid_str,
int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
u32 *sp_count, struct ffa_partition_desc
**sp_descs);
+/**
+ * ffa_memory_share() - FFA_MEM_SHARE driver operation
+ * Please see ffa_memory_share_hdlr() description for more details.
+ */
+int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args);
+
+/**
+ * ffa_memory_share_hdlr() - FFA_MEM_SHARE handler function
+ * @dev: The FF-A bus device
+ * @args: A pointer to a structure containing additional user arguments
+ *
+ * Implement FFA_MEM_SHARE FF-A function
+ * to grant access to a memory region to one or more Borrowers.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args);
+
struct ffa_priv;
/**
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
index d564c33c647..a259911d5b9 100644
--- a/include/arm_ffa_priv.h
+++ b/include/arm_ffa_priv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * Copyright 2022-2023 Arm Limited and/or its affiliates
<open-source-off...@arm.com>
+ * Copyright 2022-2023, 2025 Arm Limited and/or its affiliates
<open-source-off...@arm.com>
*
* Authors:
* Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
@@ -132,10 +132,11 @@ enum ffa_abis {
FFA_RUN = 0x6d,
FFA_MSG_SEND_DIRECT_REQ = 0x6f,
FFA_MSG_SEND_DIRECT_RESP = 0x70,
+ FFA_MEM_SHARE = 0x73,
/* To be updated when adding new FFA IDs */
FFA_FIRST_ID = FFA_ERROR, /* Lowest number ID */
- FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* Highest number
ID */
+ FFA_LAST_ID = FFA_MEM_SHARE, /* Highest number ID */
};
enum ffa_abi_errcode {
@@ -219,6 +220,143 @@ struct ffa_priv {
struct ffa_rxtxpair pair;
};
+/* FF-A memory management ABIs data structures */
+
+/**
+ * struct ffa_mem_region - Lend, donate or share memory transaction descriptor
+ *
+ * Specifies the data structure that must be used by the Owner/Lender and a
+ * Borrower/Receiver in a transaction to donate, lend or share a memory region.
+ * It specifies the memory region description, properties and other transaction
+ * attributes in an invocation of the following ABIs.
+ *
+ * FFA_MEM_DONATE.
+ * FFA_MEM_LEND.
+ * FFA_MEM_SHARE.
+ * FFA_MEM_RETRIEVE_REQ.
+ * FFA_MEM_RETRIEVE_RESP.
+ *
+ * For more details, please refer to the Table 5.19 in the FF-A specification
+ * v1.0.
+ *
+ * The interpretation of some fields depends on the ABI this structure is used
+ * with. This variance in behavior is also specified in the Table 5.19.
+ *
+ * This structure was taken from Linux and adapted to FF-A v1.0.
+ */
+struct ffa_mem_region {
+ /* The ID of the VM/owner which originally sent the memory region */
+ u16 sender_id;
+#define FFA_MEM_NORMAL BIT(5)
+#define FFA_MEM_DEVICE BIT(4)
+
+#define FFA_MEM_WRITE_BACK (3 << 2)
+#define FFA_MEM_NON_CACHEABLE BIT(2)
+
+#define FFA_DEV_nGnRnE (0 << 2)
+#define FFA_DEV_nGnRE BIT(2)
+#define FFA_MEM_RETRIEVE_TYPE_LEND (2 << 3)
+#define FFA_MEM_RETRIEVE_TYPE_DONATE (3 << 3)
+
+#define FFA_MEM_RETRIEVE_ADDR_ALIGN_HINT BIT(9)
+#define FFA_MEM_RETRIEVE_ADDR_ALIGN(x) ((x) << 5)
+ /* Flags to control behaviour of the transaction. */
+ u32 flags;
+#define HANDLE_LOW_MASK GENMASK_ULL(31, 0)
+#define HANDLE_HIGH_MASK GENMASK_ULL(63, 32)
+#define HANDLE_LOW(x) ((u32)(FIELD_GET(HANDLE_LOW_MASK, (x))))
+#define HANDLE_HIGH(x) ((u32)(FIELD_GET(HANDLE_HIGH_MASK,
(x))))
+
+#define PACK_HANDLE(l, h) \
+ (FIELD_PREP(HANDLE_LOW_MASK, (l)) | FIELD_PREP(HANDLE_HIGH_MASK, (h)))
+ /*
+ * A globally-unique ID assigned by the hypervisor for a region
+ * of memory being sent between VMs.
+ */
+ u64 handle;
+ /*
+ * An implementation defined value associated with the receiver and the
+ * memory region.
+ */
+ u64 tag;
+
+ u32 reserved2;
+
+ /*
+ * The number of `ffa_mem_region_attributes` entries included in this
+ * transaction.
+ */
+ u32 ep_count;
+};
+
+/**
+ * struct ffa_mem_region_addr_range - Constituent memory region descriptor
+ *
+ * Each descriptor specifies the base address and size of a virtually or
+ * physically contiguous memory region.
+ *
+ * For more details, please refer to Table 5.14 in the FF-A
+ * specification v1.0.
+ *
+ * This structure was taken from Linux.
+ */
+struct ffa_mem_region_addr_range {
+ /* The base IPA of the constituent memory region, aligned to 4 kiB */
+ u64 address;
+ /* The number of 4 kiB pages in the constituent memory region. */
+ u32 pg_cnt;
+ u32 reserved;
+};
+
+/**
+ * struct ffa_composite_mem_region - Composite memory region descriptor
+ *
+ * For more details, please refer to Table 5.13 in the FF-A
+ * specification v1.0.
+ *
+ * This structure was taken from Linux.
+ */
+struct ffa_composite_mem_region {
+ /*
+ * The total number of 4 kiB pages included in this memory region. This
+ * must be equal to the sum of page counts specified in each
+ * `struct ffa_mem_region_addr_range`.
+ */
+ u32 total_pg_cnt;
+ /* The number of constituents included in this memory region range */
+#define FFA_MEM_CONSTITUENTS (1)
+ u32 addr_range_cnt;
+ u64 reserved;
+ /** An array of `addr_range_cnt` memory region constituents. */
+ struct ffa_mem_region_addr_range constituents[];
+};
+
+/* Functions prototypes */
+
/**
* ffa_get_version_hdlr() - FFA_VERSION handler function
* @dev: The FF-A bus device
--
2.25.1