* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox