From: Kevin Wolf <kwolf@redhat.com>
To: Gleb Natapov <gleb@redhat.com>
Cc: avi@redhat.com, kvm@vger.kernel.org
Subject: Re: [PATCH kvm-unit-tests 4/4] x86/taskswitch_vm86: Task switches into/out of VM86
Date: Mon, 23 Jan 2012 17:32:59 +0100 [thread overview]
Message-ID: <4F1D8BBB.1010907@redhat.com> (raw)
In-Reply-To: <20120123162222.GB12119@redhat.com>
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.
next prev parent reply other threads:[~2012-01-23 16:29 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2012-01-23 16:42 ` Gleb Natapov
2012-01-24 10:14 ` Kevin Wolf
2012-01-24 10:26 ` Gleb Natapov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F1D8BBB.1010907@redhat.com \
--to=kwolf@redhat.com \
--cc=avi@redhat.com \
--cc=gleb@redhat.com \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox