diff mbox series

[06/10] qcomtee: add primordial object

Message ID 20241202-qcom-tee-using-tee-ss-without-mem-obj-v1-6-f502ef01e016@quicinc.com
State New
Headers show
Series None | expand

Commit Message

Amirreza Zarrabi Dec. 3, 2024, 4:19 a.m. UTC
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(-)
diff mbox series

Patch

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 */