TEE_Result tee_svc_copy_to_user(struct tee_ta_session *sess, void *uaddr, const void *kaddr, size_t len) { TEE_Result res; struct tee_ta_session *s; if (sess == NULL) { res = tee_ta_get_current_session(&s); if (res != TEE_SUCCESS) return res; } else { s = sess; tee_ta_set_current_session(s); } res = tee_mmu_check_access_rights(s->ctx, TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (tee_uaddr_t)uaddr, len); if (res != TEE_SUCCESS) return res; memcpy(uaddr, kaddr, len); return TEE_SUCCESS; }
/* * tee_uta_cache_operation - dynamic cache clean/inval request from a TA * It follows ARM recommendation: * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0246d/Beicdhde.html * Note that this implementation assumes dsb operations are part of * cache_maintenance_l1(), and L2 cache sync are part of * cache_maintenance_l2() */ static TEE_Result cache_operation(struct tee_ta_session *sess, enum utee_cache_operation op, void *va, size_t len) { TEE_Result ret; paddr_t pa = 0; struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); if ((sess->ctx->flags & TA_FLAG_CACHE_MAINTENANCE) == 0) return TEE_ERROR_NOT_SUPPORTED; /* * TAs are allowed to operate cache maintenance on TA memref parameters * only, not on the TA private memory. */ if (tee_mmu_is_vbuf_intersect_ta_private(utc, va, len)) return TEE_ERROR_ACCESS_DENIED; ret = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)va, len); if (ret != TEE_SUCCESS) return TEE_ERROR_ACCESS_DENIED; pa = virt_to_phys(va); if (!pa) return TEE_ERROR_ACCESS_DENIED; switch (op) { case TEE_CACHEFLUSH: /* Clean L1, Flush L2, Flush L1 */ ret = cache_maintenance_l1(DCACHE_AREA_CLEAN, va, len); if (ret != TEE_SUCCESS) return ret; ret = cache_maintenance_l2(L2CACHE_AREA_CLEAN_INV, pa, len); if (ret != TEE_SUCCESS) return ret; return cache_maintenance_l1(DCACHE_AREA_CLEAN_INV, va, len); case TEE_CACHECLEAN: /* Clean L1, Clean L2 */ ret = cache_maintenance_l1(DCACHE_AREA_CLEAN, va, len); if (ret != TEE_SUCCESS) return ret; return cache_maintenance_l2(L2CACHE_AREA_CLEAN, pa, len); case TEE_CACHEINVALIDATE: /* Inval L2, Inval L1 */ ret = cache_maintenance_l2(L2CACHE_AREA_INVALIDATE, pa, len); if (ret != TEE_SUCCESS) return ret; return cache_maintenance_l1(DCACHE_AREA_INVALIDATE, va, len); default: return TEE_ERROR_NOT_SUPPORTED; } }
TEE_Result tee_svc_check_access_rights(uint32_t flags, const void *buf, size_t len) { TEE_Result res; struct tee_ta_session *s; res = tee_ta_get_current_session(&s); if (res != TEE_SUCCESS) return res; return tee_mmu_check_access_rights(s->ctx, flags, (tee_uaddr_t)buf, len); }
/* * tee_uta_cache_operation - dynamic cache clean/inval request from a TA * It follows ARM recommendation: * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0246d/Beicdhde.html * Note that this implementation assumes dsb operations are part of * cache_maintenance_l1(), and L2 cache sync are part of * cache_maintenance_l2() */ static TEE_Result cache_operation(struct tee_ta_session *sess, enum utee_cache_operation op, void *va, size_t len) { TEE_Result ret; paddr_t pa = 0; struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); if ((sess->ctx->flags & TA_FLAG_CACHE_MAINTENANCE) == 0) return TEE_ERROR_NOT_SUPPORTED; ret = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_WRITE, (tee_uaddr_t)va, len); if (ret != TEE_SUCCESS) return TEE_ERROR_ACCESS_DENIED; pa = virt_to_phys(va); if (!pa) return TEE_ERROR_ACCESS_DENIED; switch (op) { case TEE_CACHEFLUSH: /* Clean L1, Flush L2, Flush L1 */ ret = cache_maintenance_l1(DCACHE_AREA_CLEAN, va, len); if (ret != TEE_SUCCESS) return ret; ret = cache_maintenance_l2(L2CACHE_AREA_CLEAN_INV, pa, len); if (ret != TEE_SUCCESS) return ret; return cache_maintenance_l1(DCACHE_AREA_CLEAN_INV, va, len); case TEE_CACHECLEAN: /* Clean L1, Clean L2 */ ret = cache_maintenance_l1(DCACHE_AREA_CLEAN, va, len); if (ret != TEE_SUCCESS) return ret; return cache_maintenance_l2(L2CACHE_AREA_CLEAN, pa, len); case TEE_CACHEINVALIDATE: /* Inval L2, Inval L1 */ ret = cache_maintenance_l2(L2CACHE_AREA_INVALIDATE, pa, len); if (ret != TEE_SUCCESS) return ret; return cache_maintenance_l1(DCACHE_AREA_INVALIDATE, va, len); default: return TEE_ERROR_NOT_SUPPORTED; } }
static TEE_Result gprof_start_pc_sampling(struct tee_ta_session *s, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct sample_buf *sbuf; uint32_t offset; uint32_t scale; TEE_Result res; uint32_t len; uaddr_t buf; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; buf = (uaddr_t)params[0].memref.buffer; len = params[0].memref.size; offset = params[1].value.a; scale = params[1].value.b; res = tee_mmu_check_access_rights(to_user_ta_ctx(s->ctx), TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, buf, len); if (res != TEE_SUCCESS) return res; sbuf = calloc(1, sizeof(*sbuf)); if (!sbuf) return TEE_ERROR_OUT_OF_MEMORY; sbuf->samples = (uint16_t *)buf; sbuf->nsamples = len / sizeof(*sbuf->samples); sbuf->offset = offset; sbuf->scale = scale; sbuf->freq = read_cntfrq(); sbuf->enabled = true; s->sbuf = sbuf; return TEE_SUCCESS; }