Skip to content

Commit 87ab676

Browse files
qc-azarrabijenswi-linaro
authored andcommitted
tee: qcom: enable TEE_IOC_SHM_ALLOC ioctl
Enable userspace to allocate shared memory with QTEE. Since QTEE handles shared memory as object, a wrapper is implemented to represent tee_shm as an object. The shared memory identifier, obtained through TEE_IOC_SHM_ALLOC, is transferred to the driver using TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT/OUTPUT. Tested-by: Neil Armstrong <neil.armstrong@linaro.org> Acked-by: Sumit Garg <sumit.garg@oss.qualcomm.com> Tested-by: Harshal Dev <quic_hdev@quicinc.com> Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
1 parent 0f7bfdc commit 87ab676

6 files changed

Lines changed: 267 additions & 4 deletions

File tree

drivers/tee/qcomtee/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ obj-$(CONFIG_QCOMTEE) += qcomtee.o
33
qcomtee-objs += async.o
44
qcomtee-objs += call.o
55
qcomtee-objs += core.o
6+
qcomtee-objs += mem_obj.o
67
qcomtee-objs += primordial_obj.o
78
qcomtee-objs += shm.o
89
qcomtee-objs += user_obj.o

drivers/tee/qcomtee/call.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ int qcomtee_objref_to_arg(struct qcomtee_arg *arg, struct tee_param *param,
122122
err = qcomtee_user_param_to_object(&arg->o, param, ctx);
123123
/* param is a QTEE object: */
124124
else if (param->u.objref.flags & QCOMTEE_OBJREF_FLAG_TEE)
125-
err = qcomtee_context_find_qtee_object(&arg->o, param, ctx);
125+
err = qcomtee_context_find_qtee_object(&arg->o, param, ctx);
126+
/* param is a memory object: */
127+
else if (param->u.objref.flags & QCOMTEE_OBJREF_FLAG_MEM)
128+
err = qcomtee_memobj_param_to_object(&arg->o, param, ctx);
126129

127130
/*
128131
* For callback objects, call qcomtee_object_get() to keep a temporary
@@ -168,6 +171,10 @@ int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg,
168171
if (is_qcomtee_user_object(object))
169172
return qcomtee_user_param_from_object(param, object,
170173
ctx);
174+
/* object is a memory object: */
175+
else if (is_qcomtee_memobj_object(object))
176+
return qcomtee_memobj_param_from_object(param, object,
177+
ctx);
171178

172179
break;
173180
case QCOMTEE_OBJECT_TYPE_TEE:

drivers/tee/qcomtee/mem_obj.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
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+
}

drivers/tee/qcomtee/primordial_obj.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,39 @@
1414
* for native kernel services or privileged operations.
1515
*
1616
* We support:
17+
* - %QCOMTEE_OBJECT_OP_MAP_REGION to map a memory object and return mapping
18+
* object and mapping information (see qcomtee_mem_object_map()).
1719
* - %QCOMTEE_OBJECT_OP_YIELD to yield by the thread running in QTEE.
1820
* - %QCOMTEE_OBJECT_OP_SLEEP to wait for a period of time.
1921
*/
2022

23+
#define QCOMTEE_OBJECT_OP_MAP_REGION 0
2124
#define QCOMTEE_OBJECT_OP_YIELD 1
2225
#define QCOMTEE_OBJECT_OP_SLEEP 2
2326

