x86: Split APIC tests into IOAPIC/APIC tests
PATCH 1/2 x86: Split APIC tests into IOAPIC/APIC tests
Split apart the APIC tests into constituent parts (IOAPIC and APIC tests).
Signed-off-by Steve Rutherford <[email protected]>
--- config/config-x86-common.mak | 2 + config/config-x86_64.mak | 1 + lib/x86/apic.c | 29 +++++++++++++ lib/x86/apic.h | 6 +++ x86/apic.c | 80 ----------------------------------- x86/eventinj.c | 5 --- x86/ioapic.c | 99 ++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 5 +++ 8 files changed, 142 insertions(+), 85 deletions(-) create mode 100644 x86/ioapic.c
config/config-x86-common.mak +2 -0
@@ -69,6 +69,8 @@ $(TEST_DIR)/tsc_adjust.elf: $(cstart.o) $(TEST_DIR)/tsc_adjust.o $(TEST_DIR)/apic.elf: $(cstart.o) $(TEST_DIR)/apic.o +$(TEST_DIR)/ioapic.elf: $(cstart.o) $(TEST_DIR)/ioapic.o + $(TEST_DIR)/tscdeadline_latency.elf: $(cstart.o) $(TEST_DIR)/tscdeadline_latency.o $(TEST_DIR)/init.elf: $(cstart.o) $(TEST_DIR)/init.o
config/config-x86_64.mak +1 -0
@@ -10,5 +10,6 @@ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ tests += $(TEST_DIR)/svm.flat tests += $(TEST_DIR)/vmx.flat tests += $(TEST_DIR)/tscdeadline_latency.flat +tests += $(TEST_DIR)/ioapic.flat include config/config-x86-common.mak
lib/x86/apic.c +29 -0
@@ -17,6 +17,11 @@ static void outb(unsigned char data, unsigned short port) asmvolatile ("out %0, %1" : :"a" (data),"d" (port)); } +void eoi (void ) +{ +apic_write (APIC_EOI ,0 ); +} +static u32 xapic_read (unsigned reg) {return *(volatile u32 *)(g_apic + reg);
@@ -117,6 +122,12 @@ int enable_x2apic(void) } } +u32 ioapic_read_reg (unsigned reg) +{ + *(volatile u32 *)g_ioapic = reg; +return *(volatile u32 *)(g_ioapic +0x10 ); +} +void ioapic_write_reg (unsigned reg,u32 value) { *(volatile u32 *)g_ioapic = reg;
@@ -129,6 +140,24 @@ void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e)ioapic_write_reg (0x10 + line *2 +1 , ((u32 *)&e)[1 ]); } +ioapic_redir_entry_t ioapic_read_redir (unsigned line) +{ +ioapic_redir_entry_t e; + + ((u32 *)&e)[0 ] =ioapic_read_reg (0x10 + line *2 +0 ); + ((u32 *)&e)[1 ] =ioapic_read_reg (0x10 + line *2 +1 ); +return e; + +} + +void set_mask (unsigned line,int mask) +{ +ioapic_redir_entry_t e =ioapic_read_redir (line); + + e.mask = mask; +ioapic_write_redir (line, e); +} +void enable_apic (void ) {printf ("enabling apic\n" );
lib/x86/apic.h +6 -0
@@ -20,8 +20,14 @@ typedef struct {void mask_pic_interrupts (void ); +void eoi (void ); +void ioapic_write_redir (unsigned line,ioapic_redir_entry_t e);void ioapic_write_reg (unsigned reg,uint32_t value); +ioapic_redir_entry_t ioapic_read_redir (unsigned line); +uint32_t ioapic_read_reg (unsigned reg); + +void set_mask (unsigned line,int mask);void enable_apic (void );uint32_t apic_read (unsigned reg);
x86/apic.c +0 -80
98 lines not on this page · raw message
x86/eventinj.c +0 -5
@@ -32,11 +32,6 @@ void apic_self_nmi(void)apic_icr_write (APIC_DEST_PHYSICAL |APIC_DM_NMI |APIC_INT_ASSERT ,0 ); } -static void eoi (void ) -{ -apic_write (APIC_EOI ,0 ); -} -#define flush_phys_addr (__s) outl(0xe4, __s)#define flush_stack () do { \ int __l; \
x86/ioapic.c new file +99 -0
99 lines not on this page · raw message
x86/unittests.cfg +5 -0
@@ -12,6 +12,11 @@ smp = 2 extra_params = -cpu qemu64,+x2apic,+tsc-deadline arch = x86_64 +[ioapic] +file = ioapic.flat +extra_params = -cpu qemu64 +arch = x86_64 + [smptest] file = smptest.flat smp = 2
Signature · 1 line
2.2.0.rc0.207.ga3a616c
PATCH 2/2 x86: extend IOAPIC tests
Add tests for fundamental behaviors of the IOAPIC:
Edge & level triggered interrupts Level triggered interrupt coalescing Level triggered EOIs
Interrupt masking
Passes with most recent version of KVM on Intel x86.
Signed-off-by Steve Rutherford <[email protected]>
--- config/config-x86_64.mak | 4 +- x86/ioapic.c | 186 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 181 insertions(+), 9 deletions(-)
config/config-x86_64.mak +2 -2
@@ -6,10 +6,10 @@ CFLAGS += -mno-red-zone tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \ $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \ - $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat + $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \ + $(TEST_DIR)/ioapic.flat tests += $(TEST_DIR)/svm.flat tests += $(TEST_DIR)/vmx.flat tests += $(TEST_DIR)/tscdeadline_latency.flat -tests += $(TEST_DIR)/ioapic.flat include config/config-x86-common.mak
x86/ioapic.c +179 -7
218 lines not on this page · raw message
Signature · 1 line
2.2.0.rc0.207.ga3a616c
Paolo Bonzini
maintainerQuoted 345 lines · Steve Rutherford
Split apart the APIC tests into constituent parts (IOAPIC and APIC tests).
Signed-off-by Steve Rutherford <[email protected]>--- config/config-x86-common.mak | 2 + config/config-x86_64.mak | 1 + lib/x86/apic.c | 29 +++++++++++++ lib/x86/apic.h | 6 +++ x86/apic.c | 80 ----------------------------------- x86/eventinj.c | 5 --- x86/ioapic.c | 99 ++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 5 +++ 8 files changed, 142 insertions(+), 85 deletions(-) create mode 100644 x86/ioapic.cconfig/config-x86-common.mak +2
-0@@ -69,6 +69,8 @@ $(TEST_DIR)/tsc_adjust.elf: $(cstart.o) $(TEST_DIR)/tsc_adjust.o $(TEST_DIR)/apic.elf: $(cstart.o) $(TEST_DIR)/apic.o +$(TEST_DIR)/ioapic.elf: $(cstart.o) $(TEST_DIR)/ioapic.o + $(TEST_DIR)/tscdeadline_latency.elf: $(cstart.o) $(TEST_DIR)/tscdeadline_latency.o $(TEST_DIR)/init.elf: $(cstart.o) $(TEST_DIR)/init.oconfig/config-x86_64.mak +1
-0@@ -10,5 +10,6 @@ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ tests += $(TEST_DIR)/svm.flat tests += $(TEST_DIR)/vmx.flat tests += $(TEST_DIR)/tscdeadline_latency.flat +tests += $(TEST_DIR)/ioapic.flat include config/config-x86-common.maklib/x86/apic.c +29
-0@@ -17,6 +17,11 @@ static void outb(unsigned char data, unsigned short port) asmvolatile ("out %0, %1" : :"a" (data),"d" (port)); } +void eoi (void ) +{ +apic_write (APIC_EOI ,0 ); +} +static u32 xapic_read (unsigned reg) {return *(volatile u32 *)(g_apic + reg);@@ -117,6 +122,12 @@ int enable_x2apic(void) } } +u32 ioapic_read_reg (unsigned reg) +{ + *(volatile u32 *)g_ioapic = reg; +return *(volatile u32 *)(g_ioapic +0x10 ); +} +void ioapic_write_reg (unsigned reg,u32 value) { *(volatile u32 *)g_ioapic = reg;@@ -129,6 +140,24 @@ void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e)ioapic_write_reg (0x10 + line *2 +1 , ((u32 *)&e)[1 ]); } +ioapic_redir_entry_t ioapic_read_redir (unsigned line) +{ +ioapic_redir_entry_t e; + + ((u32 *)&e)[0 ] =ioapic_read_reg (0x10 + line *2 +0 ); + ((u32 *)&e)[1 ] =ioapic_read_reg (0x10 + line *2 +1 ); +return e; + +} + +void set_mask (unsigned line,int mask) +{ +ioapic_redir_entry_t e =ioapic_read_redir (line); + + e.mask = mask; +ioapic_write_redir (line, e); +} +void enable_apic (void ) {printf ("enabling apic\n" );lib/x86/apic.h +6
-0@@ -20,8 +20,14 @@ typedef struct {void mask_pic_interrupts (void ); +void eoi (void ); +void ioapic_write_redir (unsigned line,ioapic_redir_entry_t e);void ioapic_write_reg (unsigned reg,uint32_t value); +ioapic_redir_entry_t ioapic_read_redir (unsigned line); +uint32_t ioapic_read_reg (unsigned reg); + +void set_mask (unsigned line,int mask);void enable_apic (void );uint32_t apic_read (unsigned reg);x86/apic.c +0
-80@@ -140,11 +140,6 @@ static void test_apicbase(void)report_prefix_pop (); } -static void eoi (void ) -{ -apic_write (APIC_EOI ,0 ); -} -static int ipi_count;static void self_ipi_isr (isr_regs_t *regs)@@ -165,79 +160,6 @@ static void test_self_ipi(void)report ("self ipi" , ipi_count ==1 ); } -static void set_ioapic_redir (unsigned line,unsigned vec) -{ -ioapic_redir_entry_t e = { - .vector = vec, - .delivery_mode =0 , - .trig_mode =0 , - }; - -ioapic_write_redir (line, e); -} - -static void set_irq_line (unsigned line,int val) -{ - asmvolatile ("out %0, %1" : :"a" ((u8 )val),"d" ((u16)(0x2000 + line))); -} - -static void toggle_irq_line (unsigned line) -{ -set_irq_line (line,1 ); -set_irq_line (line,0 ); -} - -static int g_isr_77; - -static void ioapic_isr_77 (isr_regs_t *regs) -{ - ++g_isr_77; -eoi (); -} - -static void test_ioapic_intr (void ) -{ -handle_irq (0x77 , ioapic_isr_77); -set_ioapic_redir (0x0e ,0x77 ); -toggle_irq_line (0x0e ); - asmvolatile ("nop" ); -report ("ioapic interrupt" , g_isr_77 ==1 ); -} - -static int g_78, g_66, g_66_after_78; -static ulong g_66_rip, g_78_rip; - -static void ioapic_isr_78 (isr_regs_t *regs) -{ - ++g_78; - g_78_rip = regs->rip; -eoi (); -} - -static void ioapic_isr_66 (isr_regs_t *regs) -{ - ++g_66; -if (g_78) - ++g_66_after_78; - g_66_rip = regs->rip; -eoi (); -} - -static void test_ioapic_simultaneous (void ) -{ -handle_irq (0x78 , ioapic_isr_78); -handle_irq (0x66 , ioapic_isr_66); -set_ioapic_redir (0x0e ,0x78 ); -set_ioapic_redir (0x0f ,0x66 ); -irq_disable (); -toggle_irq_line (0x0f ); -toggle_irq_line (0x0e ); -irq_enable (); - asmvolatile ("nop" ); -report ("ioapic simultaneous interrupt" , - g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip); -} -volatile int nmi_counter_private, nmi_counter, nmi_hlt_counter, sti_loop_active;void sti_nop (char *p)@@ -390,8 +312,6 @@ int main()test_self_ipi (); -test_ioapic_intr (); -test_ioapic_simultaneous ();test_sti_nmi ();test_multiple_nmi ();x86/eventinj.c +0
-5@@ -32,11 +32,6 @@ void apic_self_nmi(void)apic_icr_write (APIC_DEST_PHYSICAL |APIC_DM_NMI |APIC_INT_ASSERT ,0 ); } -static void eoi (void ) -{ -apic_write (APIC_EOI ,0 ); -} -#define flush_phys_addr (__s) outl(0xe4, __s)#define flush_stack () do { \ int __l; \x86/ioapic.c new file +99
-0@@ -0,0 +1,99 @@ +#include "libcflat.h" +#include "apic.h" +#include "vm.h" +#include "smp.h" +#include "desc.h" +#include "isr.h" + +#define EDGE_TRIGGERED 0 +#define LEVEL_TRIGGERED 1 + +static void set_ioapic_redir (unsigned line,unsigned vec,unsigned trig_mode) +{ +ioapic_redir_entry_t e = { + .vector = vec, + .delivery_mode =0 , + .trig_mode = trig_mode, + }; + +ioapic_write_redir (line, e); +} + +static void set_irq_line (unsigned line,int val) +{ + asmvolatile ("out %0, %1" : :"a" ((u8 )val),"d" ((u16)(0x2000 + line))); +} + +static void toggle_irq_line (unsigned line) +{ +set_irq_line (line,1 ); +set_irq_line (line,0 ); +} + +static volatile int g_isr_77; + +static void ioapic_isr_77 (isr_regs_t *regs) +{ + ++g_isr_77; +eoi (); +} + +static void test_ioapic_intr (void ) +{ +handle_irq (0x77 , ioapic_isr_77); +set_ioapic_redir (0x0e ,0x77 ,EDGE_TRIGGERED ); +toggle_irq_line (0x0e ); + asmvolatile ("nop" ); +report ("ioapic interrupt" , g_isr_77 ==1 ); +} + +static int g_78, g_66, g_66_after_78; +static ulong g_66_rip, g_78_rip; + +static void ioapic_isr_78 (isr_regs_t *regs) +{ + ++g_78; + g_78_rip = regs->rip; +eoi (); +} + +static void ioapic_isr_66 (isr_regs_t *regs) +{ + ++g_66; +if (g_78) + ++g_66_after_78; + g_66_rip = regs->rip; +eoi (); +} + +static void test_ioapic_simultaneous (void ) +{ +handle_irq (0x78 , ioapic_isr_78); +handle_irq (0x66 , ioapic_isr_66); +set_ioapic_redir (0x0e ,0x78 ,EDGE_TRIGGERED ); +set_ioapic_redir (0x0f ,0x66 ,EDGE_TRIGGERED ); +irq_disable (); +toggle_irq_line (0x0f ); +toggle_irq_line (0x0e ); +irq_enable (); + asmvolatile ("nop" ); +report ("ioapic simultaneous interrupt" , + g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip); +} + +int main (void ) +{ +setup_vm (); +smp_init (); +setup_idt (); + +mask_pic_interrupts (); +enable_apic (); + +irq_enable (); + +test_ioapic_intr (); +test_ioapic_simultaneous (); + +return report_summary (); +}x86/unittests.cfg +0
-0@@ -12,6 +12,11 @@ smp = 2 extra_params = -cpu qemu64,+x2apic,+tsc-deadline
x86/unittests.cfg smp = 2 · line 22
Quoted 10 lines
x86/unittests.cfg +5
-0arch = x86_64 +[ioapic] +file = ioapic.flat +extra_params = -cpu qemu64 +arch = x86_64 + [smptest] file = smptest.flat smp = 2
Applying these two, thanks!
Paolo