[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XTF PATCH] Misaligned I/O Breakpoints
This xtf test tests a bug to hardware IO port breakpoints fixed by 08aacc392d86 ("x86/emul: Fix misaligned IO breakpoint behaviour in PV guests") Signed-off-by: Matthew Barnes <matthew.barnes@xxxxxxxxx> --- docs/all-tests.dox | 2 + tests/misaligned-io-breakpoints/Makefile | 9 + tests/misaligned-io-breakpoints/main.c | 283 +++++++++++++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 tests/misaligned-io-breakpoints/Makefile create mode 100644 tests/misaligned-io-breakpoints/main.c diff --git a/docs/all-tests.dox b/docs/all-tests.dox index 0a8b9130cfe8..66e35babe4d7 100644 --- a/docs/all-tests.dox +++ b/docs/all-tests.dox @@ -41,6 +41,8 @@ Coveres XSA-106 and XSA-156. @subpage test-umip - Guest User-Mode Instruction Prevention support. +@subpage test-misaligned-io-breakpoints - Misaligned I/O port hardware breakpoint test. + @section index-xsa XSA Proof-of-Concept tests diff --git a/tests/misaligned-io-breakpoints/Makefile b/tests/misaligned-io-breakpoints/Makefile new file mode 100644 index 000000000000..9e4cd3eef761 --- /dev/null +++ b/tests/misaligned-io-breakpoints/Makefile @@ -0,0 +1,9 @@ +include $(ROOT)/build/common.mk + +NAME := misaligned-io-breakpoints +CATEGORY := utility +TEST-ENVS := pv64 + +obj-perenv += main.o + +include $(ROOT)/build/gen.mk diff --git a/tests/misaligned-io-breakpoints/main.c b/tests/misaligned-io-breakpoints/main.c new file mode 100644 index 000000000000..d91222b29288 --- /dev/null +++ b/tests/misaligned-io-breakpoints/main.c @@ -0,0 +1,283 @@ +/** + * @file tests/misaligned-io-breakpoints/main.c + * @ref test-misaligned-io-breakpoints - Misaligned I/O port hardware breakpoint test. + * + * @page test-misaligned-io-breakpoints Misaligned I/O Breakpoints + * + * When hardware breakpoints are configured on misaligned IO ports, the + * hardware will mask the addresses based on the breakpoint width during + * comparison. + * + * This test checks that the emulated behaviour of misaligned IO breakpoints + * in PV guests match that of real hardware. + * + * @see tests/io-breakpoint-bug/main.c + */ +#include <xtf.h> + +enum width { _16, _32 }; + +const char test_title[] = "Misaligned I/O Breakpoints"; + +static const struct test { + unsigned long breakpoint_port; + enum width breakpoint_size; + uint16_t io_op_port; + enum width io_op_len; + bool expect_breakpoint_trigger; +} tests[] = { + /* 16-bit breakpoint, 16-bit I/O operation */ + { 0x09, _16, 0x06, _16, false }, + { 0x09, _16, 0x07, _16, true }, + { 0x09, _16, 0x08, _16, true }, + { 0x09, _16, 0x09, _16, true }, + { 0x09, _16, 0x0a, _16, false }, + + { 0x0b, _16, 0x08, _16, false }, + { 0x0b, _16, 0x09, _16, true }, + { 0x0b, _16, 0x0a, _16, true }, + { 0x0b, _16, 0x0b, _16, true }, + { 0x0b, _16, 0x0c, _16, false }, + + /* 16-bit breakpoint, 32-bit I/O operation */ + { 0x09, _16, 0x04, _32, false }, + { 0x09, _16, 0x05, _32, true }, + { 0x09, _16, 0x06, _32, true }, + { 0x09, _16, 0x07, _32, true }, + { 0x09, _16, 0x08, _32, true }, + { 0x09, _16, 0x09, _32, true }, + { 0x09, _16, 0x0a, _32, false }, + + { 0x0b, _16, 0x06, _32, false }, + { 0x0b, _16, 0x07, _32, true }, + { 0x0b, _16, 0x08, _32, true }, + { 0x0b, _16, 0x09, _32, true }, + { 0x0b, _16, 0x0a, _32, true }, + { 0x0b, _16, 0x0b, _32, true }, + { 0x0b, _16, 0x0c, _32, false }, + + /* 32-bit breakpoint, 16-bit I/O operation */ + { 0x09, _32, 0x06, _16, false }, + { 0x09, _32, 0x07, _16, true }, + { 0x09, _32, 0x08, _16, true }, + { 0x09, _32, 0x09, _16, true }, + { 0x09, _32, 0x0a, _16, true }, + { 0x09, _32, 0x0b, _16, true }, + { 0x09, _32, 0x0c, _16, false }, + + { 0x0a, _32, 0x06, _16, false }, + { 0x0a, _32, 0x07, _16, true }, + { 0x0a, _32, 0x08, _16, true }, + { 0x0a, _32, 0x09, _16, true }, + { 0x0a, _32, 0x0a, _16, true }, + { 0x0a, _32, 0x0b, _16, true }, + { 0x0a, _32, 0x0c, _16, false }, + + { 0x0b, _32, 0x06, _16, false }, + { 0x0b, _32, 0x07, _16, true }, + { 0x0b, _32, 0x08, _16, true }, + { 0x0b, _32, 0x09, _16, true }, + { 0x0b, _32, 0x0a, _16, true }, + { 0x0b, _32, 0x0b, _16, true }, + { 0x0b, _32, 0x0c, _16, false }, + + { 0x0d, _32, 0x0a, _16, false }, + { 0x0d, _32, 0x0b, _16, true }, + { 0x0d, _32, 0x0c, _16, true }, + { 0x0d, _32, 0x0d, _16, true }, + { 0x0d, _32, 0x0e, _16, true }, + { 0x0d, _32, 0x0f, _16, true }, + { 0x0d, _32, 0x10, _16, false }, + + { 0x0e, _32, 0x0a, _16, false }, + { 0x0e, _32, 0x0b, _16, true }, + { 0x0e, _32, 0x0c, _16, true }, + { 0x0e, _32, 0x0d, _16, true }, + { 0x0e, _32, 0x0e, _16, true }, + { 0x0e, _32, 0x0f, _16, true }, + { 0x0e, _32, 0x10, _16, false }, + + { 0x0f, _32, 0x0a, _16, false }, + { 0x0f, _32, 0x0b, _16, true }, + { 0x0f, _32, 0x0c, _16, true }, + { 0x0f, _32, 0x0d, _16, true }, + { 0x0f, _32, 0x0e, _16, true }, + { 0x0f, _32, 0x0f, _16, true }, + { 0x0f, _32, 0x10, _16, false }, + + /* 32-bit breakpoint, 32-bit I/O operation */ + { 0x09, _32, 0x04, _32, false }, + { 0x09, _32, 0x05, _32, true }, + { 0x09, _32, 0x06, _32, true }, + { 0x09, _32, 0x07, _32, true }, + { 0x09, _32, 0x08, _32, true }, + { 0x09, _32, 0x09, _32, true }, + { 0x09, _32, 0x0a, _32, true }, + { 0x09, _32, 0x0b, _32, true }, + { 0x09, _32, 0x0c, _32, false }, + + { 0x0a, _32, 0x04, _32, false }, + { 0x0a, _32, 0x05, _32, true }, + { 0x0a, _32, 0x06, _32, true }, + { 0x0a, _32, 0x07, _32, true }, + { 0x0a, _32, 0x08, _32, true }, + { 0x0a, _32, 0x09, _32, true }, + { 0x0a, _32, 0x0a, _32, true }, + { 0x0a, _32, 0x0b, _32, true }, + { 0x0a, _32, 0x0c, _32, false }, + + { 0x0b, _32, 0x04, _32, false }, + { 0x0b, _32, 0x05, _32, true }, + { 0x0b, _32, 0x06, _32, true }, + { 0x0b, _32, 0x07, _32, true }, + { 0x0b, _32, 0x08, _32, true }, + { 0x0b, _32, 0x09, _32, true }, + { 0x0b, _32, 0x0a, _32, true }, + { 0x0b, _32, 0x0b, _32, true }, + { 0x0b, _32, 0x0c, _32, false }, + + { 0x0d, _32, 0x08, _32, false }, + { 0x0d, _32, 0x09, _32, true }, + { 0x0d, _32, 0x0a, _32, true }, + { 0x0d, _32, 0x0b, _32, true }, + { 0x0d, _32, 0x0c, _32, true }, + { 0x0d, _32, 0x0d, _32, true }, + { 0x0d, _32, 0x0e, _32, true }, + { 0x0d, _32, 0x0f, _32, true }, + { 0x0d, _32, 0x10, _32, false }, + + { 0x0e, _32, 0x08, _32, false }, + { 0x0e, _32, 0x09, _32, true }, + { 0x0e, _32, 0x0a, _32, true }, + { 0x0e, _32, 0x0b, _32, true }, + { 0x0e, _32, 0x0c, _32, true }, + { 0x0e, _32, 0x0d, _32, true }, + { 0x0e, _32, 0x0e, _32, true }, + { 0x0e, _32, 0x0f, _32, true }, + { 0x0e, _32, 0x10, _32, false }, + + { 0x0f, _32, 0x08, _32, false }, + { 0x0f, _32, 0x09, _32, true }, + { 0x0f, _32, 0x0a, _32, true }, + { 0x0f, _32, 0x0b, _32, true }, + { 0x0f, _32, 0x0c, _32, true }, + { 0x0f, _32, 0x0d, _32, true }, + { 0x0f, _32, 0x0e, _32, true }, + { 0x0f, _32, 0x0f, _32, true }, + { 0x0f, _32, 0x10, _32, false }, +}; + +static void enable_debug_extensions(void) +{ + unsigned long cr4 = read_cr4(); + + if ( !(cr4 & X86_CR4_DE) ) + write_cr4(cr4 | X86_CR4_DE); +} + +static void init_breakpoint(enum width width) +{ + unsigned long io0, dr7; + + switch (width) + { + case _16: + io0 = DR7_SYM(0, G, IO, 16) | X86_DR7_GE | X86_DR7_DEFAULT; + break; + case _32: + io0 = DR7_SYM(0, G, IO, 32) | X86_DR7_GE | X86_DR7_DEFAULT; + break; + default: + xtf_failure(" Fail: Unknown width %d\n", width); + return; + } + + write_dr7(io0); + + if ( (dr7 = read_dr7()) != io0 ) + xtf_failure(" Fail: dr7 %#lx != io0 %#lx\n", dr7, io0); +} + +static void set_breakpoint(unsigned long io_port) +{ + unsigned long dr0; + + write_dr0(io_port); + + if ( (dr0 = read_dr0()) != io_port ) + xtf_failure(" Fail: dr0 %#lx != %#lx\n", dr0, io_port); +} + +/* Set vCPU IOPL to 1 to allow IO calls in kernel space */ +static void set_iopl(void) +{ + unsigned int iopl = 1; + + hypercall_physdev_op(PHYSDEVOP_set_iopl, &iopl); +} + +static exinfo_t io_op(uint16_t io_port, enum width io_op_len) +{ + exinfo_t fault = 0; + + switch (io_op_len) + { + case _16: + asm volatile ("outw %w0, %w1; 1:" + _ASM_EXTABLE_HANDLER(1b, 1b, %P[rec]) + : "+a" (fault) + : "Nd" (io_port), + [rec] "p" (ex_record_fault_eax)); + break; + case _32: + asm volatile ("outl %k0, %w1; 1:" + _ASM_EXTABLE_HANDLER(1b, 1b, %P[rec]) + : "+a" (fault) + : "Nd" (io_port), + [rec] "p" (ex_record_fault_eax)); + break; + default: + xtf_failure(" Fail: Unknown width %d\n", io_op_len); + break; + } + + return fault; +} + +void test_main(void) +{ + unsigned int i; + + enable_debug_extensions(); + set_iopl(); + + for ( i = 0; i < ARRAY_SIZE(tests); ++i ) + { + const struct test *t = &tests[i]; + + /* arrange */ + init_breakpoint(t->breakpoint_size); + set_breakpoint(t->breakpoint_port); + + /* act */ + exinfo_t ex = io_op(t->io_op_port, t->io_op_len); + + /* assert */ + if ( t->expect_breakpoint_trigger && ex != EXINFO_SYM(DB, 0) ) + xtf_failure("Fail: Expected trigger with breakpoint port 0x%02lx and io port 0x%02x, but got no trigger.\n", t->breakpoint_port, t->io_op_port); + if ( !t->expect_breakpoint_trigger && ex == EXINFO_SYM(DB, 0) ) + xtf_failure("Fail: Expected no trigger with breakpoint port 0x%02lx and io port 0x%02x, but got trigger.\n", t->breakpoint_port, t->io_op_port); + } + + xtf_success(NULL); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- 2.34.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |