8
8
#include <softirq.h>
9
9
#include <ptdev.h>
10
10
11
- /* passthrough device link */
12
- struct list_head ptdev_list ;
11
+ #define PTDEV_BITMAP_ARRAY_SIZE INT_DIV_ROUNDUP(CONFIG_MAX_PT_IRQ_ENTRIES, 64U)
12
+ struct ptdev_remapping_info ptdev_irq_entries [CONFIG_MAX_PT_IRQ_ENTRIES ];
13
+ static uint64_t ptdev_entry_bitmaps [PTDEV_BITMAP_ARRAY_SIZE ];
14
+
13
15
spinlock_t ptdev_lock ;
14
16
15
- /*
16
- * entry could both be in ptdev_list and vm->softirq_dev_entry_list.
17
- * When release entry, we need make sure entry deleted from both
18
- * lists. We have to require two locks and the lock sequence is:
19
- * ptdev_lock
20
- * vm->softirq_dev_lock
21
- */
17
+ bool is_entry_active (const struct ptdev_remapping_info * entry )
18
+ {
19
+ return atomic_load32 (& entry -> active ) == ACTIVE_FLAG ;
20
+ }
21
+
22
+ static inline uint16_t alloc_ptdev_entry_id (void )
23
+ {
24
+ uint16_t id = (uint16_t )ffz64_ex (ptdev_entry_bitmaps , CONFIG_MAX_PT_IRQ_ENTRIES );
25
+
26
+ while (id < CONFIG_MAX_PT_IRQ_ENTRIES ) {
27
+ if (!bitmap_test_and_set_lock ((id & 0x3FU ), & ptdev_entry_bitmaps [id >> 6U ])) {
28
+ return id ;
29
+ }
30
+ id = (uint16_t )ffz64_ex (ptdev_entry_bitmaps , CONFIG_MAX_PT_IRQ_ENTRIES );
31
+ }
32
+
33
+ return INVALID_PTDEV_ENTRY_ID ;
34
+ }
22
35
23
36
static void ptdev_enqueue_softirq (struct ptdev_remapping_info * entry )
24
37
{
@@ -78,22 +91,26 @@ struct ptdev_remapping_info *
78
91
alloc_entry (struct acrn_vm * vm , uint32_t intr_type )
79
92
{
80
93
struct ptdev_remapping_info * entry ;
94
+ uint16_t ptdev_id = alloc_ptdev_entry_id ();
81
95
82
- /* allocate */
83
- entry = calloc (1U , sizeof (* entry ));
84
- ASSERT (entry != NULL , "alloc memory failed" );
96
+ if (ptdev_id >= CONFIG_MAX_PT_IRQ_ENTRIES ) {
97
+ pr_err ("Alloc ptdev irq entry failed" );
98
+ return NULL ;
99
+ }
100
+
101
+ entry = & ptdev_irq_entries [ptdev_id ];
102
+ (void )memset ((void * )entry , 0U , sizeof (struct ptdev_remapping_info ));
103
+ entry -> ptdev_entry_id = ptdev_id ;
85
104
entry -> intr_type = intr_type ;
86
105
entry -> vm = vm ;
106
+ entry -> intr_count = 0UL ;
87
107
88
108
INIT_LIST_HEAD (& entry -> softirq_node );
89
- INIT_LIST_HEAD (& entry -> entry_node );
90
109
91
- entry -> intr_count = 0UL ;
92
110
initialize_timer (& entry -> intr_delay_timer , ptdev_intr_delay_callback ,
93
111
entry , 0UL , 0 , 0UL );
94
112
95
113
atomic_clear32 (& entry -> active , ACTIVE_FLAG );
96
- list_add (& entry -> entry_node , & ptdev_list );
97
114
98
115
return entry ;
99
116
}
@@ -104,30 +121,26 @@ release_entry(struct ptdev_remapping_info *entry)
104
121
{
105
122
uint64_t rflags ;
106
123
107
- /* remove entry from ptdev_list */
108
- list_del_init (& entry -> entry_node );
109
-
110
124
/*
111
125
* remove entry from softirq list.the ptdev_lock
112
126
* is required before calling release_entry.
113
127
*/
114
128
spinlock_irqsave_obtain (& entry -> vm -> softirq_dev_lock , & rflags );
115
129
list_del_init (& entry -> softirq_node );
116
130
spinlock_irqrestore_release (& entry -> vm -> softirq_dev_lock , rflags );
117
-
118
- free ( entry );
131
+ atomic_clear32 ( & entry -> active , ACTIVE_FLAG );
132
+ bitmap_clear_nolock (( entry -> ptdev_entry_id ) & 0x3FU , & ptdev_entry_bitmaps [( entry -> ptdev_entry_id ) >> 6U ] );
119
133
}
120
134
121
135
/* require ptdev_lock protect */
122
136
static void
123
137
release_all_entries (const struct acrn_vm * vm )
124
138
{
125
139
struct ptdev_remapping_info * entry ;
126
- struct list_head * pos , * tmp ;
140
+ uint16_t idx ;
127
141
128
- list_for_each_safe (pos , tmp , & ptdev_list ) {
129
- entry = list_entry (pos , struct ptdev_remapping_info ,
130
- entry_node );
142
+ for (idx = 0U ; idx < CONFIG_MAX_PT_IRQ_ENTRIES ; idx ++ ) {
143
+ entry = & ptdev_irq_entries [idx ];
131
144
if (entry -> vm == vm ) {
132
145
release_entry (entry );
133
146
}
@@ -200,7 +213,6 @@ void ptdev_init(void)
200
213
return ;
201
214
}
202
215
203
- INIT_LIST_HEAD (& ptdev_list );
204
216
spinlock_init (& ptdev_lock );
205
217
206
218
register_softirq (SOFTIRQ_PTDEV , ptdev_softirq );
@@ -218,12 +230,14 @@ uint32_t get_vm_ptdev_intr_data(const struct acrn_vm *target_vm, uint64_t *buffe
218
230
uint32_t buffer_cnt )
219
231
{
220
232
uint32_t index = 0U ;
233
+ uint16_t i ;
221
234
struct ptdev_remapping_info * entry ;
222
- struct list_head * pos , * tmp ;
223
235
224
- list_for_each_safe (pos , tmp , & ptdev_list ) {
225
- entry = list_entry (pos , struct ptdev_remapping_info ,
226
- entry_node );
236
+ for (i = 0U ; i < CONFIG_MAX_PT_IRQ_ENTRIES ; i ++ ) {
237
+ entry = & ptdev_irq_entries [i ];
238
+ if (!is_entry_active (entry )) {
239
+ continue ;
240
+ }
227
241
if (entry -> vm == target_vm ) {
228
242
buffer [index ] = entry -> allocated_pirq ;
229
243
buffer [index + 1U ] = entry -> intr_count ;
0 commit comments