27+
/* Mapping information format as expected by QTEE. */
28+
struct qcomtee_mapping_info {
29+
u64 paddr;
30+
u64 len;
31+
u32 perms;
32+
} __packed;
33+
2434
static int
2535
qcomtee_primordial_obj_dispatch(struct qcomtee_object_invoke_ctx *oic,
2636
struct qcomtee_object *primordial_object_unused,
2737
u32 op, struct qcomtee_arg *args)
2838
{
39+
struct qcomtee_mapping_info *map_info;
40+
struct qcomtee_object *mem_object;
41+
struct qcomtee_object *map_object;
2942
int err = 0;
3043

3144
switch (op) {
3245
case QCOMTEE_OBJECT_OP_YIELD:
3346
cond_resched();
3447
/* No output object. */
3548
oic->data = NULL;
49+
3650
break;
3751
case QCOMTEE_OBJECT_OP_SLEEP:
3852
/* Check message format matched QCOMTEE_OBJECT_OP_SLEEP op. */
@@ -44,6 +58,29 @@ qcomtee_primordial_obj_dispatch(struct qcomtee_object_invoke_ctx *oic,
4458
msleep(*(u32 *)(args[0].b.addr));
4559
/* No output object. */
4660
oic->data = NULL;
61+
62+
break;
63+
case QCOMTEE_OBJECT_OP_MAP_REGION:
64+
if (qcomtee_args_len(args) != 3 ||
65+
args[0].type != QCOMTEE_ARG_TYPE_OB ||
66+
args[1].type != QCOMTEE_ARG_TYPE_IO ||
67+
args[2].type != QCOMTEE_ARG_TYPE_OO ||
68+
args[0].b.size < sizeof(struct qcomtee_mapping_info))
69+
return -EINVAL;
70+
71+
map_info = args[0].b.addr;
72+
mem_object = args[1].o;
73+
74+
qcomtee_mem_object_map(mem_object, &map_object,
75+
&map_info->paddr, &map_info->len,
76+
&map_info->perms);
77+
78+
args[2].o = map_object;
79+
/* One output object; pass it for cleanup to notify. */
80+
oic->data = map_object;
81+
82+
qcomtee_object_put(mem_object);
83+
4784
break;
4885
default:
4986
err = -EINVAL;
@@ -52,8 +89,21 @@ qcomtee_primordial_obj_dispatch(struct qcomtee_object_invoke_ctx *oic,
5289
return err;
5390
}
5491

92+
/* Called after submitting the callback response. */
93+
static void qcomtee_primordial_obj_notify(struct qcomtee_object_invoke_ctx *oic,
94+
struct qcomtee_object *unused,
95+
int err)
96+
{
97+
struct qcomtee_object *object = oic->data;
98+
99+
/* If err, QTEE did not obtain mapping object. Drop it. */
100+
if (object && err)
101+
qcomtee_object_put(object);
102+
}
103+
55104
static struct qcomtee_object_operations qcomtee_primordial_obj_ops = {
56105
.dispatch = qcomtee_primordial_obj_dispatch,
106+
.notify = qcomtee_primordial_obj_notify,
57107
};
58108

59109
struct qcomtee_object qcomtee_primordial_object = {

drivers/tee/qcomtee/qcomtee.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
/* Flags relating to object reference. */
1616
#define QCOMTEE_OBJREF_FLAG_TEE BIT(0)
1717
#define QCOMTEE_OBJREF_FLAG_USER BIT(1)
18+
#define QCOMTEE_OBJREF_FLAG_MEM BIT(2)
1819

1920
/**
2021
* struct qcomtee - Main service struct.
@@ -143,4 +144,42 @@ int qcomtee_user_object_submit(struct tee_context *ctx,
143144
/* (2) Primordial Object. */
144145
extern struct qcomtee_object qcomtee_primordial_object;
145146

147+
/* (3) Memory Object API. */
148+
149+
/* Is it a memory object using tee_shm? */
150+
int is_qcomtee_memobj_object(struct qcomtee_object *object);
151+
152+
/**
153+
* qcomtee_memobj_param_to_object() - OBJREF parameter to &struct qcomtee_object.
154+
* @object: object returned.
155+
* @param: TEE parameter.
156+
* @ctx: context in which the conversion should happen.
157+
*
158+
* @param is an OBJREF with %QCOMTEE_OBJREF_FLAG_MEM flags.
159+
*
160+
* Return: On success return 0 or <0 on failure.
161+
*/
162+
int qcomtee_memobj_param_to_object(struct qcomtee_object **object,
163+
struct tee_param *param,
164+
struct tee_context *ctx);
165+
166+
/* Reverse what qcomtee_memobj_param_to_object() does. */
167+
int qcomtee_memobj_param_from_object(struct tee_param *param,
168+
struct qcomtee_object *object,
169+
struct tee_context *ctx);
170+
171+
/**
172+
* qcomtee_mem_object_map() - Map a memory object.
173+
* @object: memory object.
174+
* @map_object: created mapping object.
175+
* @mem_paddr: physical address of the memory.
176+
* @mem_size: size of the memory.
177+
* @perms: QTEE access permissions.
178+
*
179+
* Return: On success return 0 or <0 on failure.
180+
*/
181+
int qcomtee_mem_object_map(struct qcomtee_object *object,
182+
struct qcomtee_object **map_object, u64 *mem_paddr,
183+
u64 *mem_size, u32 *perms);
184+
146185
#endif /* QCOMTEE_H */

drivers/tee/qcomtee/shm.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ static int qcomtee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
117117
static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm,
118118
size_t size, size_t align)
119119
{
120-
if (!(shm->flags & TEE_SHM_PRIV))
121-
return -ENOMEM;
122-
123120
return tee_dyn_shm_alloc_helper(shm, size, align, qcomtee_shm_register);
124121
}
125122

0 commit comments

Comments
 (0)