1*d6e29083SAmirreza Zarrabi // SPDX-License-Identifier: GPL-2.0-only 2*d6e29083SAmirreza Zarrabi /* 3*d6e29083SAmirreza Zarrabi * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4*d6e29083SAmirreza Zarrabi */ 5*d6e29083SAmirreza Zarrabi 6*d6e29083SAmirreza Zarrabi #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7*d6e29083SAmirreza Zarrabi 8*d6e29083SAmirreza Zarrabi #include <linux/firmware/qcom/qcom_tzmem.h> 9*d6e29083SAmirreza Zarrabi #include <linux/mm.h> 10*d6e29083SAmirreza Zarrabi 11*d6e29083SAmirreza Zarrabi #include "qcomtee.h" 12*d6e29083SAmirreza Zarrabi 13*d6e29083SAmirreza Zarrabi /** 14*d6e29083SAmirreza Zarrabi * define MAX_OUTBOUND_BUFFER_SIZE - Maximum size of outbound buffers. 15*d6e29083SAmirreza Zarrabi * 16*d6e29083SAmirreza Zarrabi * The size of outbound buffer depends on QTEE callback requests. 17*d6e29083SAmirreza Zarrabi */ 18*d6e29083SAmirreza Zarrabi #define MAX_OUTBOUND_BUFFER_SIZE SZ_4K 19*d6e29083SAmirreza Zarrabi 20*d6e29083SAmirreza Zarrabi /** 21*d6e29083SAmirreza Zarrabi * define MAX_INBOUND_BUFFER_SIZE - Maximum size of the inbound buffer. 22*d6e29083SAmirreza Zarrabi * 23*d6e29083SAmirreza Zarrabi * The size of the inbound buffer depends on the user's requests, 24*d6e29083SAmirreza Zarrabi * specifically the number of IB and OB arguments. If an invocation 25*d6e29083SAmirreza Zarrabi * requires a size larger than %MAX_INBOUND_BUFFER_SIZE, the user should 26*d6e29083SAmirreza Zarrabi * consider using another form of shared memory with QTEE. 27*d6e29083SAmirreza Zarrabi */ 28*d6e29083SAmirreza Zarrabi #define MAX_INBOUND_BUFFER_SIZE SZ_4M 29*d6e29083SAmirreza Zarrabi 30*d6e29083SAmirreza Zarrabi /** 31*d6e29083SAmirreza Zarrabi * qcomtee_msg_buffers_alloc() - Allocate inbound and outbound buffers. 32*d6e29083SAmirreza Zarrabi * @oic: context to use for the current invocation. 33*d6e29083SAmirreza Zarrabi * @u: array of arguments for the current invocation. 34*d6e29083SAmirreza Zarrabi * 35*d6e29083SAmirreza Zarrabi * It calculates the size of inbound and outbound buffers based on the 36*d6e29083SAmirreza Zarrabi * arguments in @u. It allocates the buffers from the teedev pool. 37*d6e29083SAmirreza Zarrabi * 38*d6e29083SAmirreza Zarrabi * Return: On success, returns 0. On error, returns < 0. 39*d6e29083SAmirreza Zarrabi */ 40*d6e29083SAmirreza Zarrabi int qcomtee_msg_buffers_alloc(struct qcomtee_object_invoke_ctx *oic, 41*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u) 42*d6e29083SAmirreza Zarrabi { 43*d6e29083SAmirreza Zarrabi struct tee_context *ctx = oic->ctx; 44*d6e29083SAmirreza Zarrabi struct tee_shm *shm; 45*d6e29083SAmirreza Zarrabi size_t size; 46*d6e29083SAmirreza Zarrabi int i; 47*d6e29083SAmirreza Zarrabi 48*d6e29083SAmirreza Zarrabi /* Start offset in a message for buffer arguments. */ 49*d6e29083SAmirreza Zarrabi size = qcomtee_msg_buffer_args(struct qcomtee_msg_object_invoke, 50*d6e29083SAmirreza Zarrabi qcomtee_args_len(u)); 51*d6e29083SAmirreza Zarrabi if (size > MAX_INBOUND_BUFFER_SIZE) 52*d6e29083SAmirreza Zarrabi return -EINVAL; 53*d6e29083SAmirreza Zarrabi 54*d6e29083SAmirreza Zarrabi /* Add size of IB arguments. */ 55*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_buffer(i, u) { 56*d6e29083SAmirreza Zarrabi size = size_add(size, qcomtee_msg_offset_align(u[i].b.size)); 57*d6e29083SAmirreza Zarrabi if (size > MAX_INBOUND_BUFFER_SIZE) 58*d6e29083SAmirreza Zarrabi return -EINVAL; 59*d6e29083SAmirreza Zarrabi } 60*d6e29083SAmirreza Zarrabi 61*d6e29083SAmirreza Zarrabi /* Add size of OB arguments. */ 62*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_buffer(i, u) { 63*d6e29083SAmirreza Zarrabi size = size_add(size, qcomtee_msg_offset_align(u[i].b.size)); 64*d6e29083SAmirreza Zarrabi if (size > MAX_INBOUND_BUFFER_SIZE) 65*d6e29083SAmirreza Zarrabi return -EINVAL; 66*d6e29083SAmirreza Zarrabi } 67*d6e29083SAmirreza Zarrabi 68*d6e29083SAmirreza Zarrabi shm = tee_shm_alloc_priv_buf(ctx, size); 69*d6e29083SAmirreza Zarrabi if (IS_ERR(shm)) 70*d6e29083SAmirreza Zarrabi return PTR_ERR(shm); 71*d6e29083SAmirreza Zarrabi 72*d6e29083SAmirreza Zarrabi /* Allocate inbound buffer. */ 73*d6e29083SAmirreza Zarrabi oic->in_shm = shm; 74*d6e29083SAmirreza Zarrabi shm = tee_shm_alloc_priv_buf(ctx, MAX_OUTBOUND_BUFFER_SIZE); 75*d6e29083SAmirreza Zarrabi if (IS_ERR(shm)) { 76*d6e29083SAmirreza Zarrabi tee_shm_free(oic->in_shm); 77*d6e29083SAmirreza Zarrabi 78*d6e29083SAmirreza Zarrabi return PTR_ERR(shm); 79*d6e29083SAmirreza Zarrabi } 80*d6e29083SAmirreza Zarrabi /* Allocate outbound buffer. */ 81*d6e29083SAmirreza Zarrabi oic->out_shm = shm; 82*d6e29083SAmirreza Zarrabi 83*d6e29083SAmirreza Zarrabi oic->in_msg.addr = tee_shm_get_va(oic->in_shm, 0); 84*d6e29083SAmirreza Zarrabi oic->in_msg.size = tee_shm_get_size(oic->in_shm); 85*d6e29083SAmirreza Zarrabi oic->out_msg.addr = tee_shm_get_va(oic->out_shm, 0); 86*d6e29083SAmirreza Zarrabi oic->out_msg.size = tee_shm_get_size(oic->out_shm); 87*d6e29083SAmirreza Zarrabi /* QTEE assume unused buffers are zeroed. */ 88*d6e29083SAmirreza Zarrabi memzero_explicit(oic->in_msg.addr, oic->in_msg.size); 89*d6e29083SAmirreza Zarrabi memzero_explicit(oic->out_msg.addr, oic->out_msg.size); 90*d6e29083SAmirreza Zarrabi 91*d6e29083SAmirreza Zarrabi return 0; 92*d6e29083SAmirreza Zarrabi } 93*d6e29083SAmirreza Zarrabi 94*d6e29083SAmirreza Zarrabi void qcomtee_msg_buffers_free(struct qcomtee_object_invoke_ctx *oic) 95*d6e29083SAmirreza Zarrabi { 96*d6e29083SAmirreza Zarrabi tee_shm_free(oic->in_shm); 97*d6e29083SAmirreza Zarrabi tee_shm_free(oic->out_shm); 98*d6e29083SAmirreza Zarrabi } 99*d6e29083SAmirreza Zarrabi 100*d6e29083SAmirreza Zarrabi /* Dynamic shared memory pool based on tee_dyn_shm_alloc_helper(). */ 101*d6e29083SAmirreza Zarrabi 102*d6e29083SAmirreza Zarrabi static int qcomtee_shm_register(struct tee_context *ctx, struct tee_shm *shm, 103*d6e29083SAmirreza Zarrabi struct page **pages, size_t num_pages, 104*d6e29083SAmirreza Zarrabi unsigned long start) 105*d6e29083SAmirreza Zarrabi { 106*d6e29083SAmirreza Zarrabi return qcom_tzmem_shm_bridge_create(shm->paddr, shm->size, 107*d6e29083SAmirreza Zarrabi &shm->sec_world_id); 108*d6e29083SAmirreza Zarrabi } 109*d6e29083SAmirreza Zarrabi 110*d6e29083SAmirreza Zarrabi static int qcomtee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) 111*d6e29083SAmirreza Zarrabi { 112*d6e29083SAmirreza Zarrabi qcom_tzmem_shm_bridge_delete(shm->sec_world_id); 113*d6e29083SAmirreza Zarrabi 114*d6e29083SAmirreza Zarrabi return 0; 115*d6e29083SAmirreza Zarrabi } 116*d6e29083SAmirreza Zarrabi 117*d6e29083SAmirreza Zarrabi static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm, 118*d6e29083SAmirreza Zarrabi size_t size, size_t align) 119*d6e29083SAmirreza Zarrabi { 120*d6e29083SAmirreza Zarrabi return tee_dyn_shm_alloc_helper(shm, size, align, qcomtee_shm_register); 121*d6e29083SAmirreza Zarrabi } 122*d6e29083SAmirreza Zarrabi 123*d6e29083SAmirreza Zarrabi static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm) 124*d6e29083SAmirreza Zarrabi { 125*d6e29083SAmirreza Zarrabi tee_dyn_shm_free_helper(shm, qcomtee_shm_unregister); 126*d6e29083SAmirreza Zarrabi } 127*d6e29083SAmirreza Zarrabi 128*d6e29083SAmirreza Zarrabi static void pool_op_destroy_pool(struct tee_shm_pool *pool) 129*d6e29083SAmirreza Zarrabi { 130*d6e29083SAmirreza Zarrabi kfree(pool); 131*d6e29083SAmirreza Zarrabi } 132*d6e29083SAmirreza Zarrabi 133*d6e29083SAmirreza Zarrabi static const struct tee_shm_pool_ops pool_ops = { 134*d6e29083SAmirreza Zarrabi .alloc = pool_op_alloc, 135*d6e29083SAmirreza Zarrabi .free = pool_op_free, 136*d6e29083SAmirreza Zarrabi .destroy_pool = pool_op_destroy_pool, 137*d6e29083SAmirreza Zarrabi }; 138*d6e29083SAmirreza Zarrabi 139*d6e29083SAmirreza Zarrabi struct tee_shm_pool *qcomtee_shm_pool_alloc(void) 140*d6e29083SAmirreza Zarrabi { 141*d6e29083SAmirreza Zarrabi struct tee_shm_pool *pool; 142*d6e29083SAmirreza Zarrabi 143*d6e29083SAmirreza Zarrabi pool = kzalloc(sizeof(*pool), GFP_KERNEL); 144*d6e29083SAmirreza Zarrabi if (!pool) 145*d6e29083SAmirreza Zarrabi return ERR_PTR(-ENOMEM); 146*d6e29083SAmirreza Zarrabi 147*d6e29083SAmirreza Zarrabi pool->ops = &pool_ops; 148*d6e29083SAmirreza Zarrabi 149*d6e29083SAmirreza Zarrabi return pool; 150*d6e29083SAmirreza Zarrabi } 151