@@ -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
@@ -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.
*/
new file mode 100644
@@ -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
+};
@@ -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 */
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@quicinc.com> --- 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(-)