xref: /optee_os/core/kernel/notif_default.c (revision 2e02a7374b864506d2d244e64303b104ca41a05c)
1a2a3dfbcSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2a2a3dfbcSJens Wiklander /*
3a2a3dfbcSJens Wiklander  * Copyright (c) 2021-2023, Linaro Limited
4a2a3dfbcSJens Wiklander  */
5a2a3dfbcSJens Wiklander 
6*2e02a737SJens Wiklander #include <assert.h>
7a2a3dfbcSJens Wiklander #include <bitstring.h>
8*2e02a737SJens Wiklander #include <kernel/interrupt.h>
9a2a3dfbcSJens Wiklander #include <kernel/notif.h>
10a2a3dfbcSJens Wiklander #include <kernel/spinlock.h>
11*2e02a737SJens Wiklander #include <trace.h>
12a2a3dfbcSJens Wiklander #include <types_ext.h>
13a2a3dfbcSJens Wiklander 
14a2a3dfbcSJens Wiklander static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1);
15a2a3dfbcSJens Wiklander static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1);
16a2a3dfbcSJens Wiklander static unsigned int notif_default_lock = SPINLOCK_UNLOCK;
17a2a3dfbcSJens Wiklander 
18a2a3dfbcSJens Wiklander TEE_Result notif_alloc_async_value(uint32_t *val)
19a2a3dfbcSJens Wiklander {
20a2a3dfbcSJens Wiklander 	static bool alloc_values_inited;
21a2a3dfbcSJens Wiklander 	uint32_t old_itr_status = 0;
22a2a3dfbcSJens Wiklander 	int bit = 0;
23a2a3dfbcSJens Wiklander 
24a2a3dfbcSJens Wiklander 	assert(interrupt_can_raise_pi(interrupt_get_main_chip()));
25a2a3dfbcSJens Wiklander 
26a2a3dfbcSJens Wiklander 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
27a2a3dfbcSJens Wiklander 
28a2a3dfbcSJens Wiklander 	if (!alloc_values_inited) {
29a2a3dfbcSJens Wiklander 		bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF);
30a2a3dfbcSJens Wiklander 		alloc_values_inited = true;
31a2a3dfbcSJens Wiklander 	}
32a2a3dfbcSJens Wiklander 
33a2a3dfbcSJens Wiklander 	bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
34a2a3dfbcSJens Wiklander 	if (bit >= 0) {
35a2a3dfbcSJens Wiklander 		*val = bit;
36a2a3dfbcSJens Wiklander 		bit_set(notif_alloc_values, bit);
37a2a3dfbcSJens Wiklander 	}
38a2a3dfbcSJens Wiklander 
39a2a3dfbcSJens Wiklander 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
40a2a3dfbcSJens Wiklander 
41a2a3dfbcSJens Wiklander 	if (bit < 0)
42a2a3dfbcSJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
43a2a3dfbcSJens Wiklander 
44a2a3dfbcSJens Wiklander 	return TEE_SUCCESS;
45a2a3dfbcSJens Wiklander }
46a2a3dfbcSJens Wiklander 
47a2a3dfbcSJens Wiklander void notif_free_async_value(uint32_t val)
48a2a3dfbcSJens Wiklander {
49a2a3dfbcSJens Wiklander 	uint32_t old_itr_status = 0;
50a2a3dfbcSJens Wiklander 
51a2a3dfbcSJens Wiklander 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
52a2a3dfbcSJens Wiklander 
53a2a3dfbcSJens Wiklander 	assert(val < NOTIF_ASYNC_VALUE_MAX);
54a2a3dfbcSJens Wiklander 	assert(bit_test(notif_alloc_values, val));
55a2a3dfbcSJens Wiklander 	bit_clear(notif_alloc_values, val);
56a2a3dfbcSJens Wiklander 
57a2a3dfbcSJens Wiklander 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
58a2a3dfbcSJens Wiklander }
59a2a3dfbcSJens Wiklander 
60a2a3dfbcSJens Wiklander uint32_t notif_get_value(bool *value_valid, bool *value_pending)
61a2a3dfbcSJens Wiklander {
62a2a3dfbcSJens Wiklander 	uint32_t old_itr_status = 0;
63a2a3dfbcSJens Wiklander 	uint32_t res = 0;
64a2a3dfbcSJens Wiklander 	int bit = 0;
65a2a3dfbcSJens Wiklander 
66a2a3dfbcSJens Wiklander 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
67a2a3dfbcSJens Wiklander 
68a2a3dfbcSJens Wiklander 	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
69a2a3dfbcSJens Wiklander 	*value_valid = (bit >= 0);
70a2a3dfbcSJens Wiklander 	if (!*value_valid) {
71a2a3dfbcSJens Wiklander 		*value_pending = false;
72a2a3dfbcSJens Wiklander 		goto out;
73a2a3dfbcSJens Wiklander 	}
74a2a3dfbcSJens Wiklander 
75a2a3dfbcSJens Wiklander 	res = bit;
76a2a3dfbcSJens Wiklander 	bit_clear(notif_values, res);
77a2a3dfbcSJens Wiklander 	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
78a2a3dfbcSJens Wiklander 	*value_pending = (bit >= 0);
79a2a3dfbcSJens Wiklander out:
80a2a3dfbcSJens Wiklander 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
81a2a3dfbcSJens Wiklander 
82a2a3dfbcSJens Wiklander 	return res;
83a2a3dfbcSJens Wiklander }
84a2a3dfbcSJens Wiklander 
85a2a3dfbcSJens Wiklander void notif_send_async(uint32_t value)
86a2a3dfbcSJens Wiklander {
87a2a3dfbcSJens Wiklander 	uint32_t old_itr_status = 0;
88a2a3dfbcSJens Wiklander 	struct itr_chip *itr_chip = interrupt_get_main_chip();
89a2a3dfbcSJens Wiklander 
90a2a3dfbcSJens Wiklander 	assert(value <= NOTIF_ASYNC_VALUE_MAX);
91a2a3dfbcSJens Wiklander 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
92a2a3dfbcSJens Wiklander 
93a2a3dfbcSJens Wiklander 	DMSG("0x%"PRIx32, value);
94a2a3dfbcSJens Wiklander 	bit_set(notif_values, value);
95a2a3dfbcSJens Wiklander 	interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID);
96a2a3dfbcSJens Wiklander 
97a2a3dfbcSJens Wiklander 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
98a2a3dfbcSJens Wiklander }
99