12828809eSJens Wiklander /* SPDX-License-Identifier: BSD-2-Clause */ 22828809eSJens Wiklander /* 32828809eSJens Wiklander * Copyright (c) 2021, Linaro Limited 42828809eSJens Wiklander */ 52828809eSJens Wiklander 62828809eSJens Wiklander #ifndef __KERNEL_NOTIF_H 72828809eSJens Wiklander #define __KERNEL_NOTIF_H 82828809eSJens Wiklander 92828809eSJens Wiklander #include <compiler.h> 102828809eSJens Wiklander #include <sys/queue.h> 112828809eSJens Wiklander #include <tee_api_types.h> 122828809eSJens Wiklander #include <types_ext.h> 13c2d44948SJens Wiklander #include <config.h> 142828809eSJens Wiklander 15c2d44948SJens Wiklander /* 16c2d44948SJens Wiklander * Notification values are divided into two kinds, asynchronous and 17c2d44948SJens Wiklander * synchronous, where the asynchronous has the lowest values. 18c2d44948SJens Wiklander * They are ordered as: 19c2d44948SJens Wiklander * 0 Do bottom half 20c2d44948SJens Wiklander * 1..NOTIF_ASYNC_MAX Free for signalling in PTAs and should be 21c2d44948SJens Wiklander * allocated with notif_alloc_async_value() 22c2d44948SJens Wiklander * NOTIF_SYNC_VALUE_BASE.. Used as NOTIF_SYNC_VALUE_BASE + thread_id 23c2d44948SJens Wiklander * NOTIF_VALUE_MAX for mutex and condvar wait/wakeup 24c2d44948SJens Wiklander * 25c2d44948SJens Wiklander * Any value can be signalled with notif_send_sync() while only the ones 26c2d44948SJens Wiklander * <= NOTIF_ASYNC_VALUE_MAX can be signalled with notif_send_async(). 27c2d44948SJens Wiklander */ 28c2d44948SJens Wiklander 29c2d44948SJens Wiklander #if defined(CFG_CORE_ASYNC_NOTIF) 30c2d44948SJens Wiklander #define NOTIF_ASYNC_VALUE_MAX U(63) 31c2d44948SJens Wiklander #define NOTIF_SYNC_VALUE_BASE (NOTIF_ASYNC_VALUE_MAX + U(1)) 32c2d44948SJens Wiklander #else 332828809eSJens Wiklander #define NOTIF_SYNC_VALUE_BASE 0 34c2d44948SJens Wiklander #endif 352828809eSJens Wiklander 362828809eSJens Wiklander #define NOTIF_VALUE_MAX (NOTIF_SYNC_VALUE_BASE + \ 372828809eSJens Wiklander CFG_NUM_THREADS) 382828809eSJens Wiklander 39c2d44948SJens Wiklander #define NOTIF_VALUE_DO_BOTTOM_HALF 0 40c2d44948SJens Wiklander 412828809eSJens Wiklander /* 42c2d44948SJens Wiklander * enum notif_event - Notification of an event 43c2d44948SJens Wiklander * @NOTIF_EVENT_STARTED: Delivered in an atomic context to inform 44c2d44948SJens Wiklander * drivers that normal world has enabled 45c2d44948SJens Wiklander * asynchronous notifications. 46c2d44948SJens Wiklander * @NOTIF_EVENT_DO_BOTTOM_HALF: Delivered in a yielding context to let a 47c2d44948SJens Wiklander * driver do bottom half processing. 48c2d44948SJens Wiklander * @NOTIF_EVENT_STOPPED: Delivered in a yielding contest to inform 49c2d44948SJens Wiklander * drivers that normal world is about to disable 50c2d44948SJens Wiklander * asynchronous notifications. 51c2d44948SJens Wiklander * 52c2d44948SJens Wiklander * Once a driver has received a @NOTIF_EVENT_STARTED asynchronous notifications 53c2d44948SJens Wiklander * driving the @NOTIF_EVENT_DO_BOTTOM_HALF deliveries is enabled. 54c2d44948SJens Wiklander * 55c2d44948SJens Wiklander * In case a @NOTIF_EVENT_STOPPED is received there will be no more 56c2d44948SJens Wiklander * @NOTIF_EVENT_DO_BOTTOM_HALF events delivered, until @NOTIF_EVENT_STARTED 57c2d44948SJens Wiklander * has been delivered again. 58c2d44948SJens Wiklander * 59c2d44948SJens Wiklander * Note that while a @NOTIF_EVENT_STOPPED is being delivered at the same 60c2d44948SJens Wiklander * time may a @NOTIF_EVENT_STARTED be delivered again so a driver is 61c2d44948SJens Wiklander * required to sychronize accesses to its internal state. 62c2d44948SJens Wiklander */ 63c2d44948SJens Wiklander enum notif_event { 64c2d44948SJens Wiklander NOTIF_EVENT_STARTED, 65c2d44948SJens Wiklander NOTIF_EVENT_DO_BOTTOM_HALF, 66c2d44948SJens Wiklander NOTIF_EVENT_STOPPED, 67c2d44948SJens Wiklander }; 68c2d44948SJens Wiklander 69c2d44948SJens Wiklander /* 70c2d44948SJens Wiklander * struct notif_driver - Registration of driver notification 71c2d44948SJens Wiklander * @atomic_cb: A callback called in an atomic context from 72c2d44948SJens Wiklander * notif_deliver_atomic_event(). Currently only used to 73c2d44948SJens Wiklander * signal @NOTIF_EVENT_STARTED. 74c2d44948SJens Wiklander * @yielding_cb: A callback called in a yielding context from 75c2d44948SJens Wiklander * notif_deliver_event(). Currently only used to signal 76c2d44948SJens Wiklander * @NOTIF_EVENT_DO_BOTTOM_HALF and @NOTIF_EVENT_STOPPED. 77c2d44948SJens Wiklander * 78c2d44948SJens Wiklander * A atomic context means that interrupts are masked and a common spinlock 79c2d44948SJens Wiklander * is held. Calls via @atomic_cb are only atomic with regards to each 80c2d44948SJens Wiklander * other, other CPUs may execute yielding calls or even receive interrupts. 81c2d44948SJens Wiklander * 82c2d44948SJens Wiklander * A yielding context means that the function is executing in a normal 83c2d44948SJens Wiklander * threaded context allowing RPC and synchronization with other thread 84c2d44948SJens Wiklander * using mutexes and condition variables. 85c2d44948SJens Wiklander */ 86c2d44948SJens Wiklander struct notif_driver { 87c2d44948SJens Wiklander void (*atomic_cb)(struct notif_driver *ndrv, enum notif_event ev); 88c2d44948SJens Wiklander void (*yielding_cb)(struct notif_driver *ndrv, enum notif_event ev); 89c2d44948SJens Wiklander SLIST_ENTRY(notif_driver) link; 90c2d44948SJens Wiklander }; 91c2d44948SJens Wiklander 92c2d44948SJens Wiklander #if defined(CFG_CORE_ASYNC_NOTIF) 93c2d44948SJens Wiklander bool notif_async_is_started(void); 94c2d44948SJens Wiklander #else 95c2d44948SJens Wiklander static inline bool notif_async_is_started(void) 96c2d44948SJens Wiklander { 97c2d44948SJens Wiklander return false; 98c2d44948SJens Wiklander } 99c2d44948SJens Wiklander #endif 100c2d44948SJens Wiklander 101c2d44948SJens Wiklander TEE_Result notif_alloc_async_value(uint32_t *value); 102c2d44948SJens Wiklander void notif_free_async_value(uint32_t value); 103c2d44948SJens Wiklander 104c2d44948SJens Wiklander /* 105c2d44948SJens Wiklander * Wait in normal world for a value to be sent by notif_send() 1062828809eSJens Wiklander */ 1072828809eSJens Wiklander TEE_Result notif_wait(uint32_t value); 1082828809eSJens Wiklander 1092828809eSJens Wiklander /* 110*450f8adaSGavin Liu * Wait timeout in normal world for a value to be sent by notif_send() 111*450f8adaSGavin Liu */ 112*450f8adaSGavin Liu TEE_Result notif_wait_timeout(uint32_t value, uint32_t timeout_ms); 113*450f8adaSGavin Liu 114*450f8adaSGavin Liu /* 115c2d44948SJens Wiklander * Send an asynchronous value, note that it must be <= NOTIF_ASYNC_VALUE_MAX 116c2d44948SJens Wiklander */ 117c2d44948SJens Wiklander #if defined(CFG_CORE_ASYNC_NOTIF) 118c2d44948SJens Wiklander void notif_send_async(uint32_t value); 119c2d44948SJens Wiklander #else 120c2d44948SJens Wiklander static inline void notif_send_async(uint32_t value __unused) 121c2d44948SJens Wiklander { 122c2d44948SJens Wiklander } 123c2d44948SJens Wiklander #endif 124c2d44948SJens Wiklander 125c2d44948SJens Wiklander /* 126c2d44948SJens Wiklander * Send a sychronous value, note that it must be <= NOTIF_VALUE_MAX. The 127c2d44948SJens Wiklander * notification is synchronous even if the value happens to belong in the 128c2d44948SJens Wiklander * asynchronous range. 1292828809eSJens Wiklander */ 1302828809eSJens Wiklander TEE_Result notif_send_sync(uint32_t value); 1312828809eSJens Wiklander 132c2d44948SJens Wiklander /* 133c2d44948SJens Wiklander * Called by device drivers. 134c2d44948SJens Wiklander */ 135c2d44948SJens Wiklander #if defined(CFG_CORE_ASYNC_NOTIF) 136c2d44948SJens Wiklander void notif_register_driver(struct notif_driver *ndrv); 137c2d44948SJens Wiklander void notif_unregister_driver(struct notif_driver *ndrv); 138c2d44948SJens Wiklander #else 139c2d44948SJens Wiklander static inline void notif_register_driver(struct notif_driver *ndrv __unused) 140c2d44948SJens Wiklander { 141c2d44948SJens Wiklander } 142c2d44948SJens Wiklander 143c2d44948SJens Wiklander static inline void notif_unregister_driver(struct notif_driver *ndrv __unused) 144c2d44948SJens Wiklander { 145c2d44948SJens Wiklander } 146c2d44948SJens Wiklander #endif 147c2d44948SJens Wiklander 148c2d44948SJens Wiklander /* This is called from a fast call */ 149c2d44948SJens Wiklander #if defined(CFG_CORE_ASYNC_NOTIF) 150c2d44948SJens Wiklander uint32_t notif_get_value(bool *value_valid, bool *value_pending); 151c2d44948SJens Wiklander #else 152c2d44948SJens Wiklander static inline uint32_t notif_get_value(bool *value_valid, bool *value_pending) 153c2d44948SJens Wiklander { 154c2d44948SJens Wiklander *value_valid = false; 155c2d44948SJens Wiklander *value_pending = false; 156c2d44948SJens Wiklander return UINT32_MAX; 157c2d44948SJens Wiklander } 158c2d44948SJens Wiklander #endif 159c2d44948SJens Wiklander 160c2d44948SJens Wiklander /* 161c2d44948SJens Wiklander * These are called from yielding calls 162c2d44948SJens Wiklander */ 163c2d44948SJens Wiklander #if defined(CFG_CORE_ASYNC_NOTIF) 164c2d44948SJens Wiklander void notif_deliver_atomic_event(enum notif_event ev); 165c2d44948SJens Wiklander void notif_deliver_event(enum notif_event ev); 166c2d44948SJens Wiklander #else 167c2d44948SJens Wiklander static inline void notif_deliver_atomic_event(enum notif_event ev __unused) 168c2d44948SJens Wiklander { 169c2d44948SJens Wiklander } 170c2d44948SJens Wiklander 171c2d44948SJens Wiklander static inline void notif_deliver_event(enum notif_event ev __unused) 172c2d44948SJens Wiklander { 173c2d44948SJens Wiklander } 174c2d44948SJens Wiklander #endif 175c2d44948SJens Wiklander 1762828809eSJens Wiklander #endif /*__KERNEL_NOTIF_H*/ 177