diff options
author | Jelle Sels <jelle.sels@arm.com> | 2021-01-29 09:18:58 +0100 |
---|---|---|
committer | György Szing <gyorgy.szing@arm.com> | 2021-04-14 20:11:53 +0200 |
commit | 1ba62d4f955846f42720b8089a4dd4e7c422ef12 (patch) | |
tree | 6eb9f1b76211bf188b520be48a43b027c6c2692d | |
parent | 6dbe9a5a2478550dbebc59f41c60991d2cadb35a (diff) | |
download | optee_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.c | 88 |
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, ®ion_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, ¶m); + + 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; |