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