Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

optee: separate notification functions

Renames struct optee_wait_queue to struct optee_notif and all related
functions to optee_notif_*().

The implementation is changed to allow sending a notification from an
atomic state, that is from the top half of an interrupt handler.

Waiting for keys is currently only used when secure world is waiting for
a mutex or condition variable. The old implementation could handle any
32-bit key while this new implementation is restricted to only 8 bits or
the maximum value 255. A upper value is needed since a bitmap is
allocated to allow an interrupt handler to only set a bit in case the
waiter hasn't had the time yet to allocate and register a completion.

The keys are currently only representing secure world threads which
number usually are never even close to 255 so it should be safe for now.
In future ABI updates the maximum value of the key will be communicated
while the driver is initializing.

Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>

+181 -91
+1
drivers/tee/optee/Makefile
··· 2 2 obj-$(CONFIG_OPTEE) += optee.o 3 3 optee-objs += core.o 4 4 optee-objs += call.o 5 + optee-objs += notif.o 5 6 optee-objs += rpc.o 6 7 optee-objs += supp.o 7 8 optee-objs += device.o
+1 -1
drivers/tee/optee/core.c
··· 159 159 /* Unregister OP-TEE specific client devices on TEE bus */ 160 160 optee_unregister_devices(); 161 161 162 + optee_notif_uninit(optee); 162 163 /* 163 164 * The two devices have to be unregistered before we can free the 164 165 * other resources. ··· 168 167 tee_device_unregister(optee->teedev); 169 168 170 169 tee_shm_pool_free(optee->pool); 171 - optee_wait_queue_exit(&optee->wait_queue); 172 170 optee_supp_uninit(&optee->supp); 173 171 mutex_destroy(&optee->call_queue.mutex); 174 172 }
+5 -1
drivers/tee/optee/ffa_abi.c
··· 856 856 mutex_init(&optee->ffa.mutex); 857 857 mutex_init(&optee->call_queue.mutex); 858 858 INIT_LIST_HEAD(&optee->call_queue.waiters); 859 - optee_wait_queue_init(&optee->wait_queue); 860 859 optee_supp_init(&optee->supp); 861 860 ffa_dev_set_drvdata(ffa_dev, optee); 861 + rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE); 862 + if (rc) { 863 + optee_ffa_remove(ffa_dev); 864 + return rc; 865 + } 862 866 863 867 rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES); 864 868 if (rc) {
+125
drivers/tee/optee/notif.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2015-2021, Linaro Limited 4 + */ 5 + 6 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 + 8 + #include <linux/arm-smccc.h> 9 + #include <linux/errno.h> 10 + #include <linux/slab.h> 11 + #include <linux/spinlock.h> 12 + #include <linux/tee_drv.h> 13 + #include "optee_private.h" 14 + 15 + struct notif_entry { 16 + struct list_head link; 17 + struct completion c; 18 + u_int key; 19 + }; 20 + 21 + static bool have_key(struct optee *optee, u_int key) 22 + { 23 + struct notif_entry *entry; 24 + 25 + list_for_each_entry(entry, &optee->notif.db, link) 26 + if (entry->key == key) 27 + return true; 28 + 29 + return false; 30 + } 31 + 32 + int optee_notif_wait(struct optee *optee, u_int key) 33 + { 34 + unsigned long flags; 35 + struct notif_entry *entry; 36 + int rc = 0; 37 + 38 + if (key > optee->notif.max_key) 39 + return -EINVAL; 40 + 41 + entry = kmalloc(sizeof(*entry), GFP_KERNEL); 42 + if (!entry) 43 + return -ENOMEM; 44 + init_completion(&entry->c); 45 + entry->key = key; 46 + 47 + spin_lock_irqsave(&optee->notif.lock, flags); 48 + 49 + /* 50 + * If the bit is already set it means that the key has already 51 + * been posted and we must not wait. 52 + */ 53 + if (test_bit(key, optee->notif.bitmap)) { 54 + clear_bit(key, optee->notif.bitmap); 55 + goto out; 56 + } 57 + 58 + /* 59 + * Check if someone is already waiting for this key. If there is 60 + * it's a programming error. 61 + */ 62 + if (have_key(optee, key)) { 63 + rc = -EBUSY; 64 + goto out; 65 + } 66 + 67 + list_add_tail(&entry->link, &optee->notif.db); 68 + 69 + /* 70 + * Unlock temporarily and wait for completion. 71 + */ 72 + spin_unlock_irqrestore(&optee->notif.lock, flags); 73 + wait_for_completion(&entry->c); 74 + spin_lock_irqsave(&optee->notif.lock, flags); 75 + 76 + list_del(&entry->link); 77 + out: 78 + spin_unlock_irqrestore(&optee->notif.lock, flags); 79 + 80 + kfree(entry); 81 + 82 + return rc; 83 + } 84 + 85 + int optee_notif_send(struct optee *optee, u_int key) 86 + { 87 + unsigned long flags; 88 + struct notif_entry *entry; 89 + 90 + if (key > optee->notif.max_key) 91 + return -EINVAL; 92 + 93 + spin_lock_irqsave(&optee->notif.lock, flags); 94 + 95 + list_for_each_entry(entry, &optee->notif.db, link) 96 + if (entry->key == key) { 97 + complete(&entry->c); 98 + goto out; 99 + } 100 + 101 + /* Only set the bit in case there where nobody waiting */ 102 + set_bit(key, optee->notif.bitmap); 103 + out: 104 + spin_unlock_irqrestore(&optee->notif.lock, flags); 105 + 106 + return 0; 107 + } 108 + 109 + int optee_notif_init(struct optee *optee, u_int max_key) 110 + { 111 + spin_lock_init(&optee->notif.lock); 112 + INIT_LIST_HEAD(&optee->notif.db); 113 + optee->notif.bitmap = bitmap_zalloc(max_key, GFP_KERNEL); 114 + if (!optee->notif.bitmap) 115 + return -ENOMEM; 116 + 117 + optee->notif.max_key = max_key; 118 + 119 + return 0; 120 + } 121 + 122 + void optee_notif_uninit(struct optee *optee) 123 + { 124 + kfree(optee->notif.bitmap); 125 + }
+18 -8
drivers/tee/optee/optee_private.h
··· 28 28 29 29 #define TEEC_ORIGIN_COMMS 0x00000002 30 30 31 + /* 32 + * This value should be larger than the number threads in secure world to 33 + * meet the need from secure world. The number of threads in secure world 34 + * are usually not even close to 255 so we should be safe for now. 35 + */ 36 + #define OPTEE_DEFAULT_MAX_NOTIF_VALUE 255 37 + 31 38 typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long, 32 39 unsigned long, unsigned long, unsigned long, 33 40 unsigned long, unsigned long, ··· 51 44 struct list_head waiters; 52 45 }; 53 46 54 - struct optee_wait_queue { 55 - /* Serializes access to this struct */ 56 - struct mutex mu; 47 + struct optee_notif { 48 + u_int max_key; 49 + /* Serializes access to the elements below in this struct */ 50 + spinlock_t lock; 57 51 struct list_head db; 52 + u_long *bitmap; 58 53 }; 59 54 60 55 /** ··· 138 129 * @smc: specific to SMC ABI 139 130 * @ffa: specific to FF-A ABI 140 131 * @call_queue: queue of threads waiting to call @invoke_fn 141 - * @wait_queue: queue of threads from secure world waiting for a 142 - * secure world sync object 132 + * @notif: notification synchronization struct 143 133 * @supp: supplicant synchronization struct for RPC to supplicant 144 134 * @pool: shared memory pool 145 135 * @rpc_arg_count: If > 0 number of RPC parameters to make room for ··· 155 147 struct optee_ffa ffa; 156 148 }; 157 149 struct optee_call_queue call_queue; 158 - struct optee_wait_queue wait_queue; 150 + struct optee_notif notif; 159 151 struct optee_supp supp; 160 152 struct tee_shm_pool *pool; 161 153 unsigned int rpc_arg_count; ··· 193 185 size_t num_entries; 194 186 }; 195 187 196 - void optee_wait_queue_init(struct optee_wait_queue *wq); 197 - void optee_wait_queue_exit(struct optee_wait_queue *wq); 188 + int optee_notif_init(struct optee *optee, u_int max_key); 189 + void optee_notif_uninit(struct optee *optee); 190 + int optee_notif_wait(struct optee *optee, u_int key); 191 + int optee_notif_send(struct optee *optee, u_int key); 198 192 199 193 u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, 200 194 struct tee_param *param);
+17 -14
drivers/tee/optee/optee_rpc_cmd.h
··· 28 28 #define OPTEE_RPC_CMD_GET_TIME 3 29 29 30 30 /* 31 - * Wait queue primitive, helper for secure world to implement a wait queue. 31 + * Notification from/to secure world. 32 32 * 33 - * If secure world needs to wait for a secure world mutex it issues a sleep 34 - * request instead of spinning in secure world. Conversely is a wakeup 35 - * request issued when a secure world mutex with a thread waiting thread is 36 - * unlocked. 33 + * If secure world needs to wait for something, for instance a mutex, it 34 + * does a notification wait request instead of spinning in secure world. 35 + * Conversely can a synchronous notification can be sent when a secure 36 + * world mutex with a thread waiting thread is unlocked. 37 37 * 38 - * Waiting on a key 39 - * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_SLEEP 40 - * [in] value[0].b Wait key 38 + * This interface can also be used to wait for a asynchronous notification 39 + * which instead is sent via a non-secure interrupt. 41 40 * 42 - * Waking up a key 43 - * [in] value[0].a OPTEE_RPC_WAIT_QUEUE_WAKEUP 44 - * [in] value[0].b Wakeup key 41 + * Waiting on notification 42 + * [in] value[0].a OPTEE_RPC_NOTIFICATION_WAIT 43 + * [in] value[0].b notification value 44 + * 45 + * Sending a synchronous notification 46 + * [in] value[0].a OPTEE_RPC_NOTIFICATION_SEND 47 + * [in] value[0].b notification value 45 48 */ 46 - #define OPTEE_RPC_CMD_WAIT_QUEUE 4 47 - #define OPTEE_RPC_WAIT_QUEUE_SLEEP 0 48 - #define OPTEE_RPC_WAIT_QUEUE_WAKEUP 1 49 + #define OPTEE_RPC_CMD_NOTIFICATION 4 50 + #define OPTEE_RPC_NOTIFICATION_WAIT 0 51 + #define OPTEE_RPC_NOTIFICATION_SEND 1 49 52 50 53 /* 51 54 * Suspend execution
+7 -64
drivers/tee/optee/rpc.c
··· 12 12 #include "optee_private.h" 13 13 #include "optee_rpc_cmd.h" 14 14 15 - struct wq_entry { 16 - struct list_head link; 17 - struct completion c; 18 - u32 key; 19 - }; 20 - 21 - void optee_wait_queue_init(struct optee_wait_queue *priv) 22 - { 23 - mutex_init(&priv->mu); 24 - INIT_LIST_HEAD(&priv->db); 25 - } 26 - 27 - void optee_wait_queue_exit(struct optee_wait_queue *priv) 28 - { 29 - mutex_destroy(&priv->mu); 30 - } 31 - 32 15 static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg) 33 16 { 34 17 struct timespec64 ts; ··· 127 144 } 128 145 #endif 129 146 130 - static struct wq_entry *wq_entry_get(struct optee_wait_queue *wq, u32 key) 131 - { 132 - struct wq_entry *w; 133 - 134 - mutex_lock(&wq->mu); 135 - 136 - list_for_each_entry(w, &wq->db, link) 137 - if (w->key == key) 138 - goto out; 139 - 140 - w = kmalloc(sizeof(*w), GFP_KERNEL); 141 - if (w) { 142 - init_completion(&w->c); 143 - w->key = key; 144 - list_add_tail(&w->link, &wq->db); 145 - } 146 - out: 147 - mutex_unlock(&wq->mu); 148 - return w; 149 - } 150 - 151 - static void wq_sleep(struct optee_wait_queue *wq, u32 key) 152 - { 153 - struct wq_entry *w = wq_entry_get(wq, key); 154 - 155 - if (w) { 156 - wait_for_completion(&w->c); 157 - mutex_lock(&wq->mu); 158 - list_del(&w->link); 159 - mutex_unlock(&wq->mu); 160 - kfree(w); 161 - } 162 - } 163 - 164 - static void wq_wakeup(struct optee_wait_queue *wq, u32 key) 165 - { 166 - struct wq_entry *w = wq_entry_get(wq, key); 167 - 168 - if (w) 169 - complete(&w->c); 170 - } 171 - 172 147 static void handle_rpc_func_cmd_wq(struct optee *optee, 173 148 struct optee_msg_arg *arg) 174 149 { ··· 138 197 goto bad; 139 198 140 199 switch (arg->params[0].u.value.a) { 141 - case OPTEE_RPC_WAIT_QUEUE_SLEEP: 142 - wq_sleep(&optee->wait_queue, arg->params[0].u.value.b); 200 + case OPTEE_RPC_NOTIFICATION_WAIT: 201 + if (optee_notif_wait(optee, arg->params[0].u.value.b)) 202 + goto bad; 143 203 break; 144 - case OPTEE_RPC_WAIT_QUEUE_WAKEUP: 145 - wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b); 204 + case OPTEE_RPC_NOTIFICATION_SEND: 205 + if (optee_notif_send(optee, arg->params[0].u.value.b)) 206 + goto bad; 146 207 break; 147 208 default: 148 209 goto bad; ··· 262 319 case OPTEE_RPC_CMD_GET_TIME: 263 320 handle_rpc_func_cmd_get_time(arg); 264 321 break; 265 - case OPTEE_RPC_CMD_WAIT_QUEUE: 322 + case OPTEE_RPC_CMD_NOTIFICATION: 266 323 handle_rpc_func_cmd_wq(optee, arg); 267 324 break; 268 325 case OPTEE_RPC_CMD_SUSPEND:
+7 -3
drivers/tee/optee/smc_abi.c
··· 1288 1288 1289 1289 mutex_init(&optee->call_queue.mutex); 1290 1290 INIT_LIST_HEAD(&optee->call_queue.waiters); 1291 - optee_wait_queue_init(&optee->wait_queue); 1292 1291 optee_supp_init(&optee->supp); 1293 1292 optee->smc.memremaped_shm = memremaped_shm; 1294 1293 optee->pool = pool; 1294 + 1295 + platform_set_drvdata(pdev, optee); 1296 + rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE); 1297 + if (rc) { 1298 + optee_remove(pdev); 1299 + return rc; 1300 + } 1295 1301 1296 1302 /* 1297 1303 * Ensure that there are no pre-existing shm objects before enabling ··· 1312 1306 1313 1307 if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) 1314 1308 pr_info("dynamic shared memory is enabled\n"); 1315 - 1316 - platform_set_drvdata(pdev, optee); 1317 1309 1318 1310 rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES); 1319 1311 if (rc) {