Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4 */
5
6#include <linux/delay.h>
7#include "qcomtee.h"
8
9/**
10 * DOC: Primordial Object
11 *
12 * After boot, the kernel provides a static object of type
13 * %QCOMTEE_OBJECT_TYPE_CB called the primordial object. This object is used
14 * for native kernel services or privileged operations.
15 *
16 * 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()).
19 * - %QCOMTEE_OBJECT_OP_YIELD to yield by the thread running in QTEE.
20 * - %QCOMTEE_OBJECT_OP_SLEEP to wait for a period of time.
21 */
22
23#define QCOMTEE_OBJECT_OP_MAP_REGION 0
24#define QCOMTEE_OBJECT_OP_YIELD 1
25#define QCOMTEE_OBJECT_OP_SLEEP 2
26
27/* Mapping information format as expected by QTEE. */
28struct qcomtee_mapping_info {
29 u64 paddr;
30 u64 len;
31 u32 perms;
32} __packed;
33
34static int
35qcomtee_primordial_obj_dispatch(struct qcomtee_object_invoke_ctx *oic,
36 struct qcomtee_object *primordial_object_unused,
37 u32 op, struct qcomtee_arg *args)
38{
39 struct qcomtee_mapping_info *map_info;
40 struct qcomtee_object *mem_object;
41 struct qcomtee_object *map_object;
42 int err = 0;
43
44 switch (op) {
45 case QCOMTEE_OBJECT_OP_YIELD:
46 cond_resched();
47 /* No output object. */
48 oic->data = NULL;
49
50 break;
51 case QCOMTEE_OBJECT_OP_SLEEP:
52 /* Check message format matched QCOMTEE_OBJECT_OP_SLEEP op. */
53 if (qcomtee_args_len(args) != 1 ||
54 args[0].type != QCOMTEE_ARG_TYPE_IB ||
55 args[0].b.size < sizeof(u32))
56 return -EINVAL;
57
58 msleep(*(u32 *)(args[0].b.addr));
59 /* No output object. */
60 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
84 break;
85 default:
86 err = -EINVAL;
87 }
88
89 return err;
90}
91
92/* Called after submitting the callback response. */
93static 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
104static struct qcomtee_object_operations qcomtee_primordial_obj_ops = {
105 .dispatch = qcomtee_primordial_obj_dispatch,
106 .notify = qcomtee_primordial_obj_notify,
107};
108
109struct qcomtee_object qcomtee_primordial_object = {
110 .name = "primordial",
111 .object_type = QCOMTEE_OBJECT_TYPE_CB,
112 .ops = &qcomtee_primordial_obj_ops
113};