All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gleb Natapov <gleb@redhat.com>
To: Kevin Wolf <kwolf@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 18:10:17 +0200	[thread overview]
Message-ID: <20120123161017.GA12119@redhat.com> (raw)
In-Reply-To: <1327334833-31650-5-git-send-email-kwolf@redhat.com>

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.

  reply	other threads:[~2012-01-23 16:10 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 [this message]
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

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=20120123161017.GA12119@redhat.com \
    --to=gleb@redhat.com \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=kwolf@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.