Skip to content

Commit d6e2908

Browse files
qc-azarrabijenswi-linaro
authored andcommitted
tee: add Qualcomm TEE driver
Introduce qcomtee_object, which represents an object in both QTEE and the kernel. QTEE clients can invoke an instance of qcomtee_object to access QTEE services. If this invocation produces a new object in QTEE, an instance of qcomtee_object will be returned. Similarly, QTEE can request services from by issuing a callback request, which invokes an instance of qcomtee_object. Implement initial support for exporting qcomtee_object to userspace and QTEE, enabling the invocation of objects hosted in QTEE and userspace through the TEE subsystem. Tested-by: Neil Armstrong <neil.armstrong@linaro.org> Tested-by: Harshal Dev <quic_hdev@quicinc.com> Acked-by: Sumit Garg <sumit.garg@oss.qualcomm.com> Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
1 parent bd51393 commit d6e2908

14 files changed

Lines changed: 3537 additions & 0 deletions

File tree

MAINTAINERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20856,6 +20856,12 @@ F: Documentation/networking/device_drivers/cellular/qualcomm/rmnet.rst
2085620856
F: drivers/net/ethernet/qualcomm/rmnet/
2085720857
F: include/linux/if_rmnet.h
2085820858

20859+
QUALCOMM TEE (QCOMTEE) DRIVER
20860+
M: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
20861+
L: linux-arm-msm@vger.kernel.org
20862+
S: Maintained
20863+
F: drivers/tee/qcomtee/
20864+
2085920865
QUALCOMM TRUST ZONE MEMORY ALLOCATOR
2086020866
M: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
2086120867
L: linux-arm-msm@vger.kernel.org

drivers/tee/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ config TEE_DMABUF_HEAPS
2121
source "drivers/tee/optee/Kconfig"
2222
source "drivers/tee/amdtee/Kconfig"
2323
source "drivers/tee/tstee/Kconfig"
24+
source "drivers/tee/qcomtee/Kconfig"
2425

2526
endif

drivers/tee/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ tee-objs += tee_shm_pool.o
77
obj-$(CONFIG_OPTEE) += optee/
88
obj-$(CONFIG_AMDTEE) += amdtee/
99
obj-$(CONFIG_ARM_TSTEE) += tstee/
10+
obj-$(CONFIG_QCOMTEE) += qcomtee/

drivers/tee/qcomtee/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
# Qualcomm Trusted Execution Environment Configuration
3+
config QCOMTEE
4+
tristate "Qualcomm TEE Support"
5+
depends on !CPU_BIG_ENDIAN
6+
select QCOM_SCM
7+
select QCOM_TZMEM_MODE_SHMBRIDGE
8+
help
9+
This option enables the Qualcomm Trusted Execution Environment (QTEE)
10+
driver. It provides an API to access services offered by QTEE and
11+
its loaded Trusted Applications (TAs). Additionally, it facilitates
12+
the export of userspace services provided by supplicants to QTEE.

drivers/tee/qcomtee/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
obj-$(CONFIG_QCOMTEE) += qcomtee.o
3+
qcomtee-objs += async.o
4+
qcomtee-objs += call.o
5+
qcomtee-objs += core.o
6+
qcomtee-objs += shm.o
7+
qcomtee-objs += user_obj.o

