[kvm-unit-tests PATCH] x86: svm: Add debug registers intercepts test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Test debug registers read and write intercepts.

Signed-off-by: William Tambe <william.tambe@xxxxxxx>
---
 x86/svm.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/x86/svm.c b/x86/svm.c
index bc0396d..e5d9f0b 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -8,6 +8,8 @@
 #include "types.h"
 #include "alloc_page.h"
 
+#define SVM_EXIT_MAX_DR_INTERCEPT 0x3f
+
 /* for the nested page table*/
 u64 *pml4e;
 u64 *pdpe;
@@ -382,6 +384,120 @@ static void test_cr3_intercept_bypass(struct test *test)
     test->scratch = a;
 }
 
+static void prepare_dr_intercept(struct test *test)
+{
+    default_prepare(test);
+    test->vmcb->control.intercept_dr_read = 0xff;
+    test->vmcb->control.intercept_dr_write = 0xff;
+}
+
+static void test_dr_intercept(struct test *test)
+{
+    unsigned int i, failcnt = 0;
+
+    /* Loop testing debug register reads */
+    for (i = 0; i < 8; i++) {
+
+        switch (i) {
+        case 0:
+            asm volatile ("mov %%dr0, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 1:
+            asm volatile ("mov %%dr1, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 2:
+            asm volatile ("mov %%dr2, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 3:
+            asm volatile ("mov %%dr3, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 4:
+            asm volatile ("mov %%dr4, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 5:
+            asm volatile ("mov %%dr5, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 6:
+            asm volatile ("mov %%dr6, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        case 7:
+            asm volatile ("mov %%dr7, %0" : "=r"(test->scratch) : : "memory");
+            break;
+        }
+
+        if (test->scratch != i) {
+            report("dr%u read intercept", false, i);
+            failcnt++;
+        }
+    }
+
+    /* Loop testing debug register writes */
+    for (i = 0; i < 8; i++) {
+
+        switch (i) {
+        case 0:
+            asm volatile ("mov %0, %%dr0" : : "r"(test->scratch) : "memory");
+            break;
+        case 1:
+            asm volatile ("mov %0, %%dr1" : : "r"(test->scratch) : "memory");
+            break;
+        case 2:
+            asm volatile ("mov %0, %%dr2" : : "r"(test->scratch) : "memory");
+            break;
+        case 3:
+            asm volatile ("mov %0, %%dr3" : : "r"(test->scratch) : "memory");
+            break;
+        case 4:
+            asm volatile ("mov %0, %%dr4" : : "r"(test->scratch) : "memory");
+            break;
+        case 5:
+            asm volatile ("mov %0, %%dr5" : : "r"(test->scratch) : "memory");
+            break;
+        case 6:
+            asm volatile ("mov %0, %%dr6" : : "r"(test->scratch) : "memory");
+            break;
+        case 7:
+            asm volatile ("mov %0, %%dr7" : : "r"(test->scratch) : "memory");
+            break;
+        }
+
+        if (test->scratch != i) {
+            report("dr%u write intercept", false, i);
+            failcnt++;
+        }
+    }
+
+    test->scratch = failcnt;
+}
+
+static bool dr_intercept_finished(struct test *test)
+{
+    ulong n = (test->vmcb->control.exit_code - SVM_EXIT_READ_DR0);
+
+    /* Only expect DR intercepts */
+    if (n > (SVM_EXIT_MAX_DR_INTERCEPT - SVM_EXIT_READ_DR0))
+        return true;
+
+    /*
+     * Compute debug register number.
+     * Per Appendix C "SVM Intercept Exit Codes" of AMD64 Architecture
+     * Programmer's Manual Volume 2 - System Programming:
+     * http://support.amd.com/TechDocs/24593.pdf
+     * there are 16 VMEXIT codes each for DR read and write.
+     */
+    test->scratch = (n % 16);
+
+    /* Jump over MOV instruction */
+    test->vmcb->save.rip += 3;
+
+    return false;
+}
+
+static bool check_dr_intercept(struct test *test)
+{
+    return !test->scratch;
+}
+
 static bool next_rip_supported(void)
 {
     return (cpuid(SVM_CPUID_FUNC).d & 8);
@@ -1064,6 +1180,8 @@ static struct test tests[] = {
     { "cr3 read intercept emulate", smp_supported,
       prepare_cr3_intercept_bypass, test_cr3_intercept_bypass,
       default_finished, check_cr3_intercept },
+    { "dr intercept check", default_supported, prepare_dr_intercept,
+      test_dr_intercept, dr_intercept_finished, check_dr_intercept },
     { "next_rip", next_rip_supported, prepare_next_rip, test_next_rip,
       default_finished, check_next_rip },
     { "mode_switch", default_supported, prepare_mode_switch, test_mode_switch,
-- 
2.17.1





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux