1*87ab676dSAmirreza Zarrabi // SPDX-License-Identifier: GPL-2.0-only 2*87ab676dSAmirreza Zarrabi /* 3*87ab676dSAmirreza Zarrabi * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4*87ab676dSAmirreza Zarrabi */ 5*87ab676dSAmirreza Zarrabi 6*87ab676dSAmirreza Zarrabi #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7*87ab676dSAmirreza Zarrabi 8*87ab676dSAmirreza Zarrabi #include <linux/firmware/qcom/qcom_scm.h> 9*87ab676dSAmirreza Zarrabi #include <linux/mm.h> 10*87ab676dSAmirreza Zarrabi 11*87ab676dSAmirreza Zarrabi #include "qcomtee.h" 12*87ab676dSAmirreza Zarrabi 13*87ab676dSAmirreza Zarrabi /** 14*87ab676dSAmirreza Zarrabi * DOC: Memory and Mapping Objects 15*87ab676dSAmirreza Zarrabi * 16*87ab676dSAmirreza Zarrabi * QTEE uses memory objects for memory sharing with Linux. 17*87ab676dSAmirreza Zarrabi * A memory object can be a standard dma_buf or a contiguous memory range, 18*87ab676dSAmirreza Zarrabi * e.g., tee_shm. A memory object should support one operation: map. When 19*87ab676dSAmirreza Zarrabi * invoked by QTEE, a mapping object is generated. A mapping object supports 20*87ab676dSAmirreza Zarrabi * one operation: unmap. 21*87ab676dSAmirreza Zarrabi * 22*87ab676dSAmirreza Zarrabi * (1) To map a memory object, QTEE invokes the primordial object with 23*87ab676dSAmirreza Zarrabi * %QCOMTEE_OBJECT_OP_MAP_REGION operation; see 24*87ab676dSAmirreza Zarrabi * qcomtee_primordial_obj_dispatch(). 25*87ab676dSAmirreza Zarrabi * (2) To unmap a memory object, QTEE releases the mapping object which 26*87ab676dSAmirreza Zarrabi * calls qcomtee_mem_object_release(). 27*87ab676dSAmirreza Zarrabi * 28*87ab676dSAmirreza Zarrabi * The map operation is implemented in the primordial object as a privileged 29*87ab676dSAmirreza Zarrabi * operation instead of qcomtee_mem_object_dispatch(). Otherwise, on 30*87ab676dSAmirreza Zarrabi * platforms without shm_bridge, a user can trick QTEE into writing to the 31*87ab676dSAmirreza Zarrabi * kernel memory by passing a user object as a memory object and returning a 32*87ab676dSAmirreza Zarrabi * random physical address as the result of the mapping request. 33*87ab676dSAmirreza Zarrabi */ 34*87ab676dSAmirreza Zarrabi 35*87ab676dSAmirreza Zarrabi struct qcomtee_mem_object { 36*87ab676dSAmirreza Zarrabi struct qcomtee_object object; 37*87ab676dSAmirreza Zarrabi struct tee_shm *shm; 38*87ab676dSAmirreza Zarrabi /* QTEE requires these felids to be page aligned. */ 39*87ab676dSAmirreza Zarrabi phys_addr_t paddr; /* Physical address of range. */ 40*87ab676dSAmirreza Zarrabi size_t size; /* Size of the range. */ 41*87ab676dSAmirreza Zarrabi }; 42*87ab676dSAmirreza Zarrabi 43*87ab676dSAmirreza Zarrabi #define to_qcomtee_mem_object(o) \ 44*87ab676dSAmirreza Zarrabi container_of((o), struct qcomtee_mem_object, object) 45*87ab676dSAmirreza Zarrabi 46*87ab676dSAmirreza Zarrabi static struct qcomtee_object_operations qcomtee_mem_object_ops; 47*87ab676dSAmirreza Zarrabi 48*87ab676dSAmirreza Zarrabi /* Is it a memory object using tee_shm? */ 49*87ab676dSAmirreza Zarrabi int is_qcomtee_memobj_object(struct qcomtee_object *object) 50*87ab676dSAmirreza Zarrabi { 51*87ab676dSAmirreza Zarrabi return object != NULL_QCOMTEE_OBJECT && 52*87ab676dSAmirreza Zarrabi typeof_qcomtee_object(object) == QCOMTEE_OBJECT_TYPE_CB && 53*87ab676dSAmirreza Zarrabi object->ops == &qcomtee_mem_object_ops; 54*87ab676dSAmirreza Zarrabi } 55*87ab676dSAmirreza Zarrabi 56*87ab676dSAmirreza Zarrabi static int qcomtee_mem_object_dispatch(struct qcomtee_object_invoke_ctx *oic, 57*87ab676dSAmirreza Zarrabi struct qcomtee_object *object, u32 op, 58*87ab676dSAmirreza Zarrabi struct qcomtee_arg *args) 59*87ab676dSAmirreza Zarrabi { 60*87ab676dSAmirreza Zarrabi return -EINVAL; 61*87ab676dSAmirreza Zarrabi } 62*87ab676dSAmirreza Zarrabi 63*87ab676dSAmirreza Zarrabi static void qcomtee_mem_object_release(struct qcomtee_object *object) 64*87ab676dSAmirreza Zarrabi { 65*87ab676dSAmirreza Zarrabi struct qcomtee_mem_object *mem_object = to_qcomtee_mem_object(object); 66*87ab676dSAmirreza Zarrabi 67*87ab676dSAmirreza Zarrabi /* Matching get is in qcomtee_memobj_param_to_object(). */ 68*87ab676dSAmirreza Zarrabi tee_shm_put(mem_object->shm); 69*87ab676dSAmirreza Zarrabi kfree(mem_object); 70*87ab676dSAmirreza Zarrabi } 71*87ab676dSAmirreza Zarrabi 72*87ab676dSAmirreza Zarrabi static struct qcomtee_object_operations qcomtee_mem_object_ops = { 73*87ab676dSAmirreza Zarrabi .release = qcomtee_mem_object_release, 74*87ab676dSAmirreza Zarrabi .dispatch = qcomtee_mem_object_dispatch, 75*87ab676dSAmirreza Zarrabi }; 76*87ab676dSAmirreza Zarrabi 77*87ab676dSAmirreza Zarrabi /** 78*87ab676dSAmirreza Zarrabi * qcomtee_memobj_param_to_object() - OBJREF parameter to &struct qcomtee_object. 79*87ab676dSAmirreza Zarrabi * @object: object returned. 80*87ab676dSAmirreza Zarrabi * @param: TEE parameter. 81*87ab676dSAmirreza Zarrabi * @ctx: context in which the conversion should happen. 82*87ab676dSAmirreza Zarrabi * 83*87ab676dSAmirreza Zarrabi * @param is an OBJREF with %QCOMTEE_OBJREF_FLAG_MEM flags. 84*87ab676dSAmirreza Zarrabi * 85*87ab676dSAmirreza Zarrabi * Return: On success return 0 or <0 on failure. 86*87ab676dSAmirreza Zarrabi */ 87*87ab676dSAmirreza Zarrabi int qcomtee_memobj_param_to_object(struct qcomtee_object **object, 88*87ab676dSAmirreza Zarrabi struct tee_param *param, 89*87ab676dSAmirreza Zarrabi struct tee_context *ctx) 90*87ab676dSAmirreza Zarrabi { 91*87ab676dSAmirreza Zarrabi struct qcomtee_mem_object *mem_object __free(kfree) = NULL; 92*87ab676dSAmirreza Zarrabi struct tee_shm *shm; 93*87ab676dSAmirreza Zarrabi int err; 94*87ab676dSAmirreza Zarrabi 95*87ab676dSAmirreza Zarrabi mem_object = kzalloc(sizeof(*mem_object), GFP_KERNEL); 96*87ab676dSAmirreza Zarrabi if (!mem_object) 97*87ab676dSAmirreza Zarrabi return -ENOMEM; 98*87ab676dSAmirreza Zarrabi 99*87ab676dSAmirreza Zarrabi shm = tee_shm_get_from_id(ctx, param->u.objref.id); 100*87ab676dSAmirreza Zarrabi if (IS_ERR(shm)) 101*87ab676dSAmirreza Zarrabi return PTR_ERR(shm); 102*87ab676dSAmirreza Zarrabi 103*87ab676dSAmirreza Zarrabi /* mem-object wrapping the memref. */ 104*87ab676dSAmirreza Zarrabi err = qcomtee_object_user_init(&mem_object->object, 105*87ab676dSAmirreza Zarrabi QCOMTEE_OBJECT_TYPE_CB, 106*87ab676dSAmirreza Zarrabi &qcomtee_mem_object_ops, "tee-shm-%d", 107*87ab676dSAmirreza Zarrabi shm->id); 108*87ab676dSAmirreza Zarrabi if (err) { 109*87ab676dSAmirreza Zarrabi tee_shm_put(shm); 110*87ab676dSAmirreza Zarrabi 111*87ab676dSAmirreza Zarrabi return err; 112*87ab676dSAmirreza Zarrabi } 113*87ab676dSAmirreza Zarrabi 114*87ab676dSAmirreza Zarrabi mem_object->paddr = shm->paddr; 115*87ab676dSAmirreza Zarrabi mem_object->size = shm->size; 116*87ab676dSAmirreza Zarrabi mem_object->shm = shm; 117*87ab676dSAmirreza Zarrabi 118*87ab676dSAmirreza Zarrabi *object = &no_free_ptr(mem_object)->object; 119*87ab676dSAmirreza Zarrabi 120*87ab676dSAmirreza Zarrabi return 0; 121*87ab676dSAmirreza Zarrabi } 122*87ab676dSAmirreza Zarrabi 123*87ab676dSAmirreza Zarrabi /* Reverse what qcomtee_memobj_param_to_object() does. */ 124*87ab676dSAmirreza Zarrabi int qcomtee_memobj_param_from_object(struct tee_param *param, 125*87ab676dSAmirreza Zarrabi struct qcomtee_object *object, 126*87ab676dSAmirreza Zarrabi struct tee_context *ctx) 127*87ab676dSAmirreza Zarrabi { 128*87ab676dSAmirreza Zarrabi struct qcomtee_mem_object *mem_object; 129*87ab676dSAmirreza Zarrabi 130*87ab676dSAmirreza Zarrabi mem_object = to_qcomtee_mem_object(object); 131*87ab676dSAmirreza Zarrabi /* Sure if the memobj is in a same context it is originated from. */ 132*87ab676dSAmirreza Zarrabi if (mem_object->shm->ctx != ctx) 133*87ab676dSAmirreza Zarrabi return -EINVAL; 134*87ab676dSAmirreza Zarrabi 135*87ab676dSAmirreza Zarrabi param->u.objref.id = mem_object->shm->id; 136*87ab676dSAmirreza Zarrabi param->u.objref.flags = QCOMTEE_OBJREF_FLAG_MEM; 137*87ab676dSAmirreza Zarrabi 138*87ab676dSAmirreza Zarrabi /* Passing shm->id to userspace; drop the reference. */ 139*87ab676dSAmirreza Zarrabi qcomtee_object_put(object); 140*87ab676dSAmirreza Zarrabi 141*87ab676dSAmirreza Zarrabi return 0; 142*87ab676dSAmirreza Zarrabi } 143*87ab676dSAmirreza Zarrabi 144*87ab676dSAmirreza Zarrabi /** 145*87ab676dSAmirreza Zarrabi * qcomtee_mem_object_map() - Map a memory object. 146*87ab676dSAmirreza Zarrabi * @object: memory object. 147*87ab676dSAmirreza Zarrabi * @map_object: created mapping object. 148*87ab676dSAmirreza Zarrabi * @mem_paddr: physical address of the memory. 149*87ab676dSAmirreza Zarrabi * @mem_size: size of the memory. 150*87ab676dSAmirreza Zarrabi * @perms: QTEE access permissions. 151*87ab676dSAmirreza Zarrabi * 152*87ab676dSAmirreza Zarrabi * Return: On success return 0 or <0 on failure. 153*87ab676dSAmirreza Zarrabi */ 154*87ab676dSAmirreza Zarrabi int qcomtee_mem_object_map(struct qcomtee_object *object, 155*87ab676dSAmirreza Zarrabi struct qcomtee_object **map_object, u64 *mem_paddr, 156*87ab676dSAmirreza Zarrabi u64 *mem_size, u32 *perms) 157*87ab676dSAmirreza Zarrabi { 158*87ab676dSAmirreza Zarrabi struct qcomtee_mem_object *mem_object = to_qcomtee_mem_object(object); 159*87ab676dSAmirreza Zarrabi 160*87ab676dSAmirreza Zarrabi /* Reuses the memory object as a mapping object by re-sharing it. */ 161*87ab676dSAmirreza Zarrabi qcomtee_object_get(&mem_object->object); 162*87ab676dSAmirreza Zarrabi 163*87ab676dSAmirreza Zarrabi *map_object = &mem_object->object; 164*87ab676dSAmirreza Zarrabi *mem_paddr = mem_object->paddr; 165*87ab676dSAmirreza Zarrabi *mem_size = mem_object->size; 166*87ab676dSAmirreza Zarrabi *perms = QCOM_SCM_PERM_RW; 167*87ab676dSAmirreza Zarrabi 168*87ab676dSAmirreza Zarrabi return 0; 169*87ab676dSAmirreza Zarrabi } 170