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