xref: /kvm-unit-tests/x86/ioapic.c (revision 0f187a08902cc2d1a4ddf0ffe45959b0ffa4db8c)
1 #include "libcflat.h"
2 #include "apic.h"
3 #include "vm.h"
4 #include "smp.h"
5 #include "desc.h"
6 #include "isr.h"
7 
8 #define EDGE_TRIGGERED 0
9 #define LEVEL_TRIGGERED 1
10 
11 static void set_ioapic_redir(unsigned line, unsigned vec, unsigned trig_mode)
12 {
13 	ioapic_redir_entry_t e = {
14 		.vector = vec,
15 		.delivery_mode = 0,
16 		.trig_mode = trig_mode,
17 	};
18 
19 	ioapic_write_redir(line, e);
20 }
21 
22 static void set_irq_line(unsigned line, int val)
23 {
24 	asm volatile("out %0, %1" : : "a"((u8)val), "d"((u16)(0x2000 + line)));
25 }
26 
27 static void toggle_irq_line(unsigned line)
28 {
29 	set_irq_line(line, 1);
30 	set_irq_line(line, 0);
31 }
32 
33 static volatile int g_isr_77;
34 
35 static void ioapic_isr_77(isr_regs_t *regs)
36 {
37 	++g_isr_77;
38 	eoi();
39 }
40 
41 static void test_ioapic_intr(void)
42 {
43 	handle_irq(0x77, ioapic_isr_77);
44 	set_ioapic_redir(0x0e, 0x77, EDGE_TRIGGERED);
45 	toggle_irq_line(0x0e);
46 	asm volatile ("nop");
47 	report("ioapic interrupt", g_isr_77 == 1);
48 }
49 
50 static int g_78, g_66, g_66_after_78;
51 static ulong g_66_rip, g_78_rip;
52 
53 static void ioapic_isr_78(isr_regs_t *regs)
54 {
55 	++g_78;
56 	g_78_rip = regs->rip;
57 	eoi();
58 }
59 
60 static void ioapic_isr_66(isr_regs_t *regs)
61 {
62 	++g_66;
63 	if (g_78)
64 		++g_66_after_78;
65 	g_66_rip = regs->rip;
66 	eoi();
67 }
68 
69 static void test_ioapic_simultaneous(void)
70 {
71 	handle_irq(0x78, ioapic_isr_78);
72 	handle_irq(0x66, ioapic_isr_66);
73 	set_ioapic_redir(0x0e, 0x78, EDGE_TRIGGERED);
74 	set_ioapic_redir(0x0f, 0x66, EDGE_TRIGGERED);
75 	irq_disable();
76 	toggle_irq_line(0x0f);
77 	toggle_irq_line(0x0e);
78 	irq_enable();
79 	asm volatile ("nop");
80 	report("ioapic simultaneous interrupt",
81 		g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip);
82 }
83 
84 int main(void)
85 {
86 	setup_vm();
87 	smp_init();
88 	setup_idt();
89 
90 	mask_pic_interrupts();
91 	enable_apic();
92 
93 	irq_enable();
94 
95 	test_ioapic_intr();
96 	test_ioapic_simultaneous();
97 
98 	return report_summary();
99 }
100