All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests
@ 2015-05-13  1:55 Steve Rutherford
  2015-05-13  1:55 ` [PATCH 2/2] x86: extend IOAPIC tests Steve Rutherford
  2015-05-13  8:07 ` [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests Paolo Bonzini
  0 siblings, 2 replies; 3+ messages in thread
From: Steve Rutherford @ 2015-05-13  1:55 UTC (permalink / raw)
  To: kvm

Split apart the APIC tests into constituent parts (IOAPIC and APIC tests).

Signed-off-by: Steve Rutherford <srutherford@google.com>
---
 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

diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
index 8fc3490..d45c9a8 100644
--- a/config/config-x86-common.mak
+++ b/config/config-x86-common.mak
@@ -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
diff --git a/config/config-x86_64.mak b/config/config-x86_64.mak
index d62c1e9..dfdeed6 100644
--- a/config/config-x86_64.mak
+++ b/config/config-x86_64.mak
@@ -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
diff --git a/lib/x86/apic.c b/lib/x86/apic.c
index 9c42c4d..80b96d8 100644
--- a/lib/x86/apic.c
+++ b/lib/x86/apic.c
@@ -17,6 +17,11 @@ static void outb(unsigned char data, unsigned short port)
     asm volatile ("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");
diff --git a/lib/x86/apic.h b/lib/x86/apic.h
index e325e9a..216b98d 100644
--- a/lib/x86/apic.h
+++ b/lib/x86/apic.h
@@ -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);
diff --git a/x86/apic.c b/x86/apic.c
index 365c281..d4eec52 100644
--- a/x86/apic.c
+++ b/x86/apic.c
@@ -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)
-{
-    asm volatile("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);
-    asm volatile ("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();
-    asm volatile ("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();
 
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 32de6f0..bddedce 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -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;						\
diff --git a/x86/ioapic.c b/x86/ioapic.c
new file mode 100644
index 0000000..2afdaa2
--- /dev/null
+++ b/x86/ioapic.c
@@ -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)
+{
+	asm volatile("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);
+	asm volatile ("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();
+	asm volatile ("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();
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index badb08a..a38544f 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -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
-- 
2.2.0.rc0.207.ga3a616c


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] x86: extend IOAPIC tests
  2015-05-13  1:55 [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests Steve Rutherford
@ 2015-05-13  1:55 ` Steve Rutherford
  2015-05-13  8:07 ` [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests Paolo Bonzini
  1 sibling, 0 replies; 3+ messages in thread
From: Steve Rutherford @ 2015-05-13  1:55 UTC (permalink / raw)
  To: kvm

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 <srutherford@google.com>
---
 config/config-x86_64.mak |   4 +-
 x86/ioapic.c             | 186 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 181 insertions(+), 9 deletions(-)

diff --git a/config/config-x86_64.mak b/config/config-x86_64.mak
index dfdeed6..7d4eb34 100644
--- a/config/config-x86_64.mak
+++ b/config/config-x86_64.mak
@@ -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
diff --git a/x86/ioapic.c b/x86/ioapic.c
index 2afdaa2..1fcf67e 100644
--- a/x86/ioapic.c
+++ b/x86/ioapic.c
@@ -30,21 +30,87 @@ static void toggle_irq_line(unsigned line)
 	set_irq_line(line, 0);
 }
 
+static void ioapic_reg_version(void)
+{
+	u8 version_offset;
+	uint32_t data_read, data_write;
+
+	version_offset = 0x01;
+	data_read = ioapic_read_reg(version_offset);
+	data_write = data_read ^ 0xffffffff;
+
+	ioapic_write_reg(version_offset, data_write);
+	report("version register read only test",
+	       data_read == ioapic_read_reg(version_offset));
+}
+
+static void ioapic_reg_id(void)
+{
+	u8 id_offset;
+	uint32_t data_read, data_write, diff;
+
+	id_offset = 0x0;
+	data_read = ioapic_read_reg(id_offset);
+	data_write = data_read ^ 0xffffffff;
+
+	ioapic_write_reg(id_offset, data_write);
+
+	diff = data_read ^ ioapic_read_reg(id_offset);
+	report("id register only bits [24:27] writable",
+	       diff == 0x0f000000);
+}
+
+static void ioapic_arbitration_id(void)
+{
+	u8 id_offset, arb_offset;
+	uint32_t write;
+
+	id_offset = 0x0;
+	arb_offset = 0x2;
+	write = 0x0f000000;
+
+	ioapic_write_reg(id_offset, write);
+	report("arbitration register set by id",
+	       ioapic_read_reg(arb_offset) == write);
+
+	ioapic_write_reg(arb_offset, 0x0);
+	report("arbtration register read only",
+               ioapic_read_reg(arb_offset) == write);
+}
+
+static volatile int g_isr_76;
+
+static void ioapic_isr_76(isr_regs_t *regs)
+{
+	++g_isr_76;
+	eoi();
+}
+
+static void test_ioapic_edge_intr(void)
+{
+	handle_irq(0x76, ioapic_isr_76);
+	set_ioapic_redir(0x0e, 0x76, EDGE_TRIGGERED);
+	toggle_irq_line(0x0e);
+	asm volatile ("nop");
+	report("edge triggered intr", g_isr_76 == 1);
+}
+
 static volatile int g_isr_77;
 
 static void ioapic_isr_77(isr_regs_t *regs)
 {
 	++g_isr_77;
+	set_irq_line(0x0e, 0);
 	eoi();
 }
 
-static void test_ioapic_intr(void)
+static void test_ioapic_level_intr(void)
 {
 	handle_irq(0x77, ioapic_isr_77);
-	set_ioapic_redir(0x0e, 0x77, EDGE_TRIGGERED);
-	toggle_irq_line(0x0e);
+	set_ioapic_redir(0x0e, 0x77, LEVEL_TRIGGERED);
+	set_irq_line(0x0e, 1);
 	asm volatile ("nop");
-	report("ioapic interrupt", g_isr_77 == 1);
+	report("level triggered intr", g_isr_77 == 1);
 }
 
 static int g_78, g_66, g_66_after_78;
@@ -77,10 +143,106 @@ static void test_ioapic_simultaneous(void)
 	toggle_irq_line(0x0e);
 	irq_enable();
 	asm volatile ("nop");
-	report("ioapic simultaneous interrupt",
-		g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip);
+	report("ioapic simultaneous edge interrupts",
+	       g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip);
 }
 
+static int g_isr_98;
+
+static void ioapic_isr_98(isr_regs_t *regs)
+{
+	++g_isr_98;
+	if (g_isr_98 == 1) {
+		set_irq_line(0x0e, 0);
+		set_irq_line(0x0e, 1);
+	}
+	set_irq_line(0x0e, 0);
+	eoi();
+}
+
+static void test_ioapic_level_coalesce(void)
+{
+	handle_irq(0x98, ioapic_isr_98);
+	set_ioapic_redir(0x0e, 0x98, LEVEL_TRIGGERED);
+	set_irq_line(0x0e, 1);
+	asm volatile ("nop");
+	report("coalesce simultaneous level interrupts", g_isr_98 == 1);
+}
+
+static int g_isr_99;
+
+static void ioapic_isr_99(isr_regs_t *regs)
+{
+	++g_isr_99;
+	set_irq_line(0x0e, 0);
+	eoi();
+}
+
+static void test_ioapic_level_sequential(void)
+{
+	handle_irq(0x99, ioapic_isr_99);
+	set_ioapic_redir(0x0e, 0x99, LEVEL_TRIGGERED);
+	set_irq_line(0x0e, 1);
+	set_irq_line(0x0e, 1);
+	asm volatile ("nop");
+	report("sequential level interrupts", g_isr_99 == 2);
+}
+
+static volatile int g_isr_81;
+
+static void ioapic_isr_81(isr_regs_t *regs)
+{
+	++g_isr_81;
+	set_irq_line(0x0e, 0);
+	eoi();
+}
+
+static void test_ioapic_edge_mask(void)
+{
+	handle_irq(0x81, ioapic_isr_81);
+	set_ioapic_redir(0x0e, 0x81, EDGE_TRIGGERED);
+
+	set_mask(0x0e, true);
+	set_irq_line(0x0e, 1);
+	set_irq_line(0x0e, 0);
+
+	asm volatile ("nop");
+	report("masked level interrupt", g_isr_81 == 0);
+
+	set_mask(0x0e, false);
+	set_irq_line(0x0e, 1);
+
+	asm volatile ("nop");
+	report("unmasked level interrupt", g_isr_81 == 1);
+}
+
+static volatile int g_isr_82;
+
+static void ioapic_isr_82(isr_regs_t *regs)
+{
+	++g_isr_82;
+	set_irq_line(0x0e, 0);
+	eoi();
+}
+
+static void test_ioapic_level_mask(void)
+{
+	handle_irq(0x82, ioapic_isr_82);
+	set_ioapic_redir(0x0e, 0x82, LEVEL_TRIGGERED);
+
+	set_mask(0x0e, true);
+	set_irq_line(0x0e, 1);
+
+	asm volatile ("nop");
+	report("masked level interrupt", g_isr_82 == 0);
+
+	set_mask(0x0e, false);
+
+	asm volatile ("nop");
+	report("unmasked level interrupt", g_isr_82 == 1);
+}
+
+
 int main(void)
 {
 	setup_vm();
@@ -92,8 +254,18 @@ int main(void)
 
 	irq_enable();
 
-	test_ioapic_intr();
+	ioapic_reg_version();
+	ioapic_reg_id();
+	ioapic_arbitration_id();
+
+	test_ioapic_edge_intr();
+	test_ioapic_level_intr();
 	test_ioapic_simultaneous();
+	test_ioapic_level_coalesce();
+	test_ioapic_level_sequential();
+
+	test_ioapic_edge_mask();
+	test_ioapic_level_mask();
 
 	return report_summary();
 }
-- 
2.2.0.rc0.207.ga3a616c


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests
  2015-05-13  1:55 [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests Steve Rutherford
  2015-05-13  1:55 ` [PATCH 2/2] x86: extend IOAPIC tests Steve Rutherford
@ 2015-05-13  8:07 ` Paolo Bonzini
  1 sibling, 0 replies; 3+ messages in thread
From: Paolo Bonzini @ 2015-05-13  8:07 UTC (permalink / raw)
  To: Steve Rutherford, kvm



On 13/05/2015 03:55, Steve Rutherford wrote:
> Split apart the APIC tests into constituent parts (IOAPIC and APIC tests).
> 
> Signed-off-by: Steve Rutherford <srutherford@google.com>
> ---
>  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
> 
> diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
> index 8fc3490..d45c9a8 100644
> --- a/config/config-x86-common.mak
> +++ b/config/config-x86-common.mak
> @@ -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
> diff --git a/config/config-x86_64.mak b/config/config-x86_64.mak
> index d62c1e9..dfdeed6 100644
> --- a/config/config-x86_64.mak
> +++ b/config/config-x86_64.mak
> @@ -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
> diff --git a/lib/x86/apic.c b/lib/x86/apic.c
> index 9c42c4d..80b96d8 100644
> --- a/lib/x86/apic.c
> +++ b/lib/x86/apic.c
> @@ -17,6 +17,11 @@ static void outb(unsigned char data, unsigned short port)
>      asm volatile ("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");
> diff --git a/lib/x86/apic.h b/lib/x86/apic.h
> index e325e9a..216b98d 100644
> --- a/lib/x86/apic.h
> +++ b/lib/x86/apic.h
> @@ -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);
> diff --git a/x86/apic.c b/x86/apic.c
> index 365c281..d4eec52 100644
> --- a/x86/apic.c
> +++ b/x86/apic.c
> @@ -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)
> -{
> -    asm volatile("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);
> -    asm volatile ("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();
> -    asm volatile ("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();
>  
> diff --git a/x86/eventinj.c b/x86/eventinj.c
> index 32de6f0..bddedce 100644
> --- a/x86/eventinj.c
> +++ b/x86/eventinj.c
> @@ -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;						\
> diff --git a/x86/ioapic.c b/x86/ioapic.c
> new file mode 100644
> index 0000000..2afdaa2
> --- /dev/null
> +++ b/x86/ioapic.c
> @@ -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)
> +{
> +	asm volatile("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);
> +	asm volatile ("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();
> +	asm volatile ("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();
> +}
> diff --git a/x86/unittests.cfg b/x86/unittests.cfg
> index badb08a..a38544f 100644
> --- a/x86/unittests.cfg
> +++ b/x86/unittests.cfg
> @@ -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
> 

Applying these two, thanks!

Paolo

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-05-13  8:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-13  1:55 [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests Steve Rutherford
2015-05-13  1:55 ` [PATCH 2/2] x86: extend IOAPIC tests Steve Rutherford
2015-05-13  8:07 ` [PATCH 1/2] x86: Split APIC tests into IOAPIC/APIC tests Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.