29
29
*/
30
30
struct test_args {
31
31
uint32_t nr_irqs ; /* number of KVM supported IRQs. */
32
+ bool eoi_split ; /* 1 is eoir+dir, 0 is eoir only */
32
33
};
33
34
34
35
/*
@@ -112,7 +113,7 @@ static uint64_t gic_read_ap1r0(void)
112
113
return reg ;
113
114
}
114
115
115
- static void guest_irq_handler ( struct ex_regs * regs )
116
+ static void guest_irq_generic_handler ( bool eoi_split )
116
117
{
117
118
uint32_t intid = gic_get_and_ack_irq ();
118
119
@@ -129,6 +130,8 @@ static void guest_irq_handler(struct ex_regs *regs)
129
130
130
131
gic_set_eoi (intid );
131
132
GUEST_ASSERT_EQ (gic_read_ap1r0 (), 0 );
133
+ if (eoi_split )
134
+ gic_set_dir (intid );
132
135
133
136
GUEST_ASSERT (!gic_irq_get_active (intid ));
134
137
GUEST_ASSERT (!gic_irq_get_pending (intid ));
@@ -151,6 +154,24 @@ do { \
151
154
GUEST_ASSERT(_intid == 0 || _intid == IAR_SPURIOUS); \
152
155
} while (0)
153
156
157
+ #define CAT_HELPER (a , b ) a ## b
158
+ #define CAT (a , b ) CAT_HELPER(a, b)
159
+ #define PREFIX guest_irq_handler_
160
+ #define GUEST_IRQ_HANDLER_NAME (split ) CAT(PREFIX, split)
161
+ #define GENERATE_GUEST_IRQ_HANDLER (split ) \
162
+ static void CAT(PREFIX, split)(struct ex_regs *regs) \
163
+ { \
164
+ guest_irq_generic_handler(split); \
165
+ }
166
+
167
+ GENERATE_GUEST_IRQ_HANDLER (0 );
168
+ GENERATE_GUEST_IRQ_HANDLER (1 );
169
+
170
+ static void (* guest_irq_handlers [2 ])(struct ex_regs * ) = {
171
+ GUEST_IRQ_HANDLER_NAME (0 ),
172
+ GUEST_IRQ_HANDLER_NAME (1 ),
173
+ };
174
+
154
175
static void reset_priorities (struct test_args * args )
155
176
{
156
177
int i ;
@@ -220,6 +241,8 @@ static void guest_code(struct test_args args)
220
241
for (i = 0 ; i < nr_irqs ; i ++ )
221
242
gic_irq_enable (i );
222
243
244
+ gic_set_eoi_split (args .eoi_split );
245
+
223
246
reset_priorities (& args );
224
247
gic_set_priority_mask (CPU_PRIO_MASK );
225
248
@@ -268,10 +291,11 @@ static void kvm_inject_get_call(struct kvm_vm *vm, struct ucall *uc,
268
291
269
292
static void print_args (struct test_args * args )
270
293
{
271
- printf ("nr-irqs=%d\n" , args -> nr_irqs );
294
+ printf ("nr-irqs=%d eoi-split=%d\n" ,
295
+ args -> nr_irqs , args -> eoi_split );
272
296
}
273
297
274
- static void test_vgic (uint32_t nr_irqs )
298
+ static void test_vgic (uint32_t nr_irqs , bool eoi_split )
275
299
{
276
300
struct ucall uc ;
277
301
int gic_fd ;
@@ -280,6 +304,7 @@ static void test_vgic(uint32_t nr_irqs)
280
304
281
305
struct test_args args = {
282
306
.nr_irqs = nr_irqs ,
307
+ .eoi_split = eoi_split ,
283
308
};
284
309
285
310
print_args (& args );
@@ -297,7 +322,7 @@ static void test_vgic(uint32_t nr_irqs)
297
322
GICD_BASE_GPA , GICR_BASE_GPA );
298
323
299
324
vm_install_exception_handler (vm , VECTOR_IRQ_CURRENT ,
300
- guest_irq_handler );
325
+ guest_irq_handlers [ args . eoi_split ] );
301
326
302
327
while (1 ) {
303
328
vcpu_run (vm , VCPU_ID );
@@ -328,35 +353,52 @@ static void help(const char *name)
328
353
{
329
354
printf (
330
355
"\n"
331
- "usage: %s [-n num_irqs]\n" , name );
332
- printf (" -n: specify the number of IRQs to configure the vgic with.\n" );
356
+ "usage: %s [-n num_irqs] [-e eoi_split]\n" , name );
357
+ printf (" -n: specify the number of IRQs to configure the vgic with. "
358
+ "It has to be a multiple of 32 and between 64 and 1024.\n" );
359
+ printf (" -e: if 1 then EOI is split into a write to DIR on top "
360
+ "of writing EOI.\n" );
333
361
puts ("" );
334
362
exit (1 );
335
363
}
336
364
337
365
int main (int argc , char * * argv )
338
366
{
339
367
uint32_t nr_irqs = 64 ;
368
+ bool default_args = true;
340
369
int opt ;
370
+ bool eoi_split = false;
341
371
342
372
/* Tell stdout not to buffer its content */
343
373
setbuf (stdout , NULL );
344
374
345
- while ((opt = getopt (argc , argv , "hg:n :" )) != -1 ) {
375
+ while ((opt = getopt (argc , argv , "hn:e :" )) != -1 ) {
346
376
switch (opt ) {
347
377
case 'n' :
348
378
nr_irqs = atoi (optarg );
349
379
if (nr_irqs > 1024 || nr_irqs % 32 )
350
380
help (argv [0 ]);
351
381
break ;
382
+ case 'e' :
383
+ eoi_split = (bool )atoi (optarg );
384
+ default_args = false;
385
+ break ;
352
386
case 'h' :
353
387
default :
354
388
help (argv [0 ]);
355
389
break ;
356
390
}
357
391
}
358
392
359
- test_vgic (nr_irqs );
393
+ /* If the user just specified nr_irqs and/or gic_version, then run all
394
+ * combinations.
395
+ */
396
+ if (default_args ) {
397
+ test_vgic (nr_irqs , false /* eoi_split */ );
398
+ test_vgic (nr_irqs , true /* eoi_split */ );
399
+ } else {
400
+ test_vgic (nr_irqs , eoi_split );
401
+ }
360
402
361
403
return 0 ;
362
404
}
0 commit comments