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