debuggers.hg

changeset 19992:8ce42378828b

hvmloader: Add new test for MSR_SHADOW_GS_BASE validity after SWAPGS instruction.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 16 10:30:50 2009 +0100 (2009-07-16)
parents fe4c6845a9d7
children e07726c03d31
files tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/hypercall.h tools/firmware/hvmloader/tests.c tools/firmware/hvmloader/util.h
line diff
     1.1 --- a/tools/firmware/hvmloader/hvmloader.c	Thu Jul 16 10:26:55 2009 +0100
     1.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Thu Jul 16 10:30:50 2009 +0100
     1.3 @@ -22,8 +22,8 @@
     1.4  
     1.5  #include "roms.h"
     1.6  #include "acpi/acpi2_0.h"
     1.7 +#include "util.h"
     1.8  #include "hypercall.h"
     1.9 -#include "util.h"
    1.10  #include "config.h"
    1.11  #include "apic_regs.h"
    1.12  #include "pci_regs.h"
    1.13 @@ -40,7 +40,15 @@ asm (
    1.14      /* C runtime kickoff. */
    1.15      "    cld                         \n"
    1.16      "    cli                         \n"
    1.17 -    "    movl $stack_top,%esp        \n"
    1.18 +    "    lgdt gdt_desr               \n"
    1.19 +    "    mov  $"STR(SEL_DATA32)",%ax \n"
    1.20 +    "    mov  %ax,%ds                \n"
    1.21 +    "    mov  %ax,%es                \n"
    1.22 +    "    mov  %ax,%fs                \n"
    1.23 +    "    mov  %ax,%gs                \n"
    1.24 +    "    mov  %ax,%ss                \n"
    1.25 +    "    ljmp $"STR(SEL_CODE32)",$1f \n"
    1.26 +    "1:  movl $stack_top,%esp        \n"
    1.27      "    movl %esp,%ebp              \n"
    1.28      "    call main                   \n"
    1.29      /* Relocate real-mode trampoline to 0x0. */
    1.30 @@ -50,8 +58,7 @@ asm (
    1.31      "    sub  %esi,%ecx              \n"
    1.32      "    rep  movsb                  \n"
    1.33      /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
    1.34 -    "    lgdt gdt_desr               \n"
    1.35 -    "    mov  $0x0010,%ax            \n"
    1.36 +    "    mov  $"STR(SEL_DATA16)",%ax \n"
    1.37      "    mov  %ax,%ds                \n"
    1.38      "    mov  %ax,%es                \n"
    1.39      "    mov  %ax,%fs                \n"
    1.40 @@ -67,7 +74,7 @@ asm (
    1.41      "    xor  %esi,%esi              \n"
    1.42      "    xor  %edi,%edi              \n"
    1.43      /* Enter real mode, reload all segment registers and IDT. */
    1.44 -    "    ljmp $0x8,$0x0              \n"
    1.45 +    "    ljmp $"STR(SEL_CODE16)",$0x0\n"
    1.46      "trampoline_start: .code16       \n"
    1.47      "    mov  %eax,%cr0              \n"
    1.48      "    ljmp $0,$1f-trampoline_start\n"
    1.49 @@ -90,6 +97,9 @@ asm (
    1.50      "    .quad 0x0000000000000000    \n"
    1.51      "    .quad 0x008f9a000000ffff    \n" /* Ring 0 16b code, base 0 limit 4G */
    1.52      "    .quad 0x008f92000000ffff    \n" /* Ring 0 16b data, base 0 limit 4G */
    1.53 +    "    .quad 0x00cf9a000000ffff    \n" /* Ring 0 32b code, base 0 limit 4G */
    1.54 +    "    .quad 0x00cf92000000ffff    \n" /* Ring 0 32b data, base 0 limit 4G */
    1.55 +    "    .quad 0x00af9a000000ffff    \n" /* Ring 0 64b code */
    1.56      "gdt_end:                        \n"
    1.57      "                                \n"
    1.58      "    .bss                        \n"
     2.1 --- a/tools/firmware/hvmloader/hypercall.h	Thu Jul 16 10:26:55 2009 +0100
     2.2 +++ b/tools/firmware/hvmloader/hypercall.h	Thu Jul 16 10:30:50 2009 +0100
     2.3 @@ -35,9 +35,6 @@
     2.4  #include <xen/xen.h>
     2.5  #include "config.h"
     2.6  
     2.7 -#define __STR(...) #__VA_ARGS__
     2.8 -#define STR(...) __STR(__VA_ARGS__)
     2.9 -
    2.10  /*
    2.11   * NB. Hypercall address needs to be relative to a linkage symbol for
    2.12   * some version of ld to relocate the relative calls properly.
     3.1 --- a/tools/firmware/hvmloader/tests.c	Thu Jul 16 10:26:55 2009 +0100
     3.2 +++ b/tools/firmware/hvmloader/tests.c	Thu Jul 16 10:30:50 2009 +0100
     3.3 @@ -22,6 +22,10 @@
     3.4  
     3.5  #include "util.h"
     3.6  
     3.7 +#define TEST_FAIL 0
     3.8 +#define TEST_PASS 1
     3.9 +#define TEST_SKIP 2
    3.10 +
    3.11  /*
    3.12   * Memory layout during tests:
    3.13   *  4MB to 8MB is cleared.
    3.14 @@ -73,7 +77,7 @@ static int rep_io_test(void)
    3.15  {
    3.16      uint32_t *p;
    3.17      uint32_t i, p0, p1, p2;
    3.18 -    int okay = 1;
    3.19 +    int okay = TEST_PASS;
    3.20  
    3.21      static const struct {
    3.22          unsigned long addr;
    3.23 @@ -121,44 +125,114 @@ static int rep_io_test(void)
    3.24          {
    3.25              printf("Bad value at 0x%08lx: saw %08x expected %08x\n",
    3.26                     (unsigned long)p, *p, expected);
    3.27 -            okay = 0;
    3.28 +            okay = TEST_FAIL;
    3.29          }
    3.30      }
    3.31  
    3.32      return okay;
    3.33  }
    3.34  
    3.35 +static int shadow_gs_test(void)
    3.36 +{
    3.37 +    uint64_t *pd = (uint64_t *)PD_START;
    3.38 +    uint32_t i, eax, ebx, ecx, edx;
    3.39 +
    3.40 +    /* Skip this test if the CPU does not support long mode. */
    3.41 +    cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
    3.42 +    if ( eax < 0x80000001 )
    3.43 +        return TEST_SKIP;
    3.44 +    cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
    3.45 +    if ( !(edx & (1u<<29)) )
    3.46 +        return TEST_SKIP;
    3.47 +
    3.48 +    /* Long mode pagetable setup: Identity map 0-16MB with 2MB mappings. */
    3.49 +    *pd = (unsigned long)pd + 0x1007; /* Level 4 */
    3.50 +    pd += 512;
    3.51 +    *pd = (unsigned long)pd + 0x1007; /* Level 3 */
    3.52 +    pd += 512;
    3.53 +    for ( i = 0; i < 8; i++ )         /* Level 2 */
    3.54 +        *pd++ = (i << 21) + 0x1e3;
    3.55 +
    3.56 +    asm volatile (
    3.57 +        /* CR4.PAE=1 */
    3.58 +        "mov $0x20,%%ebx; "
    3.59 +        "mov %%ebx,%%cr4; "
    3.60 +        /* CR3 */
    3.61 +        "mov %%eax,%%cr3; "
    3.62 +        /* EFER.LME=1 */
    3.63 +        "mov $0xc0000080,%%ecx; rdmsr; btsl $8,%%eax; wrmsr; "
    3.64 +        /* CR0.PG=1 */
    3.65 +        "mov %%cr0,%%eax; btsl $31,%%eax; mov %%eax,%%cr0; "
    3.66 +        "jmp 1f; 1: "
    3.67 +        /* GS_BASE=2; SHADOW_GS_BASE=3 */
    3.68 +        "mov $0xc0000101,%%ecx; xor %%edx,%%edx; mov $2,%%eax; wrmsr; "
    3.69 +        "mov $0xc0000102,%%ecx; xor %%edx,%%edx; mov $3,%%eax; wrmsr; "
    3.70 +        /* Push LRETQ stack frame. */
    3.71 +        "pushl $0; pushl $"STR(SEL_CODE32)"; pushl $0; pushl $2f; "
    3.72 +        /* Jump to 64-bit mode. */
    3.73 +        "ljmp $"STR(SEL_CODE64)",$1f; 1: "
    3.74 +        /* Swap GS_BASE and SHADOW_GS_BASE */
    3.75 +        ".byte 0x0f,0x01,0xf8; " /* SWAPGS */
    3.76 +        /* Jump to 32-bit mode. */
    3.77 +        ".byte 0x89, 0xe4; "     /* MOV ESP,ESP */
    3.78 +        ".byte 0x48, 0xcb; 2: "  /* LRETQ */
    3.79 +        /* Read SHADOW_GS_BASE: should now contain 2 */
    3.80 +        "mov $0xc0000102,%%ecx; rdmsr; mov %%eax,%%ebx; "
    3.81 +        /* CR0.PG=0 */
    3.82 +        "mov %%cr0,%%eax; btcl $31,%%eax; mov %%eax,%%cr0; "
    3.83 +        "jmp 1f; 1:"
    3.84 +        /* EFER.LME=0 */
    3.85 +        "mov $0xc0000080,%%ecx; rdmsr; btcl $8,%%eax; wrmsr; "
    3.86 +        /* CR4.PAE=0 */
    3.87 +        "xor %%eax,%%eax; mov %%eax,%%cr4; "
    3.88 +        : "=b" (ebx) : "a" (PD_START) : "ecx", "edx", "memory" );
    3.89 +
    3.90 +    return (ebx == 2) ? TEST_PASS : TEST_FAIL;
    3.91 +}
    3.92 +
    3.93  void perform_tests(void)
    3.94  {
    3.95 -    int i, passed;
    3.96 +    int i, passed, skipped;
    3.97  
    3.98      static struct {
    3.99          int (* const test)(void);
   3.100          const char *description;
   3.101      } tests[] = {
   3.102          { rep_io_test, "REP INSB across page boundaries" },
   3.103 +        { shadow_gs_test, "GS base MSRs and SWAPGS" },
   3.104          { NULL, NULL }
   3.105      };
   3.106  
   3.107      printf("Testing HVM environment:\n");
   3.108  
   3.109 -    passed = 0;
   3.110 +    passed = skipped = 0;
   3.111      for ( i = 0; tests[i].test; i++ )
   3.112      {
   3.113          printf(" - %s ... ", tests[i].description);
   3.114          memset((char *)(4ul << 20), 0, 4ul << 20);
   3.115          setup_paging();
   3.116 -        if ( (*tests[i].test)() )
   3.117 +        switch ( (*tests[i].test)() )
   3.118          {
   3.119 +        case TEST_PASS:
   3.120              printf("passed\n");
   3.121              passed++;
   3.122 -        }
   3.123 -        else
   3.124 -        {
   3.125 +            break;
   3.126 +        case TEST_FAIL:
   3.127              printf("failed\n");
   3.128 +            break;
   3.129 +        case TEST_SKIP:
   3.130 +            printf("skipped\n");
   3.131 +            skipped++;
   3.132 +            break;
   3.133          }
   3.134      }
   3.135  
   3.136 -    printf("Passed %d/%d tests\n", passed, i);
   3.137 -    BUG_ON(passed != i);
   3.138 +    printf("Passed %d of %d tests\n", passed, i);
   3.139 +    if ( skipped != 0 )
   3.140 +        printf("Skipped %d of %d tests\n", skipped, i);
   3.141 +    if ( (passed + skipped) != i )
   3.142 +    {
   3.143 +        printf("FAILED %d of %d tests\n", i - passed - skipped, i);
   3.144 +        BUG();
   3.145 +    }
   3.146  }
     4.1 --- a/tools/firmware/hvmloader/util.h	Thu Jul 16 10:26:55 2009 +0100
     4.2 +++ b/tools/firmware/hvmloader/util.h	Thu Jul 16 10:30:50 2009 +0100
     4.3 @@ -5,6 +5,16 @@
     4.4  #include <stdint.h>
     4.5  #include <xen/hvm/hvm_info_table.h>
     4.6  
     4.7 +#define __STR(...) #__VA_ARGS__
     4.8 +#define STR(...) __STR(__VA_ARGS__)
     4.9 +
    4.10 +/* GDT selector values. */
    4.11 +#define SEL_CODE16          0x0008
    4.12 +#define SEL_DATA16          0x0010
    4.13 +#define SEL_CODE32          0x0018
    4.14 +#define SEL_DATA32          0x0020
    4.15 +#define SEL_CODE64          0x0028
    4.16 +
    4.17  #undef offsetof
    4.18  #define offsetof(t, m) ((unsigned long)&((t *)0)->m)
    4.19