[PATCH 3/8] arm_ffa: Add FFA_MEM_RECLAIM support

abdellatif.elkhlifi
2024-11-01T14:21:17Z

Add to the FF-A bus FFA_MEM_RECLAIM ABI

The FFA_MEM_RECLAIM is a memory management ABI described in the FF-A
v1.0 specification [1].

This ABI restores exclusive access to a memory region back to its Owner.

This work is based on the implementation in Linux [2].

[1]: https://developer.arm.com/documentation/den0077/a/?lang=en
[2]: commit cc2195fe536c28e192df5d07e6dd277af36814b4
File: drivers/firmware/arm_ffa/driver.c

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
doc/arch/arm64.ffa.rst | 2 +
drivers/firmware/arm-ffa/arm-ffa-uclass.c | 70 +++++++++++++++++++++++
drivers/firmware/arm-ffa/arm-ffa.c | 1 +
include/arm_ffa.h | 25 +++++++-
include/arm_ffa_priv.h | 3 +-
5 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 3eec735d741..d2c4fb49f79 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -186,6 +186,7 @@ The following features are provided:
- FFA_MSG_SEND_DIRECT_REQ
- FFA_MSG_SEND_DIRECT_RESP
- FFA_MEM_SHARE
+ - FFA_MEM_RECLAIM

- Support for the 64-bit version of the following ABIs:

@@ -205,6 +206,7 @@ The following features are provided:
- ffa_sync_send_receive
- ffa_rxtx_unmap
- ffa_memory_share
+ - ffa_memory_reclaim

- FF-A bus discovery makes sure FF-A framework is responsive and compatible
with the driver
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
index 8ff666c3757..5eae28386ae 100644
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -109,6 +109,18 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
"DENIED: Memory region ownership, permission, access or attributes error",
},
},
+ [FFA_ID_TO_ERRMAP_ID(FFA_MEM_RECLAIM)] = {
+ {
+ [ABORTED] =
+ "ABORTED: ABI invocation failure",
+ [INVALID_PARAMETERS] =
+ "INVALID_PARAMETERS: Invalid handle or flags",
+ [NO_MEMORY] =
+ "NO_MEMORY: Failure to create the Owner's mapping",
+ [DENIED] =
+ "DENIED: Memory region state issue",
+ },
+ },
};

/**
@@ -1115,6 +1127,41 @@ int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args)
return ffa_memory_ops(dev, FFA_MEM_SHARE, args);
}

+/**
+ * ffa_memory_reclaim_hdlr() - FFA_MEM_RECLAIM handler function
+ * @dev: The FF-A bus device
+ * @g_handle: The memory region globally unique Handle
+ * @flags: Zero memory and time slicing flags
+ *
+ * Implement FFA_MEM_RECLAIM FF-A function
+ * to restore exclusive access to a memory region back to its Owner.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_reclaim_hdlr(struct udevice *dev, u64 g_handle, u32 flags)
+{
+ ffa_value_t res;
+ int ffa_errno;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_SMC_32(FFA_MEM_RECLAIM),
+ .a1 = HANDLE_LOW(g_handle), .a2 = HANDLE_HIGH(g_handle),
+ .a3 = flags,
+ },
+ &res
+ );
+
+ if (res.a0 != FFA_SMC_32(FFA_SUCCESS)) {
+ ffa_errno = res.a2;
+ ffa_print_error_log(FFA_MEM_RECLAIM, ffa_errno);
+ return ffa_to_std_errno(ffa_errno);
+ }
+
+ return 0;
+}
+
/* FF-A driver operations (used by clients for communicating with FF-A)*/

/**
@@ -1214,6 +1261,29 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args)
return ops->memory_share(dev, args);
}

+/**
+ * ffa_memory_reclaim() - FFA_MEM_RECLAIM driver operation
+ * @dev: The FF-A bus device
+ * @g_handle: The memory region globally unique Handle
+ * @flags: Zero memory and time slicing flags
+ *
+ * Driver operation for FFA_MEM_RECLAIM.
+ * Please see ffa_memory_reclaim_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_reclaim(struct udevice *dev, u64 g_handle, u32 flags)
+{
+ struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+ if (!ops || !ops->memory_reclaim)
+ return -ENOSYS;
+
+ return ops->memory_reclaim(dev, g_handle, flags);
+}
+
/**
* 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 c4211c953ef..b7e751e3821 100644
--- a/drivers/firmware/arm-ffa/arm-ffa.c
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -85,6 +85,7 @@ static const struct ffa_bus_ops ffa_ops = {
.sync_send_receive = ffa_msg_send_direct_req_hdlr,
.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
.memory_share = ffa_memory_share_hdlr,
+ .memory_reclaim = ffa_memory_reclaim_hdlr,
};

/* Registering the FF-A driver as an SMCCC feature driver */
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index ce4a3d7f440..965139b166a 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -147,8 +147,9 @@ struct ffa_mem_ops_args {
* 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
+ * @rxtx_unmap: callback for the FFA_RXTX_UNMAP
* @memory_share: callback for the FFA_MEM_SHARE
+ * @memory_reclaim: callback for the FFA_MEM_RECLAIM
*
* The data structure providing all the operations supported by the driver.
* This structure is EFI runtime resident.
@@ -161,6 +162,7 @@ struct ffa_bus_ops {
bool is_smc64);
int (*rxtx_unmap)(struct udevice *dev);
int (*memory_share)(struct udevice *dev, struct ffa_mem_ops_args *args);
+ int (*memory_reclaim)(struct udevice *dev, u64 g_handle, u32 flags);
};

#define ffa_get_ops(dev) ((struct ffa_bus_ops *)(dev)->driver->ops)
@@ -280,6 +282,27 @@ int ffa_memory_share(struct udevice *dev, struct ffa_mem_ops_args *args);
*/
int ffa_memory_share_hdlr(struct udevice *dev, struct ffa_mem_ops_args *args);

+/**
+ * ffa_memory_reclaim() - FFA_MEM_RECLAIM driver operation
+ * Please see ffa_memory_reclaim_hdlr() description for more details.
+ */
+int ffa_memory_reclaim(struct udevice *dev, u64 g_handle, u32 flags);
+
+/**
+ * ffa_memory_reclaim_hdlr() - FFA_MEM_RECLAIM handler function
+ * @dev: The FF-A bus device
+ * @g_handle: The memory region globally unique Handle
+ * @flags: Zero memory and time slicing flags
+ *
+ * Implement FFA_MEM_RECLAIM FF-A function
+ * to restore exclusive access to a memory region back to its Owner.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_memory_reclaim_hdlr(struct udevice *dev, u64 g_handle, u32 flags);
+
struct ffa_priv;

/**
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
index 02e2cd89937..09205f40907 100644
--- a/include/arm_ffa_priv.h
+++ b/include/arm_ffa_priv.h
@@ -133,10 +133,11 @@ enum ffa_abis {
FFA_MSG_SEND_DIRECT_REQ = 0x6f,
FFA_MSG_SEND_DIRECT_RESP = 0x70,
FFA_MEM_SHARE = 0x73,
+ FFA_MEM_RECLAIM = 0x77,

/* To be updated when adding new FFA IDs */
FFA_FIRST_ID = FFA_ERROR, /* Lowest number ID */
- FFA_LAST_ID = FFA_MEM_SHARE, /* Highest number ID */
+ FFA_LAST_ID = FFA_MEM_RECLAIM, /* Highest number ID */
};

enum ffa_abi_errcode {
--
2.25.1