drivers/tee/qcomtee/async.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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 "qcomtee.h"
9+
10+
#define QCOMTEE_ASYNC_VERSION_1_0 0x00010000U /* Maj: 0x0001, Min: 0x0000. */
11+
#define QCOMTEE_ASYNC_VERSION_1_1 0x00010001U /* Maj: 0x0001, Min: 0x0001. */
12+
#define QCOMTEE_ASYNC_VERSION_1_2 0x00010002U /* Maj: 0x0001, Min: 0x0002. */
13+
#define QCOMTEE_ASYNC_VERSION_CURRENT QCOMTEE_ASYNC_VERSION_1_2
14+
15+
#define QCOMTEE_ASYNC_VERSION_MAJOR(n) upper_16_bits(n)
16+
#define QCOMTEE_ASYNC_VERSION_MINOR(n) lower_16_bits(n)
17+
18+
#define QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR \
19+
QCOMTEE_ASYNC_VERSION_MAJOR(QCOMTEE_ASYNC_VERSION_CURRENT)
20+
#define QCOMTEE_ASYNC_VERSION_CURRENT_MINOR \
21+
QCOMTEE_ASYNC_VERSION_MINOR(QCOMTEE_ASYNC_VERSION_CURRENT)
22+
23+
/**
24+
* struct qcomtee_async_msg_hdr - Asynchronous message header format.
25+
* @version: current async protocol version of the remote endpoint.
26+
* @op: async operation.
27+
*
28+
* @version specifies the endpoint's (QTEE or driver) supported async protocol.
29+
* For example, if QTEE sets @version to %QCOMTEE_ASYNC_VERSION_1_1, QTEE
30+
* handles operations supported in %QCOMTEE_ASYNC_VERSION_1_1 or
31+
* %QCOMTEE_ASYNC_VERSION_1_0. @op determines the message format.
32+
*/
33+
struct qcomtee_async_msg_hdr {
34+
u32 version;
35+
u32 op;
36+
};
37+
38+
/* Size of an empty async message. */
39+
#define QCOMTEE_ASYNC_MSG_ZERO sizeof(struct qcomtee_async_msg_hdr)
40+
41+
/**
42+
* struct qcomtee_async_release_msg - Release asynchronous message.
43+
* @hdr: message header as &struct qcomtee_async_msg_hdr.
44+
* @counts: number of objects in @object_ids.
45+
* @object_ids: array of object IDs that should be released.
46+
*
47+
* Available in Maj = 0x0001, Min >= 0x0000.
48+
*/
49+
struct qcomtee_async_release_msg {
50+
struct qcomtee_async_msg_hdr hdr;
51+
u32 counts;
52+
u32 object_ids[] __counted_by(counts);
53+
};
54+
55+
/**
56+
* qcomtee_get_async_buffer() - Get the start of the asynchronous message.
57+
* @oic: context used for the current invocation.
58+
* @async_buffer: return buffer to extract from or fill in async messages.
59+
*
60+
* If @oic is used for direct object invocation, the whole outbound buffer
61+
* is available for the async message. If @oic is used for a callback request,
62+
* the tail of the outbound buffer (after the callback request message) is
63+
* available for the async message.
64+
*
65+
* The start of the async buffer is aligned, see qcomtee_msg_offset_align().
66+
*/
67+
static void qcomtee_get_async_buffer(struct qcomtee_object_invoke_ctx *oic,
68+
struct qcomtee_buffer *async_buffer)
69+
{
70+
struct qcomtee_msg_callback *msg;
71+
unsigned int offset;
72+
int i;
73+
74+
if (!(oic->flags & QCOMTEE_OIC_FLAG_BUSY)) {
75+
/* The outbound buffer is empty. Using the whole buffer. */
76+
offset = 0;
77+
} else {
78+
msg = (struct qcomtee_msg_callback *)oic->out_msg.addr;
79+
80+
/* Start offset in a message for buffer arguments. */
81+
offset = qcomtee_msg_buffer_args(struct qcomtee_msg_callback,
82+
qcomtee_msg_args(msg));
83+
84+
/* Add size of IB arguments. */
85+
qcomtee_msg_for_each_input_buffer(i, msg)
86+
offset += qcomtee_msg_offset_align(msg->args[i].b.size);
87+
88+
/* Add size of OB arguments. */
89+
qcomtee_msg_for_each_output_buffer(i, msg)
90+
offset += qcomtee_msg_offset_align(msg->args[i].b.size);
91+
}
92+
93+
async_buffer->addr = oic->out_msg.addr + offset;
94+
async_buffer->size = oic->out_msg.size - offset;
95+
}
96+
97+
/**
98+
* async_release() - Process QTEE async release requests.
99+
* @oic: context used for the current invocation.
100+
* @msg: async message for object release.
101+
* @size: size of the async buffer available.
102+
*
103+
* Return: Size of the outbound buffer used when processing @msg.
104+
*/
105+
static size_t async_release(struct qcomtee_object_invoke_ctx *oic,
106+
struct qcomtee_async_msg_hdr *async_msg,
107+
size_t size)
108+
{
109+
struct qcomtee_async_release_msg *msg;
110+
struct qcomtee_object *object;
111+
int i;
112+
113+
msg = (struct qcomtee_async_release_msg *)async_msg;
114+
115+
for (i = 0; i < msg->counts; i++) {
116+
object = qcomtee_idx_erase(oic, msg->object_ids[i]);
117+
qcomtee_object_put(object);
118+
}
119+
120+
return struct_size(msg, object_ids, msg->counts);
121+
}
122+
123+
/**
124+
* qcomtee_fetch_async_reqs() - Fetch and process asynchronous messages.
125+
* @oic: context used for the current invocation.
126+
*
127+
* Calls handlers to process the requested operations in the async message.
128+
* Currently, only supports async release requests.
129+
*/
130+
void qcomtee_fetch_async_reqs(struct qcomtee_object_invoke_ctx *oic)
131+
{
132+
struct qcomtee_async_msg_hdr *async_msg;
133+
struct qcomtee_buffer async_buffer;
134+
size_t consumed, used = 0;
135+
u16 major_ver;
136+
137+
qcomtee_get_async_buffer(oic, &async_buffer);
138+
139+
while (async_buffer.size - used > QCOMTEE_ASYNC_MSG_ZERO) {
140+
async_msg = (struct qcomtee_async_msg_hdr *)(async_buffer.addr +
141+
used);
142+
/*
143+
* QTEE assumes that the unused space of the async buffer is
144+
* zeroed; so if version is zero, the buffer is unused.
145+
*/
146+
if (async_msg->version == 0)
147+
goto out;
148+
149+
major_ver = QCOMTEE_ASYNC_VERSION_MAJOR(async_msg->version);
150+
/* Major version mismatch is a compatibility break. */
151+
if (major_ver != QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR) {
152+
pr_err("Async message version mismatch (%u != %u)\n",
153+
major_ver, QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR);
154+
155+
goto out;
156+
}
157+
158+
switch (async_msg->op) {
159+
case QCOMTEE_MSG_OBJECT_OP_RELEASE:
160+
consumed = async_release(oic, async_msg,
161+
async_buffer.size - used);
162+
break;
163+
default:
164+
pr_err("Unsupported async message %u\n", async_msg->op);
165+
goto out;
166+
}
167+
168+
/* Supported operation but unable to parse the message. */
169+
if (!consumed) {
170+
pr_err("Unable to parse async message for op %u\n",
171+
async_msg->op);
172+
goto out;
173+
}
174+
175+
/* Next async message. */
176+
used += qcomtee_msg_offset_align(consumed);
177+
}
178+
179+
out:
180+
/* Reset the async buffer so async requests do not loop to QTEE. */
181+
memzero_explicit(async_buffer.addr, async_buffer.size);
182+
}

0 commit comments

Comments
 (0)