After booting, the kernel provides a static object known as the primordial object. This object is utilized by QTEE for native kernel services such as yield or privileged operations. Signed-off-by: Amirreza Zarrabi <quic_azarrabi@xxxxxxxxxxx> --- drivers/tee/qcomtee/Makefile | 1 + drivers/tee/qcomtee/core.c | 12 +++++-- drivers/tee/qcomtee/primordial_obj.c | 63 +++++++++++++++++++++++++++++++++++ drivers/tee/qcomtee/qcomtee_private.h | 5 +++ 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/drivers/tee/qcomtee/Makefile b/drivers/tee/qcomtee/Makefile index 7dc5e6373042..108bc7fdabcb 100644 --- a/drivers/tee/qcomtee/Makefile +++ b/drivers/tee/qcomtee/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_QCOMTEE) += qcomtee.o qcomtee-objs += async.o qcomtee-objs += core.o +qcomtee-objs += primordial_obj.o qcomtee-objs += qcom_scm.o qcomtee-objs += release.o diff --git a/drivers/tee/qcomtee/core.c b/drivers/tee/qcomtee/core.c index a949ef4cceee..79f1181cf676 100644 --- a/drivers/tee/qcomtee/core.c +++ b/drivers/tee/qcomtee/core.c @@ -34,9 +34,11 @@ int qcom_tee_next_arg_type(struct qcom_tee_arg *u, int i, enum qcom_tee_arg_type } /* QTEE expects IDs with QCOM_TEE_MSG_OBJECT_NS_BIT set for object of - * QCOM_TEE_OBJECT_TYPE_CB_OBJECT type. + * QCOM_TEE_OBJECT_TYPE_CB_OBJECT type. The first ID with QCOM_TEE_MSG_OBJECT_NS_BIT set is + * reserved for primordial object. */ -#define QCOM_TEE_OBJECT_ID_START (QCOM_TEE_MSG_OBJECT_NS_BIT + 1) +#define QCOM_TEE_OBJECT_PRIMORDIAL (QCOM_TEE_MSG_OBJECT_NS_BIT) +#define QCOM_TEE_OBJECT_ID_START (QCOM_TEE_OBJECT_PRIMORDIAL + 1) #define QCOM_TEE_OBJECT_ID_END (UINT_MAX) #define QCOM_TEE_OBJECT_SET(p, type, ...) __QCOM_TEE_OBJECT_SET(p, type, ##__VA_ARGS__, 0UL) @@ -118,7 +120,8 @@ EXPORT_SYMBOL_GPL(qcom_tee_object_get); */ void qcom_tee_object_put(struct qcom_tee_object *object) { - if (object != NULL_QCOM_TEE_OBJECT && + if (object != &qcom_tee_primordial_object && + object != NULL_QCOM_TEE_OBJECT && object != ROOT_QCOM_TEE_OBJECT) kref_put(&object->refcount, qcom_tee_object_release); } @@ -209,6 +212,9 @@ static struct qcom_tee_object *qcom_tee_local_object_get(unsigned int object_id) { struct qcom_tee_object *object; + if (object_id == QCOM_TEE_OBJECT_PRIMORDIAL) + return &qcom_tee_primordial_object; + /* We trust QTEE does not mess the refcounts. * It does not issue RELEASE request and qcom_tee_object_get(), simultaneously. */ diff --git a/drivers/tee/qcomtee/primordial_obj.c b/drivers/tee/qcomtee/primordial_obj.c new file mode 100644 index 000000000000..9065074b02e6 --- /dev/null +++ b/drivers/tee/qcomtee/primordial_obj.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/delay.h> +#include "qcomtee_private.h" + +/** + * DOC: Primordial Object + * + * After the boot, REE provides a static object of type %QCOM_TEE_OBJECT_TYPE_CB_OBJECT + * called primordial object. This object is used for native REE services or privileged operations. + * + * We support + * - %QCOM_TEE_OBJECT_OP_YIELD to yield by the thread running in QTEE. + * - %QCOM_TEE_OBJECT_OP_SLEEP to wait for period of time. + */ + +#define QCOM_TEE_OBJECT_OP_YIELD 1 +#define QCOM_TEE_OBJECT_OP_SLEEP 2 + +static int qcom_tee_primordial_object_dispatch(struct qcom_tee_object_invoke_ctx *oic, + struct qcom_tee_object *primordial_object_unused, + u32 op, struct qcom_tee_arg *args) +{ + int err = 0; + + switch (op) { + case QCOM_TEE_OBJECT_OP_YIELD: + cond_resched(); + /* No output object. */ + oic->data = NULL; + break; + case QCOM_TEE_OBJECT_OP_SLEEP: + /* Check message format matched QCOM_TEE_OBJECT_OP_SLEEP op. */ + if (qcom_tee_args_len(args) != 1 || /* Expect 1 argument. */ + args[0].type != QCOM_TEE_ARG_TYPE_IB || /* Time to sleep in ms. */ + args[0].b.size < sizeof(u32)) /* Buffer should hold a u32. */ + return -EINVAL; + + msleep(*(u32 *)(args[0].b.addr)); + /* No output object. */ + oic->data = NULL; + break; + default: + err = -EINVAL; + } + + return err; +} + +static struct qcom_tee_object_operations qcom_tee_primordial_object_ops = { + .dispatch = qcom_tee_primordial_object_dispatch, +}; + +struct qcom_tee_object qcom_tee_primordial_object = { + .name = "primordial", + .object_type = QCOM_TEE_OBJECT_TYPE_CB_OBJECT, + .ops = &qcom_tee_primordial_object_ops +}; diff --git a/drivers/tee/qcomtee/qcomtee_private.h b/drivers/tee/qcomtee/qcomtee_private.h index e3e4ef51c0b2..c718cd2d8463 100644 --- a/drivers/tee/qcomtee/qcomtee_private.h +++ b/drivers/tee/qcomtee/qcomtee_private.h @@ -44,4 +44,9 @@ int __qcom_tee_object_do_invoke(struct qcom_tee_object_invoke_ctx *oic, struct qcom_tee_object *object, u32 op, struct qcom_tee_arg *u, int *result); +/* OBJECTS: */ + +/* (1) Primordial Object. */ +extern struct qcom_tee_object qcom_tee_primordial_object; + #endif /* QCOM_TEE_PRIVATE_H */ -- 2.34.1