[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |