diff mbox

[kvm-unit-tests,3/3] x86: svm: IOIO testing

Message ID 1406750889-12977-4-git-send-email-pbonzini@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paolo Bonzini July 30, 2014, 8:08 p.m. UTC
Testing the bitmap handling so far, does not cover string instructions
yet.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 x86/svm.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)
diff mbox

Patch

diff --git a/x86/svm.c b/x86/svm.c
index 2cf5c81..290c33e 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -6,6 +6,7 @@ 
 #include "vm.h"
 #include "smp.h"
 #include "types.h"
+#include "io.h"
 
 /* for the nested page table*/
 u64 *pml4e;
@@ -505,6 +506,129 @@  static bool check_mode_switch(struct test *test)
 	return test->scratch == 2;
 }
 
+static void prepare_ioio(struct test *test)
+{
+    test->vmcb->control.intercept |= (1ULL << INTERCEPT_IOIO_PROT);
+    test->scratch = 0;
+    memset(io_bitmap, 0, 8192);
+    io_bitmap[8192] = 0xFF;
+}
+
+int get_test_stage(struct test *test)
+{
+    barrier();
+    return test->scratch;
+}
+
+void inc_test_stage(struct test *test)
+{
+    barrier();
+    test->scratch++;
+    barrier();
+}
+
+static void test_ioio(struct test *test)
+{
+    // stage 0, test IO pass
+    inb(0x5000);
+    outb(0x0, 0x5000);
+    if (get_test_stage(test) != 0)
+        goto fail;
+
+    // test IO width, in/out
+    io_bitmap[0] = 0xFF;
+    inc_test_stage(test);
+    inb(0x0);
+    if (get_test_stage(test) != 2)
+        goto fail;
+
+    outw(0x0, 0x0);
+    if (get_test_stage(test) != 3)
+        goto fail;
+
+    inl(0x0);
+    if (get_test_stage(test) != 4)
+        goto fail;
+
+    // test low/high IO port
+    io_bitmap[0x5000 / 8] = (1 << (0x5000 % 8));
+    inb(0x5000);
+    if (get_test_stage(test) != 5)
+        goto fail;
+
+    io_bitmap[0x9000 / 8] = (1 << (0x9000 % 8));
+    inw(0x9000);
+    if (get_test_stage(test) != 6)
+        goto fail;
+
+    // test partial pass
+    io_bitmap[0x5000 / 8] = (1 << (0x5000 % 8));
+    inl(0x4FFF);
+    if (get_test_stage(test) != 7)
+        goto fail;
+
+    // test across pages
+    inc_test_stage(test);
+    inl(0x7FFF);
+    if (get_test_stage(test) != 8)
+        goto fail;
+
+    inc_test_stage(test);
+    io_bitmap[0x8000 / 8] = 1 << (0x8000 % 8);
+    inl(0x7FFF);
+    if (get_test_stage(test) != 10)
+        goto fail;
+
+    io_bitmap[0] = 0;
+    inl(0xFFFF);
+    if (get_test_stage(test) != 11)
+        goto fail;
+
+    io_bitmap[0] = 0xFF;
+    io_bitmap[8192] = 0;
+    inl(0xFFFF);
+    inc_test_stage(test);
+    if (get_test_stage(test) != 12)
+        goto fail;
+
+    return;
+
+fail:
+    printf("test failure, stage %d\n", get_test_stage(test));
+    test->scratch = -1;
+}
+
+static bool ioio_finished(struct test *test)
+{
+    unsigned port, size;
+
+    /* Only expect IOIO intercepts */
+    if (test->vmcb->control.exit_code == SVM_EXIT_VMMCALL)
+        return true;
+
+    if (test->vmcb->control.exit_code != SVM_EXIT_IOIO)
+        return true;
+
+    /* one step forward */
+    test->scratch += 1;
+
+    port = test->vmcb->control.exit_info_1 >> 16;
+    size = (test->vmcb->control.exit_info_1 >> SVM_IOIO_SIZE_SHIFT) & 7;
+
+    while (size--) {
+        io_bitmap[port / 8] &= ~(1 << (port & 7));
+        port++;
+    }
+
+    return false;
+}
+
+static bool check_ioio(struct test *test)
+{
+    memset(io_bitmap, 0, 8193);
+    return test->scratch != -1;
+}
+
 static void prepare_asid_zero(struct test *test)
 {
     test->vmcb->control.asid = 0;
@@ -804,6 +928,8 @@  static struct test tests[] = {
       default_finished, null_check },
     { "vmrun", default_supported, default_prepare, test_vmrun,
        default_finished, check_vmrun },
+    { "ioio", default_supported, prepare_ioio, test_ioio,
+       ioio_finished, check_ioio },
     { "vmrun intercept check", default_supported, prepare_no_vmrun_int,
       null_test, default_finished, check_no_vmrun_int },
     { "cr3 read intercept", default_supported, prepare_cr3_intercept,