Merge changes from topic "el3_direct_msg"
* changes:
feat: use x0-x17 for ff-a calls
test: add discovery of el3 spmd logical partitions
feat(ff-a): partition information via registers
diff --git a/include/runtime_services/ffa_endpoints.h b/include/runtime_services/ffa_endpoints.h
index 88055c4..26297bc 100644
--- a/include/runtime_services/ffa_endpoints.h
+++ b/include/runtime_services/ffa_endpoints.h
@@ -14,12 +14,14 @@
#define SECONDARY_UUID {0x092358d1, 0xb94723f0, 0x64447c82, 0xc88f57f5}
#define TERTIARY_UUID {0x735cb579, 0xb9448c1d, 0xe1619385, 0xd2d80a77}
#define IVY_UUID {0xd883baea, 0xaf4eafba, 0xfdf74481, 0xa744e5cb}
+#define EL3_SPMD_LP_UUID {0xe98e43ad, 0xb7db524f, 0x47a3bf57, 0x1588f4e3}
/* vcpu_count of cactus SPs. */
#define PRIMARY_EXEC_CTX_COUNT PLATFORM_CORE_COUNT
#define SECONDARY_EXEC_CTX_COUNT PLATFORM_CORE_COUNT
#define TERTIARY_EXEC_CTX_COUNT (1)
#define IVY_EXEC_CTX_COUNT (1)
+#define EL3_SPMD_LP_EXEC_CTX_COUNT (1)
/* UUID of OPTEE SP as defined in the respective manifest. */
#define OPTEE_UUID {0x486178e0, 0xe7f811e3, 0xbc5e0002, 0xa5d5c51b}
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 8ce6ed3..a7cdcb5 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -22,7 +22,7 @@
typedef uint8_t ffa_memory_receiver_flags_t;
struct ffa_uuid {
- const uint32_t uuid[4];
+ uint32_t uuid[4];
};
/** Length in bytes of the name in boot information descriptor. */
@@ -188,6 +188,16 @@
u_register_t arg5;
u_register_t arg6;
u_register_t arg7;
+ u_register_t arg8;
+ u_register_t arg9;
+ u_register_t arg10;
+ u_register_t arg11;
+ u_register_t arg12;
+ u_register_t arg13;
+ u_register_t arg14;
+ u_register_t arg15;
+ u_register_t arg16;
+ u_register_t arg17;
};
/* Function to make an SMC or SVC service call depending on the exception
@@ -237,6 +247,47 @@
return (uint32_t)val.arg2;
}
+static inline uint16_t ffa_partition_info_regs_get_last_idx(
+ struct ffa_value args)
+{
+ return args.arg2 & 0xFFFF;
+}
+
+static inline uint16_t ffa_partition_info_regs_get_curr_idx(
+ struct ffa_value args)
+{
+ return (args.arg2 >> 16) & 0xFFFF;
+}
+
+static inline uint16_t ffa_partition_info_regs_get_tag(struct ffa_value args)
+{
+ return (args.arg2 >> 32) & 0xFFFF;
+}
+
+static inline uint16_t ffa_partition_info_regs_get_desc_size(
+ struct ffa_value args)
+{
+ return (args.arg2 >> 48);
+}
+
+static inline uint32_t ffa_partition_info_regs_partition_count(
+ struct ffa_value args)
+{
+ return ffa_partition_info_regs_get_last_idx(args) + 1;
+}
+
+static inline uint32_t ffa_partition_info_regs_entry_count(
+ struct ffa_value args, uint16_t start_idx)
+{
+ return (ffa_partition_info_regs_get_curr_idx(args) - start_idx + 1);
+}
+
+static inline uint16_t ffa_partition_info_regs_entry_size(
+ struct ffa_value args)
+{
+ return (args.arg2 >> 48) & 0xFFFFU;
+}
+
typedef uint64_t ffa_notification_bitmap_t;
#define FFA_NOTIFICATION(ID) (UINT64_C(1) << ID)
@@ -703,7 +754,9 @@
struct ffa_value ffa_notification_info_get(void);
struct ffa_value ffa_console_log(const char* message, size_t char_count);
-
+struct ffa_value ffa_partition_info_get_regs(const struct ffa_uuid uuid,
+ const uint16_t start_index,
+ const uint16_t tag);
#endif /* __ASSEMBLY__ */
#endif /* FFA_HELPERS_H */
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index 6236ae3..bf535ea 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -100,6 +100,7 @@
#define FFA_FNUM_SPM_ID_GET U(0x85)
#define FFA_FNUM_MSG_SEND2 U(0x86)
#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x87)
+#define FFA_FNUM_PARTITION_INFO_GET_REGS U(0x8B)
/* Implementation defined function numbers */
#define FFA_FNUM_CONSOLE_LOG U(0x8A)
@@ -165,6 +166,8 @@
FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET)
#define FFA_FEATURES_MEM_RETRIEVE_REQ_NS_SUPPORT (UINT32_C(1) << 1)
+#define FFA_PARTITION_INFO_GET_REGS_SMC64 \
+ FFA_FID(SMC_64, FFA_FNUM_PARTITION_INFO_GET_REGS)
/* Implementation defined SMC64 FIDs */
#define FFA_CONSOLE_LOG_SMC64 FFA_FID(SMC_64, FFA_FNUM_CONSOLE_LOG)
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index 7f47dc7..c1b3698 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -145,4 +145,7 @@
bool enable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest);
bool disable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest);
+bool ffa_partition_info_regs_helper(const struct ffa_uuid uuid,
+ const struct ffa_partition_info *expected,
+ const uint16_t expected_size);
#endif /* SPM_COMMON_H */
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index f08f5f3..614770e 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -13,7 +13,6 @@
#include <sp_helpers.h>
#include <spm_helpers.h>
#include <spm_common.h>
-
#include <lib/libc/string.h>
/* FFA version test helpers */
@@ -23,7 +22,7 @@
static uint32_t spm_version;
static const struct ffa_uuid sp_uuids[] = {
- {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}, {IVY_UUID}
+ {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID}, {IVY_UUID}, {EL3_SPMD_LP_UUID}
};
static const struct ffa_partition_info ffa_expected_partition_info[] = {
@@ -65,7 +64,15 @@
FFA_PARTITION_DIRECT_REQ_RECV |
FFA_PARTITION_DIRECT_REQ_SEND),
.uuid = sp_uuids[3]
- }
+ },
+ /* EL3 SPMD logical partition */
+ {
+ .id = SP_ID(0x7FC0),
+ .exec_context = EL3_SPMD_LP_EXEC_CTX_COUNT,
+ .properties = (FFA_PARTITION_AARCH64_EXEC |
+ FFA_PARTITION_DIRECT_REQ_SEND),
+ .uuid = sp_uuids[4]
+ },
};
/*
@@ -121,6 +128,62 @@
expect(ffa_error_code(ret), FFA_ERROR_INVALID_PARAMETER);
}
+static void ffa_partition_info_get_regs_test(void)
+{
+ struct ffa_value ret = { 0 };
+
+ VERBOSE("FF-A Partition Info regs interface tests\n");
+ ret = ffa_version(MAKE_FFA_VERSION(1, 1));
+ uint32_t version = ret.fid;
+
+ if (version == FFA_ERROR_NOT_SUPPORTED) {
+ ERROR("FFA_VERSION 1.1 not supported, skipping"
+ " FFA_PARTITION_INFO_GET_REGS test.\n");
+ return;
+ }
+
+ ret = ffa_features(FFA_PARTITION_INFO_GET_REGS_SMC64);
+ if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
+ ERROR("FFA_PARTITION_INFO_GET_REGS not supported skipping tests.\n");
+ return;
+ }
+
+ expect(ffa_partition_info_regs_helper(sp_uuids[3],
+ &ffa_expected_partition_info[3], 1), true);
+ expect(ffa_partition_info_regs_helper(sp_uuids[2],
+ &ffa_expected_partition_info[2], 1), true);
+ expect(ffa_partition_info_regs_helper(sp_uuids[1],
+ &ffa_expected_partition_info[1], 1), true);
+ expect(ffa_partition_info_regs_helper(sp_uuids[0],
+ &ffa_expected_partition_info[0], 1), true);
+
+ /*
+ * Check partition information if there is support for SPMD EL3
+ * partitions. calling partition_info_get_regs with the SPMD EL3
+ * UUID successfully, indicates the presence of it (there is no
+ * spec defined way to discover presence of el3 spmd logical
+ * partitions). If the call fails with a not supported error,
+ * we assume they dont exist and skip further tests to avoid
+ * failures on platforms without el3 spmd logical partitions.
+ */
+ ret = ffa_partition_info_get_regs(sp_uuids[4], 0, 0);
+ if ((ffa_func_id(ret) == FFA_ERROR) &&
+ ((ffa_error_code(ret) == FFA_ERROR_NOT_SUPPORTED) ||
+ (ffa_error_code(ret) == FFA_ERROR_INVALID_PARAMETER))) {
+ INFO("Skipping register based EL3 SPMD Logical partition"
+ " discovery\n");
+ expect(ffa_partition_info_regs_helper(NULL_UUID,
+ ffa_expected_partition_info,
+ (ARRAY_SIZE(ffa_expected_partition_info) - 1)), true);
+ } else {
+ expect(ffa_partition_info_regs_helper(sp_uuids[4],
+ &ffa_expected_partition_info[4], 1), true);
+ expect(ffa_partition_info_regs_helper(NULL_UUID,
+ ffa_expected_partition_info,
+ ARRAY_SIZE(ffa_expected_partition_info)), true);
+ }
+}
+
static void ffa_partition_info_get_test(struct mailbox_buffers *mb)
{
INFO("Test FFA_PARTITION_INFO_GET.\n");
@@ -134,9 +197,16 @@
expect(ffa_partition_info_helper(mb, sp_uuids[0],
&ffa_expected_partition_info[0], 1), true);
+ /*
+ * TODO: ffa_partition_info_get_regs returns EL3 SPMD LP information
+ * but partition_info_get does not. Ignore the last entry, that is
+ * assumed to be the EL3 SPMD LP information. ffa_partition_info_get
+ * uses the rx/tx buffer and the SPMD does not support the use of
+ * rx/tx buffer to return SPMD logical partition information.
+ */
expect(ffa_partition_info_helper(mb, NULL_UUID,
ffa_expected_partition_info,
- ARRAY_SIZE(ffa_expected_partition_info)), true);
+ (ARRAY_SIZE(ffa_expected_partition_info) - 1)), true);
ffa_partition_info_wrong_test();
}
@@ -192,6 +262,7 @@
ffa_version_test();
ffa_spm_id_get_test();
ffa_partition_info_get_test(mb);
+ ffa_partition_info_get_regs_test();
announce_test_section_end(test_ffa);
}
diff --git a/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S b/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S
index 0e35a38..b9c9cd9 100644
--- a/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S
+++ b/tftf/tests/runtime_services/secure_service/aarch64/ffa_arch_helpers.S
@@ -8,14 +8,24 @@
.macro service_call _conduit
/*
- * Save the address of the ffa_value structure on the stack.
- *
- * Although x0 contains an 8-byte value, we are allocating 16 bytes
+ * Use a callee saved register to point to ffa_value structure after
+ * returning from the conduit.
+ * Although x19 contains an 8-byte value, we are allocating 16 bytes
* on the stack to respect the 16-byte stack-alignment.
*/
- str x0, [sp, #-16]!
+ str x19, [sp, #-16]!
+ /*
+ * Save pointed to ffa_value structure into x19, which is a callee saved
+ * register.
+ */
+ mov x19, x0
/* Load the argument values into the appropriate registers. */
+ ldp x16, x17, [x0, #128]
+ ldp x14, x15, [x0, #112]
+ ldp x12, x13, [x0, #96]
+ ldp x10, x11, [x0, #80]
+ ldp x8, x9, [x0, #64]
ldp x6, x7, [x0, #48]
ldp x4, x5, [x0, #32]
ldp x2, x3, [x0, #16]
@@ -24,20 +34,19 @@
\_conduit #0
/*
- * Pop the ffa_value structure address from the stack into a
- * caller-saved register.
+ * The return values are stored in x0-x17, put them in the ffa_value
+ * return structure. x19 points to the ffa_value structure.
*/
- ldr x9, [sp], #16
-
- /*
- * The return values are stored in x0-x7, put them in the ffa_value
- * return structure.
- */
- stp x0, x1, [x9, #0]
- stp x2, x3, [x9, #16]
- stp x4, x5, [x9, #32]
- stp x6, x7, [x9, #48]
-
+ stp x0, x1, [x19, #0]
+ stp x2, x3, [x19, #16]
+ stp x4, x5, [x19, #32]
+ stp x6, x7, [x19, #48]
+ stp x8, x9, [x19, #64]
+ stp x10, x11, [x19, #80]
+ stp x12, x13, [x19, #96]
+ stp x14, x15, [x19, #112]
+ stp x16, x17, [x19, #128]
+ ldr x19, [sp], #16
.endm
.globl ffa_svc
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index 55221da..9547c07 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -382,6 +382,25 @@
return ffa_service_call(&args);
}
+/* Get information about VMs or SPs based on UUID, using registers. */
+struct ffa_value ffa_partition_info_get_regs(const struct ffa_uuid uuid,
+ const uint16_t start_index,
+ const uint16_t tag)
+{
+ uint64_t arg1 = (uint64_t)uuid.uuid[1] << 32 | uuid.uuid[0];
+ uint64_t arg2 = (uint64_t)uuid.uuid[3] << 32 | uuid.uuid[2];
+ uint64_t arg3 = start_index | (uint64_t)tag << 16;
+
+ struct ffa_value args = {
+ .fid = FFA_PARTITION_INFO_GET_REGS_SMC64,
+ .arg1 = arg1,
+ .arg2 = arg2,
+ .arg3 = arg3,
+ };
+
+ return ffa_service_call(&args);
+}
+
/* Get information about VMs or SPs based on UUID */
struct ffa_value ffa_partition_info_get(const struct ffa_uuid uuid)
{
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 4d08bd0..43357a2 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -390,6 +390,149 @@
(uuid2.uuid[3] == uuid2.uuid[3]);
}
+static bool ffa_partition_info_regs_get_part_info(
+ struct ffa_value *args, uint8_t idx,
+ struct ffa_partition_info *partition_info)
+{
+ /*
+ * The list of pointers to args in return value: arg0/func encodes ff-a
+ * function, arg1 is reserved, arg2 encodes indices. arg3 and greater
+ * values reflect partition properties.
+ */
+ uint64_t *arg_ptrs = (uint64_t *)args + ((idx * 3) + 3);
+ uint64_t info, uuid_lo, uuid_high;
+
+ /*
+ * Each partition information is encoded in 3 registers, so there can be
+ * a maximum of 5 entries.
+ */
+ if (idx >= 5 || !partition_info) {
+ return false;
+ }
+
+ info = *arg_ptrs;
+
+ arg_ptrs++;
+ uuid_lo = *arg_ptrs;
+
+ arg_ptrs++;
+ uuid_high = *arg_ptrs;
+
+ /*
+ * As defined in FF-A 1.2 ALP0, 14.9 FFA_PARTITION_INFO_GET_REGS.
+ */
+ partition_info->id = info & 0xFFFFU;
+ partition_info->exec_context = (info >> 16) & 0xFFFFU;
+ partition_info->properties = (info >> 32);
+ partition_info->uuid.uuid[0] = uuid_lo & 0xFFFFFFFFU;
+ partition_info->uuid.uuid[1] = (uuid_lo >> 32) & 0xFFFFFFFFU;
+ partition_info->uuid.uuid[2] = uuid_high & 0xFFFFFFFFU;
+ partition_info->uuid.uuid[3] = (uuid_high >> 32) & 0xFFFFFFFFU;
+
+ return true;
+}
+
+static bool ffa_compare_partition_info(
+ const struct ffa_uuid uuid,
+ const struct ffa_partition_info *info,
+ const struct ffa_partition_info *expected)
+{
+ bool result = true;
+ /*
+ * If a UUID is specified then the UUID returned in the
+ * partition info descriptor MBZ.
+ */
+ struct ffa_uuid expected_uuid =
+ ffa_uuid_equal(uuid, NULL_UUID) ? expected->uuid : NULL_UUID;
+
+ if (info->id != expected->id) {
+ ERROR("Wrong ID. Expected %x, got %x\n", expected->id, info->id);
+ result = false;
+ }
+
+ if (info->exec_context != expected->exec_context) {
+ ERROR("Wrong context. Expected %d, got %d\n",
+ expected->exec_context,
+ info->exec_context);
+ result = false;
+ }
+ if (info->properties != expected->properties) {
+ ERROR("Wrong properties. Expected %d, got %d\n",
+ expected->properties,
+ info->properties);
+ result = false;
+ }
+
+ if (!ffa_uuid_equal(info->uuid, expected_uuid)) {
+ ERROR("Wrong UUID. Expected %x %x %x %x, "
+ "got %x %x %x %x\n",
+ expected_uuid.uuid[0],
+ expected_uuid.uuid[1],
+ expected_uuid.uuid[2],
+ expected_uuid.uuid[3],
+ info->uuid.uuid[0],
+ info->uuid.uuid[1],
+ info->uuid.uuid[2],
+ info->uuid.uuid[3]);
+ result = false;
+ }
+
+ return result;
+}
+
+/**
+ * Sends a ffa_partition_info_get_regs request and returns the information
+ * returned in registers in the output parameters. Validation against
+ * expected results shall be done by the caller outside the function.
+ */
+bool ffa_partition_info_regs_helper(const struct ffa_uuid uuid,
+ const struct ffa_partition_info *expected,
+ const uint16_t expected_size)
+{
+ /*
+ * TODO: For now, support only one invocation. Can be enhanced easily
+ * to extend to arbitrary number of partitions.
+ */
+ if (expected_size > 5) {
+ ERROR("%s only supports information received in"
+ " one invocation of the ABI (5 partitions)\n",
+ __func__);
+ return false;
+ }
+
+ struct ffa_value ret = ffa_partition_info_get_regs(uuid, 0, 0);
+
+ if (ffa_func_id(ret) != FFA_SUCCESS_SMC64) {
+ return false;
+ }
+
+ if (ffa_partition_info_regs_partition_count(ret) !=
+ expected_size) {
+ ERROR("Unexpected number of partitions %d (expected %d)\n",
+ ffa_partition_info_regs_partition_count(ret),
+ expected_size);
+ return false;
+ }
+
+ if (ffa_partition_info_regs_entry_size(ret) !=
+ sizeof(struct ffa_partition_info)) {
+ ERROR("Unexpected partition info descriptor size %d\n",
+ ffa_partition_info_regs_entry_size(ret));
+ return false;
+ }
+
+ for (unsigned int i = 0U; i < expected_size; i++) {
+ struct ffa_partition_info info = { 0 };
+
+ ffa_partition_info_regs_get_part_info(&ret, i, &info);
+ if (!ffa_compare_partition_info(uuid, &info, &expected[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
/**
* Sends a ffa_partition_info request and checks the response against the
* target.
@@ -418,47 +561,8 @@
(const struct ffa_partition_info *)(mb->recv);
for (unsigned int i = 0U; i < expected_size; i++) {
- /*
- * If a UUID is specified then the UUID returned in the
- * partition info descriptor MBZ.
- */
- struct ffa_uuid expected_uuid =
- ffa_uuid_equal(uuid, NULL_UUID) ?
- expected[i].uuid :
- NULL_UUID;
-
- if (info[i].id != expected[i].id) {
- ERROR("Wrong ID. Expected %x, got %x\n",
- expected[i].id,
- info[i].id);
+ if (!ffa_compare_partition_info(uuid, &info[i], &expected[i]))
result = false;
- }
- if (info[i].exec_context != expected[i].exec_context) {
- ERROR("Wrong context. Expected %d, got %d\n",
- expected[i].exec_context,
- info[i].exec_context);
- result = false;
- }
- if (info[i].properties != expected[i].properties) {
- ERROR("Wrong properties. Expected %d, got %d\n",
- expected[i].properties,
- info[i].properties);
- result = false;
- }
-
- if (!ffa_uuid_equal(info[i].uuid, expected_uuid)) {
- ERROR("Wrong UUID. Expected %x %x %x %x, "
- "got %x %x %x %x\n",
- expected_uuid.uuid[0],
- expected_uuid.uuid[1],
- expected_uuid.uuid[2],
- expected_uuid.uuid[3],
- info[i].uuid.uuid[0],
- info[i].uuid.uuid[1],
- info[i].uuid.uuid[2],
- info[i].uuid.uuid[3]);
- result = false;
- }
}
}