aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelle Sels <jelle.sels@arm.com>2021-01-29 09:18:58 +0100
committerGyörgy Szing <gyorgy.szing@arm.com>2021-04-14 20:11:53 +0200
commit1ba62d4f955846f42720b8089a4dd4e7c422ef12 (patch)
tree6eb9f1b76211bf188b520be48a43b027c6c2692d
parent6dbe9a5a2478550dbebc59f41c60991d2cadb35a (diff)
downloadoptee_os-1ba62d4f955846f42720b8089a4dd4e7c422ef12.tar.gz
SPMC: Pass device regions to SP
Pass the device regions info to the SPs as part of the ffa_init_info struct. ffa_init_info is moved from the stack to a dedicated page. This to not fill the stack to much and also to give us the opportunity to remove the page later. The region addresses can be found in a SP with the following sample code: void __noreturn sp_main(struct ffa_init_info *init_info) { struct device_region * d = NULL; d = (struct device_region*) init_info->nvp[0].value; DMSG("device region 0 va=%p name=%s", d[0].location, d[0].name); Check-patch gives warnings one the error messages. They are kept explicit long. https://www.kernel.org/doc/html/v4.10/process/coding-style.html#breaking-long-lines-and-strings Signed-off-by: Jelle Sels <jelle.sels@arm.com> Change-Id: If6a6314e9ffa152b27b960701f6607d7e1ceba96
-rw-r--r--core/arch/arm/kernel/sp.c88
1 files changed, 66 insertions, 22 deletions
diff --git a/core/arch/arm/kernel/sp.c b/core/arch/arm/kernel/sp.c
index c31379a8f..a325f37c5 100644
--- a/core/arch/arm/kernel/sp.c
+++ b/core/arch/arm/kernel/sp.c
@@ -37,17 +37,25 @@
#define MEM_NS_ACCESS BIT(3)
struct name_value_pair {
- uint32_t name[4];
- uintptr_t value;
- size_t size;
+ uint8_t name[16];
+ uint64_t value;
+ uint64_t size;
};
struct ffa_init_info {
- uint32_t magic; /* FF -A */
+ char magic[4];/* FF -A */
uint32_t count; /* Count of name value size pairs */
struct name_value_pair nvp[]; /* Array of name value size pairs */
};
+struct device_region {
+ char name[16];
+ uintptr_t location;
+ size_t size;
+ };
+
+#define DEV_REGION 0
+
const struct tee_ta_ops *_sp_ops;
static TEE_Result sp_init_set_registers(struct sp_session *sp_s);
static TEE_Result __attribute__((unused)) sp_init_uuid(const TEE_UUID *uuid);
@@ -57,11 +65,11 @@ static struct sp_sessions_head tee_open_sp_sessions =
TAILQ_HEAD_INITIALIZER(tee_open_sp_sessions);
const struct ffa_init_info secure_partition_info = {
- .magic = 0xaaaaa,
+ .magic = {'F', 'F', '-', 'A'},
.count = 1,
.nvp = {{
- .name = {'a', 'b', 'c', '\0'},
- .value = 0x555,
+ .name = "DEVICE_REGIONS",
+ .value = 0,
.size = 0
} }
@@ -189,6 +197,9 @@ static TEE_Result sp_map_device_regions(struct sp_session *s, const void *fdt,
{
int sp_node = 0;
int dev_regions_offs = 0;
+ struct thread_ctx_regs *sp_regs = &s->sp_regs;
+ struct ffa_init_info *info = NULL;
+ struct device_region *d = NULL;
if (!fdt)
return TEE_ERROR_ITEM_NOT_FOUND;
@@ -198,21 +209,36 @@ static TEE_Result sp_map_device_regions(struct sp_session *s, const void *fdt,
/* No device regions in this DT */
return TEE_SUCCESS;
+ /*Add all memory regions*/
+ info = (struct ffa_init_info *)sp_regs->x[0];
+
+ /* Store the device regions as the first element after the nvp fields.*/
+ info->nvp[DEV_REGION].value = (uint64_t)&info->nvp[info->count];
+ d = (struct device_region *) &info->nvp[info->count];
+
fdt_for_each_subnode(sp_node, fdt, dev_regions_offs) {
vaddr_t va = 0;
uint64_t pa = 0;
uint32_t sz = 0;
uint32_t attributes = 0;
uint32_t prot = 0;
+ const char *region_name = NULL;
+ int region_name_len = 0;
- if (sp_dt_get_u64(fdt, sp_node, "base-address", &pa))
- return TEE_ERROR_ITEM_NOT_FOUND;
+ if (sp_dt_get_u64(fdt, sp_node, "base-address", &pa)) {
+ EMSG("NO DEVICE REGION base-address DEFINED, SKIPPING DEVICE REGION");
+ continue;
+ }
- if (sp_dt_get_u32(fdt, sp_node, "pages-count", &sz))
- return TEE_ERROR_ITEM_NOT_FOUND;
+ if (sp_dt_get_u32(fdt, sp_node, "pages-count", &sz)) {
+ EMSG("NO DEVICE REGION pages-count DEFINED, SKIPPING DEVICE REGION");
+ continue;
+ }
- if (sp_dt_get_u32(fdt, sp_node, "attributes", &attributes))
- return TEE_ERROR_ITEM_NOT_FOUND;
+ if (sp_dt_get_u32(fdt, sp_node, "attributes", &attributes)) {
+ EMSG("NO DEVICE REGION attributes DEFINED, SKIPPING DEVICE REGION");
+ continue;
+ }
/*Set read bit if enable*/
if (attributes & MEM_READ_ACCESS)
@@ -223,8 +249,10 @@ static TEE_Result sp_map_device_regions(struct sp_session *s, const void *fdt,
prot |= TEE_MATTR_UW;
/*Device memory should not be executable*/
- if (attributes & MEM_EXECUTABLE_ACCESS)
- return TEE_ERROR_BAD_PARAMETERS;
+ if (attributes & MEM_EXECUTABLE_ACCESS) {
+ EMSG("DEVICE REGION mapped with MEM_EXECUTABLE_ACCESS, SKIPPING DEVICE REGION");
+ continue;
+ }
/*Enable secure memory when NS memory bit is not set*/
if (!(attributes & MEM_NS_ACCESS))
@@ -233,7 +261,20 @@ static TEE_Result sp_map_device_regions(struct sp_session *s, const void *fdt,
prot |= (TEE_MATTR_CACHE_NONCACHE << TEE_MATTR_CACHE_SHIFT)
| TEE_MATTR_DEVICE;
+ region_name = fdt_get_name(fdt, sp_node, &region_name_len);
+ if (!region_name) {
+ EMSG("NO DEVICE REGION NAME DEFINED, SKIPPING DEVICE REGION");
+ continue;
+ }
+
+ memcpy(d->name, region_name,
+ MIN(region_name_len + 1, (int)sizeof(d->name)));
+ d->size = sz * SMALL_PAGE_SIZE;
+ info->nvp[DEV_REGION].size += sizeof(struct device_region);
+
map_region(s, pa, sz, prot, &va);
+ d->location = va;
+ d++;
}
return TEE_SUCCESS;
}
@@ -301,20 +342,20 @@ static TEE_Result sp_process_manifest(struct sp_session *s,
}
static void sp_init_info(struct sp_session *sp_s,
- const struct ffa_init_info *sp_info)
+ const struct ffa_init_info *sp_info __unused)
{
+ vaddr_t sp_init_va = 0;
struct ffa_init_info *info = NULL;
size_t pairs_size = (sp_info->count * sizeof(struct name_value_pair));
- size_t info_size = sizeof(*sp_info) + pairs_size;
struct user_ta_ctx *utc = to_user_ta_ctx(sp_s->s->ctx);
- /* Store the secure partition info on top of stack. */
- utc->stack_ptr -= ROUNDUP(info_size, STACK_ALIGNMENT);
+ alloc_and_map_ldelf_fobj(utc, SMALL_PAGE_SIZE,
+ TEE_MATTR_URW | TEE_MATTR_PRW, &sp_init_va);
- sp_s->sp_regs.x[0] = (uintptr_t)utc->stack_ptr;
- info = (struct ffa_init_info *)utc->stack_ptr;
+ sp_s->sp_regs.x[0] = (uintptr_t)sp_init_va;
+ info = (struct ffa_init_info *)sp_init_va;
- memcpy(info, sp_info, sizeof(*info));
+ memcpy(info, sp_info, sizeof(struct ffa_init_info));
memcpy((void *)info->nvp, sp_info->nvp, pairs_size);
}
@@ -338,7 +379,10 @@ static TEE_Result __attribute__((unused)) sp_init_uuid(const TEE_UUID *uuid)
&clnt_id,
cancel_req_to,
&param);
+
+ args.a0 = sp_get_session(sess->id)->sp_regs.x[0];
sp_thread(sess->id, FFA_NW_ID, &args);
+
thread_spmc_msg_recv(&args, sess->id);
return res;