* [PATCH kvm-unit-tests 0/4] VM86 testcase and run_tests.sh
@ 2012-01-23 16:07 Kevin Wolf
2012-01-23 16:07 ` [PATCH kvm-unit-tests 1/4] Add run_tests.sh Kevin Wolf
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Kevin Wolf @ 2012-01-23 16:07 UTC (permalink / raw)
To: avi; +Cc: kwolf, kvm
This adds a test case for taskswitches into/out of VM86. This test case
currently fails on KVM, it passes with TCG. I'll send out KVM fixes together
with this series.
I also included a small shell script that just runs tests and prints a
PASS/FAIL message for each. I've been using this script locally for a while,
but maybe someone else finds it handy, too.
Kevin Wolf (4):
Add run_tests.sh
Add taskswitch testcases to unittest.cfg
Fix i386 build
x86/taskswitch_vm86: Task switches into/out of VM86
config-i386.mak | 3 +-
lib/x86/desc.c | 39 +-----------------
lib/x86/desc.h | 36 ++++++++++++++++
lib/x86/vm.c | 4 +-
lib/x86/vm.h | 1 +
run_tests.sh | 107 +++++++++++++++++++++++++++++++++++++++++++++++++
x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++
x86/unittests.cfg | 18 ++++++++
8 files changed, 227 insertions(+), 40 deletions(-)
create mode 100755 run_tests.sh
create mode 100644 x86/taskswitch_vm86.c
--
1.7.6.5
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH kvm-unit-tests 1/4] Add run_tests.sh 2012-01-23 16:07 [PATCH kvm-unit-tests 0/4] VM86 testcase and run_tests.sh Kevin Wolf @ 2012-01-23 16:07 ` Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 2/4] Add taskswitch testcases to unittest.cfg Kevin Wolf ` (2 subsequent siblings) 3 siblings, 0 replies; 14+ messages in thread From: Kevin Wolf @ 2012-01-23 16:07 UTC (permalink / raw) To: avi; +Cc: kwolf, kvm This adds a convenient way to run all tests without having to set up Autotest. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- run_tests.sh | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 107 insertions(+), 0 deletions(-) create mode 100755 run_tests.sh diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..8d152b0 --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +testroot=x86 +config=$testroot/unittests.cfg +qemu=${qemu:-qemu-system-x86_64} +verbose=0 + +function run() +{ + local testname="$1" + local groups="$2" + local smp="$3" + local kernel="$4" + local opts="$5" + + if [ -z "$testname" ]; then + return + fi + + if [ -n "$only_group" ] && ! grep -q "$only_group" <<<$groups; then + return + fi + + cmdline="$qemu -display none -enable-kvm -device testdev,chardev=testlog -chardev stdio,id=testlog -kernel $kernel -smp $smp $opts" + if [ $verbose != 0 ]; then + echo $cmdline + fi + + # extra_params in the config file may contain backticks that need to be + # expanded, so use eval to start qemu + eval $cmdline >> test.log + + if [ $? == 0 ]; then + echo PASS $1 + else + echo FAIL $1 + fi +} + +function run_all() +{ + local config="$1" + local testname + local smp + local kernel + local opts + local groups + + exec {config_fd}<$config + + while read -u $config_fd line; do + if [[ "$line" =~ ^\[(.*)\]$ ]]; then + run "$testname" "$groups" "$smp" "$kernel" "$opts" + testname=${BASH_REMATCH[1]} + smp=1 + kernel="" + opts="" + groups="" + elif [[ $line =~ ^file\ *=\ *(.*)$ ]]; then + kernel=$testroot/${BASH_REMATCH[1]} + elif [[ $line =~ ^smp\ *=\ *(.*)$ ]]; then + smp=${BASH_REMATCH[1]} + elif [[ $line =~ ^extra_params\ *=\ *(.*)$ ]]; then + opts=${BASH_REMATCH[1]} + elif [[ $line =~ ^groups\ *=\ *(.*)$ ]]; then + groups=${BASH_REMATCH[1]} + fi + done + + run "$testname" "$groups" "$smp" "$kernel" "$opts" + + exec {config_fd}<&- +} + +function usage() +{ +cat <<EOF + +Usage: $0 [-g group] [-h] [-v] + + -g: Only execute tests in the given group + -h: Output this help text + -v: Enables verbose mode + +EOF +} + +echo > test.log +while getopts "g:hv" opt; do + case $opt in + g) + only_group=$OPTARG + ;; + h) + usage + exit + ;; + v) + verbose=1 + ;; + *) + exit + ;; + esac +done + +run_all $config -- 1.7.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH kvm-unit-tests 2/4] Add taskswitch testcases to unittest.cfg 2012-01-23 16:07 [PATCH kvm-unit-tests 0/4] VM86 testcase and run_tests.sh Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 1/4] Add run_tests.sh Kevin Wolf @ 2012-01-23 16:07 ` Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 3/4] Fix i386 build Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 Kevin Wolf 3 siblings, 0 replies; 14+ messages in thread From: Kevin Wolf @ 2012-01-23 16:07 UTC (permalink / raw) To: avi; +Cc: kwolf, kvm Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- x86/unittests.cfg | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 065020a..dac7d44 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -64,6 +64,18 @@ file = svm.flat smp = 2 extra_params = -cpu qemu64,-svm +[taskswitch] +file = taskswitch.flat +smp = 2 +extra_params = -cpu qemu64,-svm +groups = task + +[taskswitch2] +file = taskswitch2.flat +smp = 2 +extra_params = -cpu qemu64,-svm +groups = task + [kvmclock_test] file = kvmclock_test.flat smp = 2 -- 1.7.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH kvm-unit-tests 3/4] Fix i386 build 2012-01-23 16:07 [PATCH kvm-unit-tests 0/4] VM86 testcase and run_tests.sh Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 1/4] Add run_tests.sh Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 2/4] Add taskswitch testcases to unittest.cfg Kevin Wolf @ 2012-01-23 16:07 ` Kevin Wolf 2012-01-24 9:51 ` Takuya Yoshikawa 2012-01-23 16:07 ` [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 Kevin Wolf 3 siblings, 1 reply; 14+ messages in thread From: Kevin Wolf @ 2012-01-23 16:07 UTC (permalink / raw) To: avi; +Cc: kwolf, kvm Commit 1d946e07 removed idt, but left a reference to idt in i386-only code. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- lib/x86/desc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index c268955..770c250 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -329,7 +329,7 @@ void setup_gdt(void) static void set_idt_task_gate(int vec, u16 sel) { - idt_entry_t *e = &idt[vec]; + idt_entry_t *e = &boot_idt[vec]; memset(e, 0, sizeof *e); -- 1.7.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 3/4] Fix i386 build 2012-01-23 16:07 ` [PATCH kvm-unit-tests 3/4] Fix i386 build Kevin Wolf @ 2012-01-24 9:51 ` Takuya Yoshikawa 2012-01-24 9:58 ` Kevin Wolf 0 siblings, 1 reply; 14+ messages in thread From: Takuya Yoshikawa @ 2012-01-24 9:51 UTC (permalink / raw) To: Kevin Wolf; +Cc: avi, kvm (2012/01/24 1:07), Kevin Wolf wrote: > Commit 1d946e07 removed idt, but left a reference to idt in i386-only > code. > This is already fixed by commit b319491d278d4e85de7ea967982f7d416f4a44e4 desc: fix build for i386 Takuya ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 3/4] Fix i386 build 2012-01-24 9:51 ` Takuya Yoshikawa @ 2012-01-24 9:58 ` Kevin Wolf 0 siblings, 0 replies; 14+ messages in thread From: Kevin Wolf @ 2012-01-24 9:58 UTC (permalink / raw) To: Takuya Yoshikawa; +Cc: avi, kvm Am 24.01.2012 10:51, schrieb Takuya Yoshikawa: > (2012/01/24 1:07), Kevin Wolf wrote: >> Commit 1d946e07 removed idt, but left a reference to idt in i386-only >> code. >> > > This is already fixed by > > commit b319491d278d4e85de7ea967982f7d416f4a44e4 > desc: fix build for i386 Whoops, my .git/config was still referring to the github URL. Thanks! The other three patches seem to apply to master anyway. Kevin ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:07 [PATCH kvm-unit-tests 0/4] VM86 testcase and run_tests.sh Kevin Wolf ` (2 preceding siblings ...) 2012-01-23 16:07 ` [PATCH kvm-unit-tests 3/4] Fix i386 build Kevin Wolf @ 2012-01-23 16:07 ` Kevin Wolf 2012-01-23 16:10 ` Gleb Natapov 3 siblings, 1 reply; 14+ messages in thread From: Kevin Wolf @ 2012-01-23 16:07 UTC (permalink / raw) To: avi; +Cc: kwolf, kvm This adds a test case that jumps into VM86 by iret-ing to a TSS and back to Protected Mode using a task gate in the IDT. Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- config-i386.mak | 3 +- lib/x86/desc.c | 37 +----------------------------- lib/x86/desc.h | 36 +++++++++++++++++++++++++++++ lib/x86/vm.c | 4 +- lib/x86/vm.h | 1 + x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 6 +++++ 7 files changed, 107 insertions(+), 39 deletions(-) create mode 100644 x86/taskswitch_vm86.c diff --git a/config-i386.mak b/config-i386.mak index de52f3d..b5c3b9c 100644 --- a/config-i386.mak +++ b/config-i386.mak @@ -5,9 +5,10 @@ ldarch = elf32-i386 CFLAGS += -D__i386__ CFLAGS += -I $(KERNELDIR)/include -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat $(TEST_DIR)/taskswitch_vm86.flat include config-x86-common.mak $(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o $(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o +$(TEST_DIR)/taskswitch_vm86.elf: $(cstart.o) $(TEST_DIR)/taskswitch_vm86.o diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 770c250..c4a3607 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -27,41 +27,6 @@ typedef struct { u8 base_high; } gdt_entry_t; -typedef struct { - u16 prev; - u16 res1; - u32 esp0; - u16 ss0; - u16 res2; - u32 esp1; - u16 ss1; - u16 res3; - u32 esp2; - u16 ss2; - u16 res4; - u32 cr3; - u32 eip; - u32 eflags; - u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; - u16 es; - u16 res5; - u16 cs; - u16 res6; - u16 ss; - u16 res7; - u16 ds; - u16 res8; - u16 fs; - u16 res9; - u16 gs; - u16 res10; - u16 ldt; - u16 res11; - u16 t:1; - u16 res12:15; - u16 iomap_base; -} tss32_t; - extern idt_entry_t boot_idt[256]; void set_idt_entry(int vec, void *addr, int dpl) @@ -327,7 +292,7 @@ void setup_gdt(void) ".Lflush2: "::"r"(0x10)); } -static void set_idt_task_gate(int vec, u16 sel) +void set_idt_task_gate(int vec, u16 sel) { idt_entry_t *e = &boot_idt[vec]; diff --git a/lib/x86/desc.h b/lib/x86/desc.h index 0b4897c..f819452 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -24,6 +24,41 @@ struct ex_regs { unsigned long rflags; }; +typedef struct { + u16 prev; + u16 res1; + u32 esp0; + u16 ss0; + u16 res2; + u32 esp1; + u16 ss1; + u16 res3; + u32 esp2; + u16 ss2; + u16 res4; + u32 cr3; + u32 eip; + u32 eflags; + u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; + u16 es; + u16 res5; + u16 cs; + u16 res6; + u16 ss; + u16 res7; + u16 ds; + u16 res8; + u16 fs; + u16 res9; + u16 gs; + u16 res10; + u16 ldt; + u16 res11; + u16 t:1; + u16 res12:15; + u16 iomap_base; +} tss32_t; + #define ASM_TRY(catch) \ "movl $0, %%gs:4 \n\t" \ ".pushsection .data.ex \n\t" \ @@ -44,6 +79,7 @@ unsigned exception_error_code(void); void set_idt_entry(int vec, void *addr, int dpl); void set_idt_sel(int vec, u16 sel); void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); +void set_idt_task_gate(int vec, u16 sel); void set_intr_task_gate(int e, void *fn); void print_current_tss_info(void); void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); diff --git a/lib/x86/vm.c b/lib/x86/vm.c index abbb0c9..aae044a 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -108,14 +108,14 @@ void install_large_page(unsigned long *cr3, unsigned long phys, void *virt) { - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0); + install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); } void install_page(unsigned long *cr3, unsigned long phys, void *virt) { - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0); + install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); } diff --git a/lib/x86/vm.h b/lib/x86/vm.h index bf8fd52..aebc5c3 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -13,6 +13,7 @@ #define PTE_PRESENT (1ull << 0) #define PTE_PSE (1ull << 7) #define PTE_WRITE (1ull << 1) +#define PTE_USER (1ull << 2) #define PTE_ADDR (0xffffffffff000ull) void setup_vm(); diff --git a/x86/taskswitch_vm86.c b/x86/taskswitch_vm86.c new file mode 100644 index 0000000..363cb00 --- /dev/null +++ b/x86/taskswitch_vm86.c @@ -0,0 +1,59 @@ +#include "libcflat.h" +#include "desc.h" +#include "processor.h" +#include "vm.h" + +static tss32_t main_tss; +static tss32_t vm86_tss; + +#define FREE_GDT_INDEX 4 +#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) +#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) + +extern void vm86_start(void); + +int main(void) +{ + u8 *vm86_start; + + setup_vm(); + setup_idt(); + setup_gdt(); + + /* Write a 'ud2' instruction somewhere below 1 MB */ + vm86_start = (void*) 0x42000; + vm86_start[0] = 0x0f; + vm86_start[1] = 0x0b; + + /* Main TSS */ + set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); + ltr(MAIN_TSS_INDEX << 3); + main_tss = (tss32_t) { + .prev = VM86_TSS_INDEX << 3, + .cr3 = read_cr3(), + }; + + /* VM86 TSS (marked as busy, so we can iret to it) */ + set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); + vm86_tss = (tss32_t) { + .eflags = 0x20002, + .cr3 = read_cr3(), + .eip = (u32) vm86_start & 0x0f, + .cs = (u32) vm86_start >> 4, + .ds = 0x1234, + .es = 0x2345, + }; + + /* Setup task gate to main TSS for #UD */ + set_idt_task_gate(6, MAIN_TSS_INDEX << 3); + + /* Jump into VM86 task with iret, #UD lets it come back immediately */ + asm volatile( + "pushf\n" + "orw $0x4000, (%esp)\n" + "popf\n" + "iret\n" + ); + + return 0; +} diff --git a/x86/unittests.cfg b/x86/unittests.cfg index dac7d44..194850b 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -76,6 +76,12 @@ smp = 2 extra_params = -cpu qemu64,-svm groups = task +[taskswitch_vm86] +file = taskswitch_vm86.flat +smp = 2 +extra_params = -cpu qemu64,-svm +groups = task + [kvmclock_test] file = kvmclock_test.flat smp = 2 -- 1.7.6.5 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:07 ` [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 Kevin Wolf @ 2012-01-23 16:10 ` Gleb Natapov 2012-01-23 16:20 ` Kevin Wolf 0 siblings, 1 reply; 14+ messages in thread From: Gleb Natapov @ 2012-01-23 16:10 UTC (permalink / raw) To: Kevin Wolf; +Cc: avi, kvm On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: > This adds a test case that jumps into VM86 by iret-ing to a TSS and back > to Protected Mode using a task gate in the IDT. > Can you add the test case to taskswitch2.c? > Signed-off-by: Kevin Wolf <kwolf@redhat.com> > --- > config-i386.mak | 3 +- > lib/x86/desc.c | 37 +----------------------------- > lib/x86/desc.h | 36 +++++++++++++++++++++++++++++ > lib/x86/vm.c | 4 +- > lib/x86/vm.h | 1 + > x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ > x86/unittests.cfg | 6 +++++ > 7 files changed, 107 insertions(+), 39 deletions(-) > create mode 100644 x86/taskswitch_vm86.c > > diff --git a/config-i386.mak b/config-i386.mak > index de52f3d..b5c3b9c 100644 > --- a/config-i386.mak > +++ b/config-i386.mak > @@ -5,9 +5,10 @@ ldarch = elf32-i386 > CFLAGS += -D__i386__ > CFLAGS += -I $(KERNELDIR)/include > > -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat > +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat $(TEST_DIR)/taskswitch_vm86.flat > > include config-x86-common.mak > > $(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o > $(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o > +$(TEST_DIR)/taskswitch_vm86.elf: $(cstart.o) $(TEST_DIR)/taskswitch_vm86.o > diff --git a/lib/x86/desc.c b/lib/x86/desc.c > index 770c250..c4a3607 100644 > --- a/lib/x86/desc.c > +++ b/lib/x86/desc.c > @@ -27,41 +27,6 @@ typedef struct { > u8 base_high; > } gdt_entry_t; > > -typedef struct { > - u16 prev; > - u16 res1; > - u32 esp0; > - u16 ss0; > - u16 res2; > - u32 esp1; > - u16 ss1; > - u16 res3; > - u32 esp2; > - u16 ss2; > - u16 res4; > - u32 cr3; > - u32 eip; > - u32 eflags; > - u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; > - u16 es; > - u16 res5; > - u16 cs; > - u16 res6; > - u16 ss; > - u16 res7; > - u16 ds; > - u16 res8; > - u16 fs; > - u16 res9; > - u16 gs; > - u16 res10; > - u16 ldt; > - u16 res11; > - u16 t:1; > - u16 res12:15; > - u16 iomap_base; > -} tss32_t; > - > extern idt_entry_t boot_idt[256]; > > void set_idt_entry(int vec, void *addr, int dpl) > @@ -327,7 +292,7 @@ void setup_gdt(void) > ".Lflush2: "::"r"(0x10)); > } > > -static void set_idt_task_gate(int vec, u16 sel) > +void set_idt_task_gate(int vec, u16 sel) > { > idt_entry_t *e = &boot_idt[vec]; > > diff --git a/lib/x86/desc.h b/lib/x86/desc.h > index 0b4897c..f819452 100644 > --- a/lib/x86/desc.h > +++ b/lib/x86/desc.h > @@ -24,6 +24,41 @@ struct ex_regs { > unsigned long rflags; > }; > > +typedef struct { > + u16 prev; > + u16 res1; > + u32 esp0; > + u16 ss0; > + u16 res2; > + u32 esp1; > + u16 ss1; > + u16 res3; > + u32 esp2; > + u16 ss2; > + u16 res4; > + u32 cr3; > + u32 eip; > + u32 eflags; > + u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; > + u16 es; > + u16 res5; > + u16 cs; > + u16 res6; > + u16 ss; > + u16 res7; > + u16 ds; > + u16 res8; > + u16 fs; > + u16 res9; > + u16 gs; > + u16 res10; > + u16 ldt; > + u16 res11; > + u16 t:1; > + u16 res12:15; > + u16 iomap_base; > +} tss32_t; > + > #define ASM_TRY(catch) \ > "movl $0, %%gs:4 \n\t" \ > ".pushsection .data.ex \n\t" \ > @@ -44,6 +79,7 @@ unsigned exception_error_code(void); > void set_idt_entry(int vec, void *addr, int dpl); > void set_idt_sel(int vec, u16 sel); > void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); > +void set_idt_task_gate(int vec, u16 sel); > void set_intr_task_gate(int e, void *fn); > void print_current_tss_info(void); > void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); > diff --git a/lib/x86/vm.c b/lib/x86/vm.c > index abbb0c9..aae044a 100644 > --- a/lib/x86/vm.c > +++ b/lib/x86/vm.c > @@ -108,14 +108,14 @@ void install_large_page(unsigned long *cr3, > unsigned long phys, > void *virt) > { > - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0); > + install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); > } > > void install_page(unsigned long *cr3, > unsigned long phys, > void *virt) > { > - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0); > + install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); > } > > > diff --git a/lib/x86/vm.h b/lib/x86/vm.h > index bf8fd52..aebc5c3 100644 > --- a/lib/x86/vm.h > +++ b/lib/x86/vm.h > @@ -13,6 +13,7 @@ > #define PTE_PRESENT (1ull << 0) > #define PTE_PSE (1ull << 7) > #define PTE_WRITE (1ull << 1) > +#define PTE_USER (1ull << 2) > #define PTE_ADDR (0xffffffffff000ull) > > void setup_vm(); > diff --git a/x86/taskswitch_vm86.c b/x86/taskswitch_vm86.c > new file mode 100644 > index 0000000..363cb00 > --- /dev/null > +++ b/x86/taskswitch_vm86.c > @@ -0,0 +1,59 @@ > +#include "libcflat.h" > +#include "desc.h" > +#include "processor.h" > +#include "vm.h" > + > +static tss32_t main_tss; > +static tss32_t vm86_tss; > + > +#define FREE_GDT_INDEX 4 > +#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) > +#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) > + > +extern void vm86_start(void); > + > +int main(void) > +{ > + u8 *vm86_start; > + > + setup_vm(); > + setup_idt(); > + setup_gdt(); > + > + /* Write a 'ud2' instruction somewhere below 1 MB */ > + vm86_start = (void*) 0x42000; > + vm86_start[0] = 0x0f; > + vm86_start[1] = 0x0b; > + > + /* Main TSS */ > + set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); > + ltr(MAIN_TSS_INDEX << 3); > + main_tss = (tss32_t) { > + .prev = VM86_TSS_INDEX << 3, > + .cr3 = read_cr3(), > + }; > + > + /* VM86 TSS (marked as busy, so we can iret to it) */ > + set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); > + vm86_tss = (tss32_t) { > + .eflags = 0x20002, > + .cr3 = read_cr3(), > + .eip = (u32) vm86_start & 0x0f, > + .cs = (u32) vm86_start >> 4, > + .ds = 0x1234, > + .es = 0x2345, > + }; > + > + /* Setup task gate to main TSS for #UD */ > + set_idt_task_gate(6, MAIN_TSS_INDEX << 3); > + > + /* Jump into VM86 task with iret, #UD lets it come back immediately */ > + asm volatile( > + "pushf\n" > + "orw $0x4000, (%esp)\n" > + "popf\n" > + "iret\n" > + ); > + > + return 0; > +} > diff --git a/x86/unittests.cfg b/x86/unittests.cfg > index dac7d44..194850b 100644 > --- a/x86/unittests.cfg > +++ b/x86/unittests.cfg > @@ -76,6 +76,12 @@ smp = 2 > extra_params = -cpu qemu64,-svm > groups = task > > +[taskswitch_vm86] > +file = taskswitch_vm86.flat > +smp = 2 > +extra_params = -cpu qemu64,-svm > +groups = task > + > [kvmclock_test] > file = kvmclock_test.flat > smp = 2 > -- > 1.7.6.5 > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:10 ` Gleb Natapov @ 2012-01-23 16:20 ` Kevin Wolf 2012-01-23 16:22 ` Gleb Natapov 0 siblings, 1 reply; 14+ messages in thread From: Kevin Wolf @ 2012-01-23 16:20 UTC (permalink / raw) To: Gleb Natapov; +Cc: avi, kvm Am 23.01.2012 17:10, schrieb Gleb Natapov: > On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: >> This adds a test case that jumps into VM86 by iret-ing to a TSS and back >> to Protected Mode using a task gate in the IDT. >> > Can you add the test case to taskswitch2.c? That's actually what I intended to do at first, but there's nothing to share and having a clean environment that can't interfere with other tests feels nicer. What would we gain from merging the files? Kevin > >> Signed-off-by: Kevin Wolf <kwolf@redhat.com> >> --- >> config-i386.mak | 3 +- >> lib/x86/desc.c | 37 +----------------------------- >> lib/x86/desc.h | 36 +++++++++++++++++++++++++++++ >> lib/x86/vm.c | 4 +- >> lib/x86/vm.h | 1 + >> x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ >> x86/unittests.cfg | 6 +++++ >> 7 files changed, 107 insertions(+), 39 deletions(-) >> create mode 100644 x86/taskswitch_vm86.c >> >> diff --git a/config-i386.mak b/config-i386.mak >> index de52f3d..b5c3b9c 100644 >> --- a/config-i386.mak >> +++ b/config-i386.mak >> @@ -5,9 +5,10 @@ ldarch = elf32-i386 >> CFLAGS += -D__i386__ >> CFLAGS += -I $(KERNELDIR)/include >> >> -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat >> +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat $(TEST_DIR)/taskswitch_vm86.flat >> >> include config-x86-common.mak >> >> $(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o >> $(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o >> +$(TEST_DIR)/taskswitch_vm86.elf: $(cstart.o) $(TEST_DIR)/taskswitch_vm86.o >> diff --git a/lib/x86/desc.c b/lib/x86/desc.c >> index 770c250..c4a3607 100644 >> --- a/lib/x86/desc.c >> +++ b/lib/x86/desc.c >> @@ -27,41 +27,6 @@ typedef struct { >> u8 base_high; >> } gdt_entry_t; >> >> -typedef struct { >> - u16 prev; >> - u16 res1; >> - u32 esp0; >> - u16 ss0; >> - u16 res2; >> - u32 esp1; >> - u16 ss1; >> - u16 res3; >> - u32 esp2; >> - u16 ss2; >> - u16 res4; >> - u32 cr3; >> - u32 eip; >> - u32 eflags; >> - u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; >> - u16 es; >> - u16 res5; >> - u16 cs; >> - u16 res6; >> - u16 ss; >> - u16 res7; >> - u16 ds; >> - u16 res8; >> - u16 fs; >> - u16 res9; >> - u16 gs; >> - u16 res10; >> - u16 ldt; >> - u16 res11; >> - u16 t:1; >> - u16 res12:15; >> - u16 iomap_base; >> -} tss32_t; >> - >> extern idt_entry_t boot_idt[256]; >> >> void set_idt_entry(int vec, void *addr, int dpl) >> @@ -327,7 +292,7 @@ void setup_gdt(void) >> ".Lflush2: "::"r"(0x10)); >> } >> >> -static void set_idt_task_gate(int vec, u16 sel) >> +void set_idt_task_gate(int vec, u16 sel) >> { >> idt_entry_t *e = &boot_idt[vec]; >> >> diff --git a/lib/x86/desc.h b/lib/x86/desc.h >> index 0b4897c..f819452 100644 >> --- a/lib/x86/desc.h >> +++ b/lib/x86/desc.h >> @@ -24,6 +24,41 @@ struct ex_regs { >> unsigned long rflags; >> }; >> >> +typedef struct { >> + u16 prev; >> + u16 res1; >> + u32 esp0; >> + u16 ss0; >> + u16 res2; >> + u32 esp1; >> + u16 ss1; >> + u16 res3; >> + u32 esp2; >> + u16 ss2; >> + u16 res4; >> + u32 cr3; >> + u32 eip; >> + u32 eflags; >> + u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; >> + u16 es; >> + u16 res5; >> + u16 cs; >> + u16 res6; >> + u16 ss; >> + u16 res7; >> + u16 ds; >> + u16 res8; >> + u16 fs; >> + u16 res9; >> + u16 gs; >> + u16 res10; >> + u16 ldt; >> + u16 res11; >> + u16 t:1; >> + u16 res12:15; >> + u16 iomap_base; >> +} tss32_t; >> + >> #define ASM_TRY(catch) \ >> "movl $0, %%gs:4 \n\t" \ >> ".pushsection .data.ex \n\t" \ >> @@ -44,6 +79,7 @@ unsigned exception_error_code(void); >> void set_idt_entry(int vec, void *addr, int dpl); >> void set_idt_sel(int vec, u16 sel); >> void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); >> +void set_idt_task_gate(int vec, u16 sel); >> void set_intr_task_gate(int e, void *fn); >> void print_current_tss_info(void); >> void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); >> diff --git a/lib/x86/vm.c b/lib/x86/vm.c >> index abbb0c9..aae044a 100644 >> --- a/lib/x86/vm.c >> +++ b/lib/x86/vm.c >> @@ -108,14 +108,14 @@ void install_large_page(unsigned long *cr3, >> unsigned long phys, >> void *virt) >> { >> - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0); >> + install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); >> } >> >> void install_page(unsigned long *cr3, >> unsigned long phys, >> void *virt) >> { >> - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0); >> + install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); >> } >> >> >> diff --git a/lib/x86/vm.h b/lib/x86/vm.h >> index bf8fd52..aebc5c3 100644 >> --- a/lib/x86/vm.h >> +++ b/lib/x86/vm.h >> @@ -13,6 +13,7 @@ >> #define PTE_PRESENT (1ull << 0) >> #define PTE_PSE (1ull << 7) >> #define PTE_WRITE (1ull << 1) >> +#define PTE_USER (1ull << 2) >> #define PTE_ADDR (0xffffffffff000ull) >> >> void setup_vm(); >> diff --git a/x86/taskswitch_vm86.c b/x86/taskswitch_vm86.c >> new file mode 100644 >> index 0000000..363cb00 >> --- /dev/null >> +++ b/x86/taskswitch_vm86.c >> @@ -0,0 +1,59 @@ >> +#include "libcflat.h" >> +#include "desc.h" >> +#include "processor.h" >> +#include "vm.h" >> + >> +static tss32_t main_tss; >> +static tss32_t vm86_tss; >> + >> +#define FREE_GDT_INDEX 4 >> +#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) >> +#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) >> + >> +extern void vm86_start(void); >> + >> +int main(void) >> +{ >> + u8 *vm86_start; >> + >> + setup_vm(); >> + setup_idt(); >> + setup_gdt(); >> + >> + /* Write a 'ud2' instruction somewhere below 1 MB */ >> + vm86_start = (void*) 0x42000; >> + vm86_start[0] = 0x0f; >> + vm86_start[1] = 0x0b; >> + >> + /* Main TSS */ >> + set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); >> + ltr(MAIN_TSS_INDEX << 3); >> + main_tss = (tss32_t) { >> + .prev = VM86_TSS_INDEX << 3, >> + .cr3 = read_cr3(), >> + }; >> + >> + /* VM86 TSS (marked as busy, so we can iret to it) */ >> + set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); >> + vm86_tss = (tss32_t) { >> + .eflags = 0x20002, >> + .cr3 = read_cr3(), >> + .eip = (u32) vm86_start & 0x0f, >> + .cs = (u32) vm86_start >> 4, >> + .ds = 0x1234, >> + .es = 0x2345, >> + }; >> + >> + /* Setup task gate to main TSS for #UD */ >> + set_idt_task_gate(6, MAIN_TSS_INDEX << 3); >> + >> + /* Jump into VM86 task with iret, #UD lets it come back immediately */ >> + asm volatile( >> + "pushf\n" >> + "orw $0x4000, (%esp)\n" >> + "popf\n" >> + "iret\n" >> + ); >> + >> + return 0; >> +} >> diff --git a/x86/unittests.cfg b/x86/unittests.cfg >> index dac7d44..194850b 100644 >> --- a/x86/unittests.cfg >> +++ b/x86/unittests.cfg >> @@ -76,6 +76,12 @@ smp = 2 >> extra_params = -cpu qemu64,-svm >> groups = task >> >> +[taskswitch_vm86] >> +file = taskswitch_vm86.flat >> +smp = 2 >> +extra_params = -cpu qemu64,-svm >> +groups = task >> + >> [kvmclock_test] >> file = kvmclock_test.flat >> smp = 2 >> -- >> 1.7.6.5 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe kvm" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- > Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:20 ` Kevin Wolf @ 2012-01-23 16:22 ` Gleb Natapov 2012-01-23 16:32 ` Kevin Wolf 0 siblings, 1 reply; 14+ messages in thread From: Gleb Natapov @ 2012-01-23 16:22 UTC (permalink / raw) To: Kevin Wolf; +Cc: avi, kvm On Mon, Jan 23, 2012 at 05:20:22PM +0100, Kevin Wolf wrote: > Am 23.01.2012 17:10, schrieb Gleb Natapov: > > On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: > >> This adds a test case that jumps into VM86 by iret-ing to a TSS and back > >> to Protected Mode using a task gate in the IDT. > >> > > Can you add the test case to taskswitch2.c? > Running one test to check all aspects of taskswitch emulation. > That's actually what I intended to do at first, but there's nothing to > share and having a clean environment that can't interfere with other > tests feels nicer. > > What would we gain from merging the files? > > Kevin > > > > > >> Signed-off-by: Kevin Wolf <kwolf@redhat.com> > >> --- > >> config-i386.mak | 3 +- > >> lib/x86/desc.c | 37 +----------------------------- > >> lib/x86/desc.h | 36 +++++++++++++++++++++++++++++ > >> lib/x86/vm.c | 4 +- > >> lib/x86/vm.h | 1 + > >> x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ > >> x86/unittests.cfg | 6 +++++ > >> 7 files changed, 107 insertions(+), 39 deletions(-) > >> create mode 100644 x86/taskswitch_vm86.c > >> > >> diff --git a/config-i386.mak b/config-i386.mak > >> index de52f3d..b5c3b9c 100644 > >> --- a/config-i386.mak > >> +++ b/config-i386.mak > >> @@ -5,9 +5,10 @@ ldarch = elf32-i386 > >> CFLAGS += -D__i386__ > >> CFLAGS += -I $(KERNELDIR)/include > >> > >> -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat > >> +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat $(TEST_DIR)/taskswitch_vm86.flat > >> > >> include config-x86-common.mak > >> > >> $(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o > >> $(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o > >> +$(TEST_DIR)/taskswitch_vm86.elf: $(cstart.o) $(TEST_DIR)/taskswitch_vm86.o > >> diff --git a/lib/x86/desc.c b/lib/x86/desc.c > >> index 770c250..c4a3607 100644 > >> --- a/lib/x86/desc.c > >> +++ b/lib/x86/desc.c > >> @@ -27,41 +27,6 @@ typedef struct { > >> u8 base_high; > >> } gdt_entry_t; > >> > >> -typedef struct { > >> - u16 prev; > >> - u16 res1; > >> - u32 esp0; > >> - u16 ss0; > >> - u16 res2; > >> - u32 esp1; > >> - u16 ss1; > >> - u16 res3; > >> - u32 esp2; > >> - u16 ss2; > >> - u16 res4; > >> - u32 cr3; > >> - u32 eip; > >> - u32 eflags; > >> - u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; > >> - u16 es; > >> - u16 res5; > >> - u16 cs; > >> - u16 res6; > >> - u16 ss; > >> - u16 res7; > >> - u16 ds; > >> - u16 res8; > >> - u16 fs; > >> - u16 res9; > >> - u16 gs; > >> - u16 res10; > >> - u16 ldt; > >> - u16 res11; > >> - u16 t:1; > >> - u16 res12:15; > >> - u16 iomap_base; > >> -} tss32_t; > >> - > >> extern idt_entry_t boot_idt[256]; > >> > >> void set_idt_entry(int vec, void *addr, int dpl) > >> @@ -327,7 +292,7 @@ void setup_gdt(void) > >> ".Lflush2: "::"r"(0x10)); > >> } > >> > >> -static void set_idt_task_gate(int vec, u16 sel) > >> +void set_idt_task_gate(int vec, u16 sel) > >> { > >> idt_entry_t *e = &boot_idt[vec]; > >> > >> diff --git a/lib/x86/desc.h b/lib/x86/desc.h > >> index 0b4897c..f819452 100644 > >> --- a/lib/x86/desc.h > >> +++ b/lib/x86/desc.h > >> @@ -24,6 +24,41 @@ struct ex_regs { > >> unsigned long rflags; > >> }; > >> > >> +typedef struct { > >> + u16 prev; > >> + u16 res1; > >> + u32 esp0; > >> + u16 ss0; > >> + u16 res2; > >> + u32 esp1; > >> + u16 ss1; > >> + u16 res3; > >> + u32 esp2; > >> + u16 ss2; > >> + u16 res4; > >> + u32 cr3; > >> + u32 eip; > >> + u32 eflags; > >> + u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; > >> + u16 es; > >> + u16 res5; > >> + u16 cs; > >> + u16 res6; > >> + u16 ss; > >> + u16 res7; > >> + u16 ds; > >> + u16 res8; > >> + u16 fs; > >> + u16 res9; > >> + u16 gs; > >> + u16 res10; > >> + u16 ldt; > >> + u16 res11; > >> + u16 t:1; > >> + u16 res12:15; > >> + u16 iomap_base; > >> +} tss32_t; > >> + > >> #define ASM_TRY(catch) \ > >> "movl $0, %%gs:4 \n\t" \ > >> ".pushsection .data.ex \n\t" \ > >> @@ -44,6 +79,7 @@ unsigned exception_error_code(void); > >> void set_idt_entry(int vec, void *addr, int dpl); > >> void set_idt_sel(int vec, u16 sel); > >> void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); > >> +void set_idt_task_gate(int vec, u16 sel); > >> void set_intr_task_gate(int e, void *fn); > >> void print_current_tss_info(void); > >> void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); > >> diff --git a/lib/x86/vm.c b/lib/x86/vm.c > >> index abbb0c9..aae044a 100644 > >> --- a/lib/x86/vm.c > >> +++ b/lib/x86/vm.c > >> @@ -108,14 +108,14 @@ void install_large_page(unsigned long *cr3, > >> unsigned long phys, > >> void *virt) > >> { > >> - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0); > >> + install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); > >> } > >> > >> void install_page(unsigned long *cr3, > >> unsigned long phys, > >> void *virt) > >> { > >> - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0); > >> + install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); > >> } > >> > >> > >> diff --git a/lib/x86/vm.h b/lib/x86/vm.h > >> index bf8fd52..aebc5c3 100644 > >> --- a/lib/x86/vm.h > >> +++ b/lib/x86/vm.h > >> @@ -13,6 +13,7 @@ > >> #define PTE_PRESENT (1ull << 0) > >> #define PTE_PSE (1ull << 7) > >> #define PTE_WRITE (1ull << 1) > >> +#define PTE_USER (1ull << 2) > >> #define PTE_ADDR (0xffffffffff000ull) > >> > >> void setup_vm(); > >> diff --git a/x86/taskswitch_vm86.c b/x86/taskswitch_vm86.c > >> new file mode 100644 > >> index 0000000..363cb00 > >> --- /dev/null > >> +++ b/x86/taskswitch_vm86.c > >> @@ -0,0 +1,59 @@ > >> +#include "libcflat.h" > >> +#include "desc.h" > >> +#include "processor.h" > >> +#include "vm.h" > >> + > >> +static tss32_t main_tss; > >> +static tss32_t vm86_tss; > >> + > >> +#define FREE_GDT_INDEX 4 > >> +#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) > >> +#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) > >> + > >> +extern void vm86_start(void); > >> + > >> +int main(void) > >> +{ > >> + u8 *vm86_start; > >> + > >> + setup_vm(); > >> + setup_idt(); > >> + setup_gdt(); > >> + > >> + /* Write a 'ud2' instruction somewhere below 1 MB */ > >> + vm86_start = (void*) 0x42000; > >> + vm86_start[0] = 0x0f; > >> + vm86_start[1] = 0x0b; > >> + > >> + /* Main TSS */ > >> + set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); > >> + ltr(MAIN_TSS_INDEX << 3); > >> + main_tss = (tss32_t) { > >> + .prev = VM86_TSS_INDEX << 3, > >> + .cr3 = read_cr3(), > >> + }; > >> + > >> + /* VM86 TSS (marked as busy, so we can iret to it) */ > >> + set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); > >> + vm86_tss = (tss32_t) { > >> + .eflags = 0x20002, > >> + .cr3 = read_cr3(), > >> + .eip = (u32) vm86_start & 0x0f, > >> + .cs = (u32) vm86_start >> 4, > >> + .ds = 0x1234, > >> + .es = 0x2345, > >> + }; > >> + > >> + /* Setup task gate to main TSS for #UD */ > >> + set_idt_task_gate(6, MAIN_TSS_INDEX << 3); > >> + > >> + /* Jump into VM86 task with iret, #UD lets it come back immediately */ > >> + asm volatile( > >> + "pushf\n" > >> + "orw $0x4000, (%esp)\n" > >> + "popf\n" > >> + "iret\n" > >> + ); > >> + > >> + return 0; > >> +} > >> diff --git a/x86/unittests.cfg b/x86/unittests.cfg > >> index dac7d44..194850b 100644 > >> --- a/x86/unittests.cfg > >> +++ b/x86/unittests.cfg > >> @@ -76,6 +76,12 @@ smp = 2 > >> extra_params = -cpu qemu64,-svm > >> groups = task > >> > >> +[taskswitch_vm86] > >> +file = taskswitch_vm86.flat > >> +smp = 2 > >> +extra_params = -cpu qemu64,-svm > >> +groups = task > >> + > >> [kvmclock_test] > >> file = kvmclock_test.flat > >> smp = 2 > >> -- > >> 1.7.6.5 > >> > >> -- > >> To unsubscribe from this list: send the line "unsubscribe kvm" in > >> the body of a message to majordomo@vger.kernel.org > >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > -- > > Gleb. -- Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:22 ` Gleb Natapov @ 2012-01-23 16:32 ` Kevin Wolf 2012-01-23 16:42 ` Gleb Natapov 0 siblings, 1 reply; 14+ messages in thread From: Kevin Wolf @ 2012-01-23 16:32 UTC (permalink / raw) To: Gleb Natapov; +Cc: avi, kvm Am 23.01.2012 17:22, schrieb Gleb Natapov: > On Mon, Jan 23, 2012 at 05:20:22PM +0100, Kevin Wolf wrote: >> Am 23.01.2012 17:10, schrieb Gleb Natapov: >>> On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: >>>> This adds a test case that jumps into VM86 by iret-ing to a TSS and back >>>> to Protected Mode using a task gate in the IDT. >>>> >>> Can you add the test case to taskswitch2.c? >> > Running one test to check all aspects of taskswitch emulation. (We all know that top-posting is disliked, but middle-posting looks even crazier!) Does having one test provide any value in and of itself? It's just an implementation detail of the test suite. When testing the KVM patches I ran all three test cases with './run_tests.sh -g task', which is hopefully easy enough. Kevin > >> That's actually what I intended to do at first, but there's nothing to >> share and having a clean environment that can't interfere with other >> tests feels nicer. >> >> What would we gain from merging the files? >> >> Kevin >> >> >>> >>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com> >>>> --- >>>> config-i386.mak | 3 +- >>>> lib/x86/desc.c | 37 +----------------------------- >>>> lib/x86/desc.h | 36 +++++++++++++++++++++++++++++ >>>> lib/x86/vm.c | 4 +- >>>> lib/x86/vm.h | 1 + >>>> x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ >>>> x86/unittests.cfg | 6 +++++ >>>> 7 files changed, 107 insertions(+), 39 deletions(-) >>>> create mode 100644 x86/taskswitch_vm86.c >>>> >>>> diff --git a/config-i386.mak b/config-i386.mak >>>> index de52f3d..b5c3b9c 100644 >>>> --- a/config-i386.mak >>>> +++ b/config-i386.mak >>>> @@ -5,9 +5,10 @@ ldarch = elf32-i386 >>>> CFLAGS += -D__i386__ >>>> CFLAGS += -I $(KERNELDIR)/include >>>> >>>> -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat >>>> +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat $(TEST_DIR)/taskswitch_vm86.flat >>>> >>>> include config-x86-common.mak >>>> >>>> $(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o >>>> $(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o >>>> +$(TEST_DIR)/taskswitch_vm86.elf: $(cstart.o) $(TEST_DIR)/taskswitch_vm86.o >>>> diff --git a/lib/x86/desc.c b/lib/x86/desc.c >>>> index 770c250..c4a3607 100644 >>>> --- a/lib/x86/desc.c >>>> +++ b/lib/x86/desc.c >>>> @@ -27,41 +27,6 @@ typedef struct { >>>> u8 base_high; >>>> } gdt_entry_t; >>>> >>>> -typedef struct { >>>> - u16 prev; >>>> - u16 res1; >>>> - u32 esp0; >>>> - u16 ss0; >>>> - u16 res2; >>>> - u32 esp1; >>>> - u16 ss1; >>>> - u16 res3; >>>> - u32 esp2; >>>> - u16 ss2; >>>> - u16 res4; >>>> - u32 cr3; >>>> - u32 eip; >>>> - u32 eflags; >>>> - u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; >>>> - u16 es; >>>> - u16 res5; >>>> - u16 cs; >>>> - u16 res6; >>>> - u16 ss; >>>> - u16 res7; >>>> - u16 ds; >>>> - u16 res8; >>>> - u16 fs; >>>> - u16 res9; >>>> - u16 gs; >>>> - u16 res10; >>>> - u16 ldt; >>>> - u16 res11; >>>> - u16 t:1; >>>> - u16 res12:15; >>>> - u16 iomap_base; >>>> -} tss32_t; >>>> - >>>> extern idt_entry_t boot_idt[256]; >>>> >>>> void set_idt_entry(int vec, void *addr, int dpl) >>>> @@ -327,7 +292,7 @@ void setup_gdt(void) >>>> ".Lflush2: "::"r"(0x10)); >>>> } >>>> >>>> -static void set_idt_task_gate(int vec, u16 sel) >>>> +void set_idt_task_gate(int vec, u16 sel) >>>> { >>>> idt_entry_t *e = &boot_idt[vec]; >>>> >>>> diff --git a/lib/x86/desc.h b/lib/x86/desc.h >>>> index 0b4897c..f819452 100644 >>>> --- a/lib/x86/desc.h >>>> +++ b/lib/x86/desc.h >>>> @@ -24,6 +24,41 @@ struct ex_regs { >>>> unsigned long rflags; >>>> }; >>>> >>>> +typedef struct { >>>> + u16 prev; >>>> + u16 res1; >>>> + u32 esp0; >>>> + u16 ss0; >>>> + u16 res2; >>>> + u32 esp1; >>>> + u16 ss1; >>>> + u16 res3; >>>> + u32 esp2; >>>> + u16 ss2; >>>> + u16 res4; >>>> + u32 cr3; >>>> + u32 eip; >>>> + u32 eflags; >>>> + u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; >>>> + u16 es; >>>> + u16 res5; >>>> + u16 cs; >>>> + u16 res6; >>>> + u16 ss; >>>> + u16 res7; >>>> + u16 ds; >>>> + u16 res8; >>>> + u16 fs; >>>> + u16 res9; >>>> + u16 gs; >>>> + u16 res10; >>>> + u16 ldt; >>>> + u16 res11; >>>> + u16 t:1; >>>> + u16 res12:15; >>>> + u16 iomap_base; >>>> +} tss32_t; >>>> + >>>> #define ASM_TRY(catch) \ >>>> "movl $0, %%gs:4 \n\t" \ >>>> ".pushsection .data.ex \n\t" \ >>>> @@ -44,6 +79,7 @@ unsigned exception_error_code(void); >>>> void set_idt_entry(int vec, void *addr, int dpl); >>>> void set_idt_sel(int vec, u16 sel); >>>> void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); >>>> +void set_idt_task_gate(int vec, u16 sel); >>>> void set_intr_task_gate(int e, void *fn); >>>> void print_current_tss_info(void); >>>> void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); >>>> diff --git a/lib/x86/vm.c b/lib/x86/vm.c >>>> index abbb0c9..aae044a 100644 >>>> --- a/lib/x86/vm.c >>>> +++ b/lib/x86/vm.c >>>> @@ -108,14 +108,14 @@ void install_large_page(unsigned long *cr3, >>>> unsigned long phys, >>>> void *virt) >>>> { >>>> - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0); >>>> + install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); >>>> } >>>> >>>> void install_page(unsigned long *cr3, >>>> unsigned long phys, >>>> void *virt) >>>> { >>>> - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0); >>>> + install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); >>>> } >>>> >>>> >>>> diff --git a/lib/x86/vm.h b/lib/x86/vm.h >>>> index bf8fd52..aebc5c3 100644 >>>> --- a/lib/x86/vm.h >>>> +++ b/lib/x86/vm.h >>>> @@ -13,6 +13,7 @@ >>>> #define PTE_PRESENT (1ull << 0) >>>> #define PTE_PSE (1ull << 7) >>>> #define PTE_WRITE (1ull << 1) >>>> +#define PTE_USER (1ull << 2) >>>> #define PTE_ADDR (0xffffffffff000ull) >>>> >>>> void setup_vm(); >>>> diff --git a/x86/taskswitch_vm86.c b/x86/taskswitch_vm86.c >>>> new file mode 100644 >>>> index 0000000..363cb00 >>>> --- /dev/null >>>> +++ b/x86/taskswitch_vm86.c >>>> @@ -0,0 +1,59 @@ >>>> +#include "libcflat.h" >>>> +#include "desc.h" >>>> +#include "processor.h" >>>> +#include "vm.h" >>>> + >>>> +static tss32_t main_tss; >>>> +static tss32_t vm86_tss; >>>> + >>>> +#define FREE_GDT_INDEX 4 >>>> +#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) >>>> +#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) >>>> + >>>> +extern void vm86_start(void); >>>> + >>>> +int main(void) >>>> +{ >>>> + u8 *vm86_start; >>>> + >>>> + setup_vm(); >>>> + setup_idt(); >>>> + setup_gdt(); >>>> + >>>> + /* Write a 'ud2' instruction somewhere below 1 MB */ >>>> + vm86_start = (void*) 0x42000; >>>> + vm86_start[0] = 0x0f; >>>> + vm86_start[1] = 0x0b; >>>> + >>>> + /* Main TSS */ >>>> + set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); >>>> + ltr(MAIN_TSS_INDEX << 3); >>>> + main_tss = (tss32_t) { >>>> + .prev = VM86_TSS_INDEX << 3, >>>> + .cr3 = read_cr3(), >>>> + }; >>>> + >>>> + /* VM86 TSS (marked as busy, so we can iret to it) */ >>>> + set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); >>>> + vm86_tss = (tss32_t) { >>>> + .eflags = 0x20002, >>>> + .cr3 = read_cr3(), >>>> + .eip = (u32) vm86_start & 0x0f, >>>> + .cs = (u32) vm86_start >> 4, >>>> + .ds = 0x1234, >>>> + .es = 0x2345, >>>> + }; >>>> + >>>> + /* Setup task gate to main TSS for #UD */ >>>> + set_idt_task_gate(6, MAIN_TSS_INDEX << 3); >>>> + >>>> + /* Jump into VM86 task with iret, #UD lets it come back immediately */ >>>> + asm volatile( >>>> + "pushf\n" >>>> + "orw $0x4000, (%esp)\n" >>>> + "popf\n" >>>> + "iret\n" >>>> + ); >>>> + >>>> + return 0; >>>> +} >>>> diff --git a/x86/unittests.cfg b/x86/unittests.cfg >>>> index dac7d44..194850b 100644 >>>> --- a/x86/unittests.cfg >>>> +++ b/x86/unittests.cfg >>>> @@ -76,6 +76,12 @@ smp = 2 >>>> extra_params = -cpu qemu64,-svm >>>> groups = task >>>> >>>> +[taskswitch_vm86] >>>> +file = taskswitch_vm86.flat >>>> +smp = 2 >>>> +extra_params = -cpu qemu64,-svm >>>> +groups = task >>>> + >>>> [kvmclock_test] >>>> file = kvmclock_test.flat >>>> smp = 2 >>>> -- >>>> 1.7.6.5 >>>> >>>> -- >>>> To unsubscribe from this list: send the line "unsubscribe kvm" in >>>> the body of a message to majordomo@vger.kernel.org >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>> >>> -- >>> Gleb. > > -- > Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:32 ` Kevin Wolf @ 2012-01-23 16:42 ` Gleb Natapov 2012-01-24 10:14 ` Kevin Wolf 0 siblings, 1 reply; 14+ messages in thread From: Gleb Natapov @ 2012-01-23 16:42 UTC (permalink / raw) To: Kevin Wolf; +Cc: avi, kvm On Mon, Jan 23, 2012 at 05:32:59PM +0100, Kevin Wolf wrote: > Am 23.01.2012 17:22, schrieb Gleb Natapov: > > On Mon, Jan 23, 2012 at 05:20:22PM +0100, Kevin Wolf wrote: > >> Am 23.01.2012 17:10, schrieb Gleb Natapov: > >>> On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: > >>>> This adds a test case that jumps into VM86 by iret-ing to a TSS and back > >>>> to Protected Mode using a task gate in the IDT. > >>>> > >>> Can you add the test case to taskswitch2.c? > >> > > Running one test to check all aspects of taskswitch emulation. > > (We all know that top-posting is disliked, but middle-posting looks even > crazier!) > Inserting replies at random places is a new cool thing! > Does having one test provide any value in and of itself? It's just an > implementation detail of the test suite. When testing the KVM patches I > ran all three test cases with './run_tests.sh -g task', which is > hopefully easy enough. > I think it does. I do not have to use external script to combine tests on the same topic or even remember that such script exists. We do not create separate tests to test each instruction emulation either. And I usually run qemu not on the same machine I compile it on, so I need special tricks to make those test script work. Of course if putting this code into existing test file is hard separate test is OK, but is this really the case here? > Kevin > > > > >> That's actually what I intended to do at first, but there's nothing to > >> share and having a clean environment that can't interfere with other > >> tests feels nicer. > >> > >> What would we gain from merging the files? > >> > >> Kevin > >> > >> > >>> > >>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com> > >>>> --- > >>>> config-i386.mak | 3 +- > >>>> lib/x86/desc.c | 37 +----------------------------- > >>>> lib/x86/desc.h | 36 +++++++++++++++++++++++++++++ > >>>> lib/x86/vm.c | 4 +- > >>>> lib/x86/vm.h | 1 + > >>>> x86/taskswitch_vm86.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ > >>>> x86/unittests.cfg | 6 +++++ > >>>> 7 files changed, 107 insertions(+), 39 deletions(-) > >>>> create mode 100644 x86/taskswitch_vm86.c > >>>> > >>>> diff --git a/config-i386.mak b/config-i386.mak > >>>> index de52f3d..b5c3b9c 100644 > >>>> --- a/config-i386.mak > >>>> +++ b/config-i386.mak > >>>> @@ -5,9 +5,10 @@ ldarch = elf32-i386 > >>>> CFLAGS += -D__i386__ > >>>> CFLAGS += -I $(KERNELDIR)/include > >>>> > >>>> -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat > >>>> +tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat $(TEST_DIR)/taskswitch_vm86.flat > >>>> > >>>> include config-x86-common.mak > >>>> > >>>> $(TEST_DIR)/taskswitch.elf: $(cstart.o) $(TEST_DIR)/taskswitch.o > >>>> $(TEST_DIR)/taskswitch2.elf: $(cstart.o) $(TEST_DIR)/taskswitch2.o > >>>> +$(TEST_DIR)/taskswitch_vm86.elf: $(cstart.o) $(TEST_DIR)/taskswitch_vm86.o > >>>> diff --git a/lib/x86/desc.c b/lib/x86/desc.c > >>>> index 770c250..c4a3607 100644 > >>>> --- a/lib/x86/desc.c > >>>> +++ b/lib/x86/desc.c > >>>> @@ -27,41 +27,6 @@ typedef struct { > >>>> u8 base_high; > >>>> } gdt_entry_t; > >>>> > >>>> -typedef struct { > >>>> - u16 prev; > >>>> - u16 res1; > >>>> - u32 esp0; > >>>> - u16 ss0; > >>>> - u16 res2; > >>>> - u32 esp1; > >>>> - u16 ss1; > >>>> - u16 res3; > >>>> - u32 esp2; > >>>> - u16 ss2; > >>>> - u16 res4; > >>>> - u32 cr3; > >>>> - u32 eip; > >>>> - u32 eflags; > >>>> - u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; > >>>> - u16 es; > >>>> - u16 res5; > >>>> - u16 cs; > >>>> - u16 res6; > >>>> - u16 ss; > >>>> - u16 res7; > >>>> - u16 ds; > >>>> - u16 res8; > >>>> - u16 fs; > >>>> - u16 res9; > >>>> - u16 gs; > >>>> - u16 res10; > >>>> - u16 ldt; > >>>> - u16 res11; > >>>> - u16 t:1; > >>>> - u16 res12:15; > >>>> - u16 iomap_base; > >>>> -} tss32_t; > >>>> - > >>>> extern idt_entry_t boot_idt[256]; > >>>> > >>>> void set_idt_entry(int vec, void *addr, int dpl) > >>>> @@ -327,7 +292,7 @@ void setup_gdt(void) > >>>> ".Lflush2: "::"r"(0x10)); > >>>> } > >>>> > >>>> -static void set_idt_task_gate(int vec, u16 sel) > >>>> +void set_idt_task_gate(int vec, u16 sel) > >>>> { > >>>> idt_entry_t *e = &boot_idt[vec]; > >>>> > >>>> diff --git a/lib/x86/desc.h b/lib/x86/desc.h > >>>> index 0b4897c..f819452 100644 > >>>> --- a/lib/x86/desc.h > >>>> +++ b/lib/x86/desc.h > >>>> @@ -24,6 +24,41 @@ struct ex_regs { > >>>> unsigned long rflags; > >>>> }; > >>>> > >>>> +typedef struct { > >>>> + u16 prev; > >>>> + u16 res1; > >>>> + u32 esp0; > >>>> + u16 ss0; > >>>> + u16 res2; > >>>> + u32 esp1; > >>>> + u16 ss1; > >>>> + u16 res3; > >>>> + u32 esp2; > >>>> + u16 ss2; > >>>> + u16 res4; > >>>> + u32 cr3; > >>>> + u32 eip; > >>>> + u32 eflags; > >>>> + u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; > >>>> + u16 es; > >>>> + u16 res5; > >>>> + u16 cs; > >>>> + u16 res6; > >>>> + u16 ss; > >>>> + u16 res7; > >>>> + u16 ds; > >>>> + u16 res8; > >>>> + u16 fs; > >>>> + u16 res9; > >>>> + u16 gs; > >>>> + u16 res10; > >>>> + u16 ldt; > >>>> + u16 res11; > >>>> + u16 t:1; > >>>> + u16 res12:15; > >>>> + u16 iomap_base; > >>>> +} tss32_t; > >>>> + > >>>> #define ASM_TRY(catch) \ > >>>> "movl $0, %%gs:4 \n\t" \ > >>>> ".pushsection .data.ex \n\t" \ > >>>> @@ -44,6 +79,7 @@ unsigned exception_error_code(void); > >>>> void set_idt_entry(int vec, void *addr, int dpl); > >>>> void set_idt_sel(int vec, u16 sel); > >>>> void set_gdt_entry(int num, u32 base, u32 limit, u8 access, u8 gran); > >>>> +void set_idt_task_gate(int vec, u16 sel); > >>>> void set_intr_task_gate(int e, void *fn); > >>>> void print_current_tss_info(void); > >>>> void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); > >>>> diff --git a/lib/x86/vm.c b/lib/x86/vm.c > >>>> index abbb0c9..aae044a 100644 > >>>> --- a/lib/x86/vm.c > >>>> +++ b/lib/x86/vm.c > >>>> @@ -108,14 +108,14 @@ void install_large_page(unsigned long *cr3, > >>>> unsigned long phys, > >>>> void *virt) > >>>> { > >>>> - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_PSE, 0); > >>>> + install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); > >>>> } > >>>> > >>>> void install_page(unsigned long *cr3, > >>>> unsigned long phys, > >>>> void *virt) > >>>> { > >>>> - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE, 0); > >>>> + install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); > >>>> } > >>>> > >>>> > >>>> diff --git a/lib/x86/vm.h b/lib/x86/vm.h > >>>> index bf8fd52..aebc5c3 100644 > >>>> --- a/lib/x86/vm.h > >>>> +++ b/lib/x86/vm.h > >>>> @@ -13,6 +13,7 @@ > >>>> #define PTE_PRESENT (1ull << 0) > >>>> #define PTE_PSE (1ull << 7) > >>>> #define PTE_WRITE (1ull << 1) > >>>> +#define PTE_USER (1ull << 2) > >>>> #define PTE_ADDR (0xffffffffff000ull) > >>>> > >>>> void setup_vm(); > >>>> diff --git a/x86/taskswitch_vm86.c b/x86/taskswitch_vm86.c > >>>> new file mode 100644 > >>>> index 0000000..363cb00 > >>>> --- /dev/null > >>>> +++ b/x86/taskswitch_vm86.c > >>>> @@ -0,0 +1,59 @@ > >>>> +#include "libcflat.h" > >>>> +#include "desc.h" > >>>> +#include "processor.h" > >>>> +#include "vm.h" > >>>> + > >>>> +static tss32_t main_tss; > >>>> +static tss32_t vm86_tss; > >>>> + > >>>> +#define FREE_GDT_INDEX 4 > >>>> +#define MAIN_TSS_INDEX (FREE_GDT_INDEX + 0) > >>>> +#define VM86_TSS_INDEX (FREE_GDT_INDEX + 1) > >>>> + > >>>> +extern void vm86_start(void); > >>>> + > >>>> +int main(void) > >>>> +{ > >>>> + u8 *vm86_start; > >>>> + > >>>> + setup_vm(); > >>>> + setup_idt(); > >>>> + setup_gdt(); > >>>> + > >>>> + /* Write a 'ud2' instruction somewhere below 1 MB */ > >>>> + vm86_start = (void*) 0x42000; > >>>> + vm86_start[0] = 0x0f; > >>>> + vm86_start[1] = 0x0b; > >>>> + > >>>> + /* Main TSS */ > >>>> + set_gdt_entry(MAIN_TSS_INDEX, (u32)&main_tss, sizeof(tss32_t) - 1, 0x89, 0); > >>>> + ltr(MAIN_TSS_INDEX << 3); > >>>> + main_tss = (tss32_t) { > >>>> + .prev = VM86_TSS_INDEX << 3, > >>>> + .cr3 = read_cr3(), > >>>> + }; > >>>> + > >>>> + /* VM86 TSS (marked as busy, so we can iret to it) */ > >>>> + set_gdt_entry(VM86_TSS_INDEX, (u32)&vm86_tss, sizeof(tss32_t) - 1, 0x8b, 0); > >>>> + vm86_tss = (tss32_t) { > >>>> + .eflags = 0x20002, > >>>> + .cr3 = read_cr3(), > >>>> + .eip = (u32) vm86_start & 0x0f, > >>>> + .cs = (u32) vm86_start >> 4, > >>>> + .ds = 0x1234, > >>>> + .es = 0x2345, > >>>> + }; > >>>> + > >>>> + /* Setup task gate to main TSS for #UD */ > >>>> + set_idt_task_gate(6, MAIN_TSS_INDEX << 3); > >>>> + > >>>> + /* Jump into VM86 task with iret, #UD lets it come back immediately */ > >>>> + asm volatile( > >>>> + "pushf\n" > >>>> + "orw $0x4000, (%esp)\n" > >>>> + "popf\n" > >>>> + "iret\n" > >>>> + ); > >>>> + > >>>> + return 0; > >>>> +} > >>>> diff --git a/x86/unittests.cfg b/x86/unittests.cfg > >>>> index dac7d44..194850b 100644 > >>>> --- a/x86/unittests.cfg > >>>> +++ b/x86/unittests.cfg > >>>> @@ -76,6 +76,12 @@ smp = 2 > >>>> extra_params = -cpu qemu64,-svm > >>>> groups = task > >>>> > >>>> +[taskswitch_vm86] > >>>> +file = taskswitch_vm86.flat > >>>> +smp = 2 > >>>> +extra_params = -cpu qemu64,-svm > >>>> +groups = task > >>>> + > >>>> [kvmclock_test] > >>>> file = kvmclock_test.flat > >>>> smp = 2 > >>>> -- > >>>> 1.7.6.5 > >>>> > >>>> -- > >>>> To unsubscribe from this list: send the line "unsubscribe kvm" in > >>>> the body of a message to majordomo@vger.kernel.org > >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html > >>> > >>> -- > >>> Gleb. > > > > -- > > Gleb. -- Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-23 16:42 ` Gleb Natapov @ 2012-01-24 10:14 ` Kevin Wolf 2012-01-24 10:26 ` Gleb Natapov 0 siblings, 1 reply; 14+ messages in thread From: Kevin Wolf @ 2012-01-24 10:14 UTC (permalink / raw) To: Gleb Natapov; +Cc: avi, kvm Am 23.01.2012 17:42, schrieb Gleb Natapov: > On Mon, Jan 23, 2012 at 05:32:59PM +0100, Kevin Wolf wrote: >> Am 23.01.2012 17:22, schrieb Gleb Natapov: >>> On Mon, Jan 23, 2012 at 05:20:22PM +0100, Kevin Wolf wrote: >>>> Am 23.01.2012 17:10, schrieb Gleb Natapov: >>>>> On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: >>>>>> This adds a test case that jumps into VM86 by iret-ing to a TSS and back >>>>>> to Protected Mode using a task gate in the IDT. >>>>>> >>>>> Can you add the test case to taskswitch2.c? >>>> >>> Running one test to check all aspects of taskswitch emulation. >> >> (We all know that top-posting is disliked, but middle-posting looks even >> crazier!) >> > Inserting replies Very true! > at random places is a new cool thing! > >> Does having one test provide any value in and of itself? It's just an >> implementation detail of the test suite. When testing the KVM patches I >> ran all three test cases with './run_tests.sh -g task', which is >> hopefully easy enough. >> > I think it does. I do not have to use external script to combine tests > on the same topic or even remember that such script exists. We do not > create separate tests to test each instruction emulation either. And I > usually run qemu not on the same machine I compile it on, so I need > special tricks to make those test script work. Of course if putting this > code into existing test file is hard separate test is OK, but is this > really the case here? I haven't really checked whether they interfere. I guess I would have to move the GDT indexes for my manually created TSSes and I would have to hope that nobody else needs the memory I'm overwriting with the real mode code (there doesn't seem to be memory management for < 1 MB). Should taskswitch.c and taskswitch2.c be merged as well then? Or is there a reason why they must stay separate? One file or three files makes sense to me for three tests, but two not so much. Kevin ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 2012-01-24 10:14 ` Kevin Wolf @ 2012-01-24 10:26 ` Gleb Natapov 0 siblings, 0 replies; 14+ messages in thread From: Gleb Natapov @ 2012-01-24 10:26 UTC (permalink / raw) To: Kevin Wolf; +Cc: avi, kvm On Tue, Jan 24, 2012 at 11:14:23AM +0100, Kevin Wolf wrote: > Am 23.01.2012 17:42, schrieb Gleb Natapov: > > On Mon, Jan 23, 2012 at 05:32:59PM +0100, Kevin Wolf wrote: > >> Am 23.01.2012 17:22, schrieb Gleb Natapov: > >>> On Mon, Jan 23, 2012 at 05:20:22PM +0100, Kevin Wolf wrote: > >>>> Am 23.01.2012 17:10, schrieb Gleb Natapov: > >>>>> On Mon, Jan 23, 2012 at 05:07:13PM +0100, Kevin Wolf wrote: > >>>>>> This adds a test case that jumps into VM86 by iret-ing to a TSS and back > >>>>>> to Protected Mode using a task gate in the IDT. > >>>>>> > >>>>> Can you add the test case to taskswitch2.c? > >>>> > >>> Running one test to check all aspects of taskswitch emulation. > >> > >> (We all know that top-posting is disliked, but middle-posting looks even > >> crazier!) > >> > > Inserting replies > > Very true! > :) > > at random places is a new cool thing! > > > >> Does having one test provide any value in and of itself? It's just an > >> implementation detail of the test suite. When testing the KVM patches I > >> ran all three test cases with './run_tests.sh -g task', which is > >> hopefully easy enough. > >> > > I think it does. I do not have to use external script to combine tests > > on the same topic or even remember that such script exists. We do not > > create separate tests to test each instruction emulation either. And I > > usually run qemu not on the same machine I compile it on, so I need > > special tricks to make those test script work. Of course if putting this > > code into existing test file is hard separate test is OK, but is this > > really the case here? > > I haven't really checked whether they interfere. I guess I would have to > move the GDT indexes for my manually created TSSes and I would have to > hope that nobody else needs the memory I'm overwriting with the real > mode code (there doesn't seem to be memory management for < 1 MB). > You can add function alloc_vpage_low(). Other tests may find it useful. > Should taskswitch.c and taskswitch2.c be merged as well then? Or is > there a reason why they must stay separate? One file or three files > makes sense to me for three tests, but two not so much. > taskswitch.c should be removed. It tests nothing that taskswitch2.c does not check as far as I see. -- Gleb. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2012-01-24 10:26 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-01-23 16:07 [PATCH kvm-unit-tests 0/4] VM86 testcase and run_tests.sh Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 1/4] Add run_tests.sh Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 2/4] Add taskswitch testcases to unittest.cfg Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 3/4] Fix i386 build Kevin Wolf 2012-01-24 9:51 ` Takuya Yoshikawa 2012-01-24 9:58 ` Kevin Wolf 2012-01-23 16:07 ` [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86 Kevin Wolf 2012-01-23 16:10 ` Gleb Natapov 2012-01-23 16:20 ` Kevin Wolf 2012-01-23 16:22 ` Gleb Natapov 2012-01-23 16:32 ` Kevin Wolf 2012-01-23 16:42 ` Gleb Natapov 2012-01-24 10:14 ` Kevin Wolf 2012-01-24 10:26 ` Gleb Natapov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox