xref: /optee_os/core/include/kernel/notif.h (revision 450f8ada92af73d9909324da8e1c26f40233ad64)
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