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

[Xen-changelog] [xen-unstable] hvmloader: Add new test for MSR_SHADOW_GS_BASE validity after SWAPGS instruction.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1247736650 -3600
# Node ID 8ce42378828bfa1576cbc601cadf61cb21439bf7
# Parent  fe4c6845a9d7453f5a72cd69cb26c17b4df1c9af
hvmloader: Add new test for MSR_SHADOW_GS_BASE validity after SWAPGS 
instruction.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/firmware/hvmloader/hvmloader.c |   20 +++++-
 tools/firmware/hvmloader/hypercall.h |    3 -
 tools/firmware/hvmloader/tests.c     |  104 +++++++++++++++++++++++++++++------
 tools/firmware/hvmloader/util.h      |   10 +++
 4 files changed, 114 insertions(+), 23 deletions(-)

diff -r fe4c6845a9d7 -r 8ce42378828b tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Thu Jul 16 10:26:55 2009 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c      Thu Jul 16 10:30:50 2009 +0100
@@ -22,8 +22,8 @@
 
 #include "roms.h"
 #include "acpi/acpi2_0.h"
+#include "util.h"
 #include "hypercall.h"
-#include "util.h"
 #include "config.h"
 #include "apic_regs.h"
 #include "pci_regs.h"
@@ -40,7 +40,15 @@ asm (
     /* C runtime kickoff. */
     "    cld                         \n"
     "    cli                         \n"
-    "    movl $stack_top,%esp        \n"
+    "    lgdt gdt_desr               \n"
+    "    mov  $"STR(SEL_DATA32)",%ax \n"
+    "    mov  %ax,%ds                \n"
+    "    mov  %ax,%es                \n"
+    "    mov  %ax,%fs                \n"
+    "    mov  %ax,%gs                \n"
+    "    mov  %ax,%ss                \n"
+    "    ljmp $"STR(SEL_CODE32)",$1f \n"
+    "1:  movl $stack_top,%esp        \n"
     "    movl %esp,%ebp              \n"
     "    call main                   \n"
     /* Relocate real-mode trampoline to 0x0. */
@@ -50,8 +58,7 @@ asm (
     "    sub  %esi,%ecx              \n"
     "    rep  movsb                  \n"
     /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
-    "    lgdt gdt_desr               \n"
-    "    mov  $0x0010,%ax            \n"
+    "    mov  $"STR(SEL_DATA16)",%ax \n"
     "    mov  %ax,%ds                \n"
     "    mov  %ax,%es                \n"
     "    mov  %ax,%fs                \n"
@@ -67,7 +74,7 @@ asm (
     "    xor  %esi,%esi              \n"
     "    xor  %edi,%edi              \n"
     /* Enter real mode, reload all segment registers and IDT. */
-    "    ljmp $0x8,$0x0              \n"
+    "    ljmp $"STR(SEL_CODE16)",$0x0\n"
     "trampoline_start: .code16       \n"
     "    mov  %eax,%cr0              \n"
     "    ljmp $0,$1f-trampoline_start\n"
@@ -90,6 +97,9 @@ asm (
     "    .quad 0x0000000000000000    \n"
     "    .quad 0x008f9a000000ffff    \n" /* Ring 0 16b code, base 0 limit 4G */
     "    .quad 0x008f92000000ffff    \n" /* Ring 0 16b data, base 0 limit 4G */
+    "    .quad 0x00cf9a000000ffff    \n" /* Ring 0 32b code, base 0 limit 4G */
+    "    .quad 0x00cf92000000ffff    \n" /* Ring 0 32b data, base 0 limit 4G */
+    "    .quad 0x00af9a000000ffff    \n" /* Ring 0 64b code */
     "gdt_end:                        \n"
     "                                \n"
     "    .bss                        \n"
diff -r fe4c6845a9d7 -r 8ce42378828b tools/firmware/hvmloader/hypercall.h
--- a/tools/firmware/hvmloader/hypercall.h      Thu Jul 16 10:26:55 2009 +0100
+++ b/tools/firmware/hvmloader/hypercall.h      Thu Jul 16 10:30:50 2009 +0100
@@ -34,9 +34,6 @@
 #include <stdint.h>
 #include <xen/xen.h>
 #include "config.h"
-
-#define __STR(...) #__VA_ARGS__
-#define STR(...) __STR(__VA_ARGS__)
 
 /*
  * NB. Hypercall address needs to be relative to a linkage symbol for
diff -r fe4c6845a9d7 -r 8ce42378828b tools/firmware/hvmloader/tests.c
--- a/tools/firmware/hvmloader/tests.c  Thu Jul 16 10:26:55 2009 +0100
+++ b/tools/firmware/hvmloader/tests.c  Thu Jul 16 10:30:50 2009 +0100
@@ -22,6 +22,10 @@
 
 #include "util.h"
 
+#define TEST_FAIL 0
+#define TEST_PASS 1
+#define TEST_SKIP 2
+
 /*
  * Memory layout during tests:
  *  4MB to 8MB is cleared.
@@ -73,7 +77,7 @@ static int rep_io_test(void)
 {
     uint32_t *p;
     uint32_t i, p0, p1, p2;
-    int okay = 1;
+    int okay = TEST_PASS;
 
     static const struct {
         unsigned long addr;
@@ -121,44 +125,114 @@ static int rep_io_test(void)
         {
             printf("Bad value at 0x%08lx: saw %08x expected %08x\n",
                    (unsigned long)p, *p, expected);
-            okay = 0;
+            okay = TEST_FAIL;
         }
     }
 
     return okay;
 }
 
+static int shadow_gs_test(void)
+{
+    uint64_t *pd = (uint64_t *)PD_START;
+    uint32_t i, eax, ebx, ecx, edx;
+
+    /* Skip this test if the CPU does not support long mode. */
+    cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
+    if ( eax < 0x80000001 )
+        return TEST_SKIP;
+    cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
+    if ( !(edx & (1u<<29)) )
+        return TEST_SKIP;
+
+    /* Long mode pagetable setup: Identity map 0-16MB with 2MB mappings. */
+    *pd = (unsigned long)pd + 0x1007; /* Level 4 */
+    pd += 512;
+    *pd = (unsigned long)pd + 0x1007; /* Level 3 */
+    pd += 512;
+    for ( i = 0; i < 8; i++ )         /* Level 2 */
+        *pd++ = (i << 21) + 0x1e3;
+
+    asm volatile (
+        /* CR4.PAE=1 */
+        "mov $0x20,%%ebx; "
+        "mov %%ebx,%%cr4; "
+        /* CR3 */
+        "mov %%eax,%%cr3; "
+        /* EFER.LME=1 */
+        "mov $0xc0000080,%%ecx; rdmsr; btsl $8,%%eax; wrmsr; "
+        /* CR0.PG=1 */
+        "mov %%cr0,%%eax; btsl $31,%%eax; mov %%eax,%%cr0; "
+        "jmp 1f; 1: "
+        /* GS_BASE=2; SHADOW_GS_BASE=3 */
+        "mov $0xc0000101,%%ecx; xor %%edx,%%edx; mov $2,%%eax; wrmsr; "
+        "mov $0xc0000102,%%ecx; xor %%edx,%%edx; mov $3,%%eax; wrmsr; "
+        /* Push LRETQ stack frame. */
+        "pushl $0; pushl $"STR(SEL_CODE32)"; pushl $0; pushl $2f; "
+        /* Jump to 64-bit mode. */
+        "ljmp $"STR(SEL_CODE64)",$1f; 1: "
+        /* Swap GS_BASE and SHADOW_GS_BASE */
+        ".byte 0x0f,0x01,0xf8; " /* SWAPGS */
+        /* Jump to 32-bit mode. */
+        ".byte 0x89, 0xe4; "     /* MOV ESP,ESP */
+        ".byte 0x48, 0xcb; 2: "  /* LRETQ */
+        /* Read SHADOW_GS_BASE: should now contain 2 */
+        "mov $0xc0000102,%%ecx; rdmsr; mov %%eax,%%ebx; "
+        /* CR0.PG=0 */
+        "mov %%cr0,%%eax; btcl $31,%%eax; mov %%eax,%%cr0; "
+        "jmp 1f; 1:"
+        /* EFER.LME=0 */
+        "mov $0xc0000080,%%ecx; rdmsr; btcl $8,%%eax; wrmsr; "
+        /* CR4.PAE=0 */
+        "xor %%eax,%%eax; mov %%eax,%%cr4; "
+        : "=b" (ebx) : "a" (PD_START) : "ecx", "edx", "memory" );
+
+    return (ebx == 2) ? TEST_PASS : TEST_FAIL;
+}
+
 void perform_tests(void)
 {
-    int i, passed;
+    int i, passed, skipped;
 
     static struct {
         int (* const test)(void);
         const char *description;
     } tests[] = {
         { rep_io_test, "REP INSB across page boundaries" },
+        { shadow_gs_test, "GS base MSRs and SWAPGS" },
         { NULL, NULL }
     };
 
     printf("Testing HVM environment:\n");
 
-    passed = 0;
+    passed = skipped = 0;
     for ( i = 0; tests[i].test; i++ )
     {
         printf(" - %s ... ", tests[i].description);
         memset((char *)(4ul << 20), 0, 4ul << 20);
         setup_paging();
-        if ( (*tests[i].test)() )
-        {
+        switch ( (*tests[i].test)() )
+        {
+        case TEST_PASS:
             printf("passed\n");
             passed++;
-        }
-        else
-        {
+            break;
+        case TEST_FAIL:
             printf("failed\n");
-        }
-    }
-
-    printf("Passed %d/%d tests\n", passed, i);
-    BUG_ON(passed != i);
-}
+            break;
+        case TEST_SKIP:
+            printf("skipped\n");
+            skipped++;
+            break;
+        }
+    }
+
+    printf("Passed %d of %d tests\n", passed, i);
+    if ( skipped != 0 )
+        printf("Skipped %d of %d tests\n", skipped, i);
+    if ( (passed + skipped) != i )
+    {
+        printf("FAILED %d of %d tests\n", i - passed - skipped, i);
+        BUG();
+    }
+}
diff -r fe4c6845a9d7 -r 8ce42378828b tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Thu Jul 16 10:26:55 2009 +0100
+++ b/tools/firmware/hvmloader/util.h   Thu Jul 16 10:30:50 2009 +0100
@@ -4,6 +4,16 @@
 #include <stdarg.h>
 #include <stdint.h>
 #include <xen/hvm/hvm_info_table.h>
+
+#define __STR(...) #__VA_ARGS__
+#define STR(...) __STR(__VA_ARGS__)
+
+/* GDT selector values. */
+#define SEL_CODE16          0x0008
+#define SEL_DATA16          0x0010
+#define SEL_CODE32          0x0018
+#define SEL_DATA32          0x0020
+#define SEL_CODE64          0x0028
 
 #undef offsetof
 #define offsetof(t, m) ((unsigned long)&((t *)0)->m)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.