static TEE_Result gprof_send_rpc(TEE_UUID *uuid, void *buf, size_t len, uint32_t *id) { struct mobj *mobj; TEE_Result res = TEE_ERROR_GENERIC; char *va; mobj = thread_rpc_alloc_payload(sizeof(*uuid) + len); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; va = mobj_get_va(mobj, 0); if (!va) goto exit; memcpy(va, uuid, sizeof(*uuid)); memcpy(va + sizeof(*uuid), buf, len); struct thread_param params[3] = { [0] = THREAD_PARAM_VALUE(INOUT, *id, 0, 0), [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, sizeof(*uuid)), [2] = THREAD_PARAM_MEMREF(IN, mobj, sizeof(*uuid), len), }; res = thread_rpc_cmd(OPTEE_RPC_CMD_GPROF, 3, params); if (res != TEE_SUCCESS) goto exit; *id = (uint32_t)params[0].u.value.a; exit: thread_rpc_free_payload(mobj); return res; }
void *tee_fs_rpc_cache_alloc(size_t size, struct mobj **mobj, uint64_t *cookie) { struct thread_specific_data *tsd = thread_get_tsd(); size_t sz = size; uint64_t c = 0; paddr_t p; void *va; if (!size) return NULL; /* * Always allocate in page chunks as normal world allocates payload * memory as complete pages. */ sz = ROUNDUP(size, SMALL_PAGE_SIZE); if (sz > tsd->rpc_fs_payload_size) { tee_fs_rpc_cache_clear(tsd); *mobj = thread_rpc_alloc_payload(sz, &c); if (!*mobj) return NULL; if (mobj_get_pa(*mobj, 0, 0, &p)) goto err; if (!ALIGNMENT_IS_OK(p, uint64_t)) goto err; va = mobj_get_va(*mobj, 0); if (!va) goto err; tsd->rpc_fs_payload = va; tsd->rpc_fs_payload_mobj = *mobj; tsd->rpc_fs_payload_cookie = c; tsd->rpc_fs_payload_size = sz; } else *mobj = tsd->rpc_fs_payload_mobj; *cookie = tsd->rpc_fs_payload_cookie; return tsd->rpc_fs_payload; err: thread_rpc_free_payload(c, *mobj); return NULL; }
/* * Load a TA via RPC with UUID defined by input param @uuid. The virtual * address of the raw TA binary is received in out parameter @ta. */ static TEE_Result rpc_load(const TEE_UUID *uuid, struct shdr **ta, size_t *ta_size, struct mobj **mobj) { TEE_Result res; struct thread_param params[2]; if (!uuid || !ta || !mobj || !ta_size) return TEE_ERROR_BAD_PARAMETERS; memset(params, 0, sizeof(params)); params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); if (res != TEE_SUCCESS) return res; *mobj = thread_rpc_alloc_payload(params[1].u.memref.size); if (!*mobj) return TEE_ERROR_OUT_OF_MEMORY; if ((*mobj)->size < params[1].u.memref.size) { res = TEE_ERROR_SHORT_BUFFER; goto exit; } *ta = mobj_get_va(*mobj, 0); /* We don't expect NULL as thread_rpc_alloc_payload() was successful */ assert(*ta); *ta_size = params[1].u.memref.size; params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; params[1].u.memref.offs = 0; params[1].u.memref.mobj = *mobj; res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); exit: if (res != TEE_SUCCESS) thread_rpc_free_payload(*mobj); return res; }
static TEE_Result alloc_benchmark_buffer(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { TEE_Result res; if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_INOUT) || (TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_VALUE_INPUT) || (TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) || (TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) { return TEE_ERROR_BAD_PARAMETERS; } mutex_lock(&bench_reg_mu); /* Check if we have already registered buffer */ if (bench_ts_global) { EMSG(TA_PRINT_PREFIX "timestamp buffer was already registered"); mutex_unlock(&bench_reg_mu); return TEE_ERROR_BAD_STATE; } bench_ts_size = sizeof(struct tee_ts_global) + p[1].value.a * sizeof(struct tee_ts_cpu_buf); if (!bench_ts_size) { EMSG(TA_PRINT_PREFIX "invalid timestamp buffer size"); mutex_unlock(&bench_reg_mu); return TEE_ERROR_BAD_STATE; } bench_mobj = thread_rpc_alloc_global_payload(bench_ts_size); if (!bench_mobj) { EMSG(TA_PRINT_PREFIX "can't create mobj for timestamp buffer"); mutex_unlock(&bench_reg_mu); return TEE_ERROR_OUT_OF_MEMORY; } bench_ts_global = (struct tee_ts_global *)mobj_get_va(bench_mobj, 0); if (!bench_ts_global) { thread_rpc_free_global_payload(bench_mobj); bench_mobj = NULL; mutex_unlock(&bench_reg_mu); return TEE_ERROR_BAD_STATE; } memset((void *)bench_ts_global, 0, bench_ts_size); bench_ts_global->cores = p[1].value.a; DMSG(TA_PRINT_PREFIX "allocated timestamp buffer, addr = %p", (void *)bench_ts_global); mutex_unlock(&bench_reg_mu); /* Send back to the optee linux kernel module */ res = rpc_reg_global_buf(OPTEE_MSG_RPC_CMD_BENCH_REG_NEW, virt_to_phys((void *)bench_ts_global), bench_ts_size); p[0].value.a = virt_to_phys((void *)bench_ts_global); p[0].value.b = bench_ts_size; return res; }