From: Gleb Natapov <gleb@redhat.com>
To: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Avi Kivity <avi@redhat.com>,
Marcelo Tosatti <mtosatti@redhat.com>, kvm <kvm@vger.kernel.org>
Subject: Re: [PATCH] kvm test: Add 32-bit task switch micro-test
Date: Wed, 14 Apr 2010 17:37:39 +0300 [thread overview]
Message-ID: <20100414143739.GC18132@redhat.com> (raw)
In-Reply-To: <4BC5CD5E.6000608@siemens.com>
On Wed, Apr 14, 2010 at 04:12:46PM +0200, Jan Kiszka wrote:
> This implements a basic task switch test for 32-bit targets. It
> specifically stresses the case that a fault with attached error code
> triggers the switch via a task gate.
>
How do you compile this? I was sure kvm test suit is broken for 32 bit
code.
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>
> Gleb, you might want to have a look at this test. When using it with my
> 2.6.34 queue (or below or with QEMU), I get the following, expected
> output:
>
> fault at 8:4002ef, prev task 18, error code 1234
> post fault
>
> When using it with master + my error-code patch, I get this:
>
> fault at 8:4002ef, prev task 18, error code 1234
>
> post fault
>
> I.e. there is blank line, a repeated 0x0a character after returning from
> the fault handler. I'm suspecting that IO string rework triggers this.
> Instrumentation of the testdev showed that the spurious puts() was
> emitted over the instruction that the fault handler returns to. Any
> ideas?
>
> kvm/user/config-i386.mak | 4 +-
> kvm/user/test/x86/taskswitch.c | 164 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 167 insertions(+), 1 deletions(-)
> create mode 100644 kvm/user/test/x86/taskswitch.c
>
> diff --git a/kvm/user/config-i386.mak b/kvm/user/config-i386.mak
> index 09175d5..a9becfc 100644
> --- a/kvm/user/config-i386.mak
> +++ b/kvm/user/config-i386.mak
> @@ -5,6 +5,8 @@ ldarch = elf32-i386
> CFLAGS += -D__i386__
> CFLAGS += -I $(KERNELDIR)/include
>
> -tests=
> +tests = $(TEST_DIR)/taskswitch.flat
>
> include config-x86-common.mak
> +
> +$(TEST_DIR)/taskswitch.flat: $(cstart.o) $(TEST_DIR)/taskswitch.o
> diff --git a/kvm/user/test/x86/taskswitch.c b/kvm/user/test/x86/taskswitch.c
> new file mode 100644
> index 0000000..8ed8a93
> --- /dev/null
> +++ b/kvm/user/test/x86/taskswitch.c
> @@ -0,0 +1,164 @@
> +/*
> + * Copyright 2010 Siemens AG
> + * Author: Jan Kiszka
> + *
> + * Released under GPLv2.
> + */
> +
> +#include "libcflat.h"
> +
> +#define FIRST_SPARE_SEL 0x18
> +
> +struct exception_frame {
> + unsigned long error_code;
> + unsigned long ip;
> + unsigned long cs;
> + unsigned long flags;
> +};
> +
> +struct tss32 {
> + unsigned short prev;
> + unsigned short res1;
> + unsigned long esp0;
> + unsigned short ss0;
> + unsigned short res2;
> + unsigned long esp1;
> + unsigned short ss1;
> + unsigned short res3;
> + unsigned long esp2;
> + unsigned short ss2;
> + unsigned short res4;
> + unsigned long cr3;
> + unsigned long eip;
> + unsigned long eflags;
> + unsigned long eax, ecx, edx, ebx, esp, ebp, esi, edi;
> + unsigned short es;
> + unsigned short res5;
> + unsigned short cs;
> + unsigned short res6;
> + unsigned short ss;
> + unsigned short res7;
> + unsigned short ds;
> + unsigned short res8;
> + unsigned short fs;
> + unsigned short res9;
> + unsigned short gs;
> + unsigned short res10;
> + unsigned short ldt;
> + unsigned short res11;
> + unsigned short t:1;
> + unsigned short res12:15;
> + unsigned short iomap_base;
> +};
> +
> +static char main_stack[4096];
> +static char fault_stack[4096];
> +static struct tss32 main_tss;
> +static struct tss32 fault_tss;
> +
> +static unsigned long long gdt[] __attribute__((aligned(16))) = {
> + 0,
> + 0x00cf9b000000ffffull,
> + 0x00cf93000000ffffull,
> + 0, 0, /* TSS segments */
> + 0, /* task return gate */
> +};
> +
> +static unsigned long long gdtr;
> +
> +void fault_entry(void);
> +
> +static __attribute__((used, regparm(1))) void
> +fault_handler(unsigned long error_code)
> +{
> + unsigned short *desc;
> +
> + printf("fault at %x:%x, prev task %x, error code %x\n",
> + main_tss.cs, main_tss.eip, fault_tss.prev, error_code);
> +
> + main_tss.eip += 2;
> +
> + desc = (unsigned short *)&gdt[3];
> + desc[2] &= ~0x0200;
> +
> + desc = (unsigned short *)&gdt[5];
> + desc[0] = 0;
> + desc[1] = fault_tss.prev;
> + desc[2] = 0x8500;
> + desc[3] = 0;
> +}
> +
> +asm (
> + "fault_entry:\n"
> + " mov (%esp),%eax\n"
> + " call fault_handler\n"
> + " jmp $0x28, $0\n"
> +);
> +
> +static void setup_tss(struct tss32 *tss, void *entry,
> + void *stack_base, unsigned long stack_size)
> +{
> + unsigned long cr3;
> + unsigned short cs, ds;
> +
> + asm ("mov %%cr3,%0" : "=r" (cr3));
> + asm ("mov %%cs,%0" : "=r" (cs));
> + asm ("mov %%ds,%0" : "=r" (ds));
> +
> + tss->ss0 = tss->ss1 = tss->ss2 = tss->ss = ds;
> + tss->esp0 = tss->esp1 = tss->esp2 = tss->esp =
> + (unsigned long)stack_base + stack_size;
> + tss->ds = tss->es = tss->fs = tss->gs = ds;
> + tss->cs = cs;
> + tss->eip = (unsigned long)entry;
> + tss->cr3 = cr3;
> +}
> +
> +static void setup_tss_desc(unsigned short tss_sel, struct tss32 *tss)
> +{
> + unsigned long addr = (unsigned long)tss;
> + unsigned short *desc;
> +
> + desc = (unsigned short *)&gdt[tss_sel/8];
> + desc[0] = sizeof(*tss) - 1;
> + desc[1] = addr;
> + desc[2] = 0x8900 | ((addr & 0x00ff0000) >> 16);
> + desc[3] = (addr & 0xff000000) >> 16;
> +}
> +
> +static void set_intr_task(unsigned short tss_sel, int intr, struct tss32 *tss)
> +{
> + unsigned short *desc = (void *)(intr* sizeof(long) * 2);
> +
> + setup_tss_desc(tss_sel, tss);
> +
> + desc[0] = 0;
> + desc[1] = tss_sel;
> + desc[2] = 0x8500;
> + desc[3] = 0;
> +}
> +
> +int main(int ac, char **av)
> +{
> + const long invalid_segment = 0x1234;
> +
> + gdtr = ((unsigned long long)(unsigned long)&gdt << 16) |
> + (sizeof(gdt) - 1);
> + asm ("lgdt %0" : : "m" (gdtr));
> +
> + setup_tss(&main_tss, 0, main_stack, sizeof(main_stack));
> + setup_tss_desc(FIRST_SPARE_SEL, &main_tss);
> + asm ("ltr %0" : : "r" ((unsigned short)FIRST_SPARE_SEL));
> +
> + setup_tss(&fault_tss, fault_entry, fault_stack, sizeof(fault_stack));
> + set_intr_task(FIRST_SPARE_SEL+8, 13, &fault_tss);
> +
> + asm (
> + "mov %0,%%es\n"
> + : : "r" (invalid_segment) : "edi"
> + );
> +
> + printf("post fault\n");
> +
> + return 0;
> +}
--
Gleb.
next prev parent reply other threads:[~2010-04-14 14:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-14 14:12 [PATCH] kvm test: Add 32-bit task switch micro-test Jan Kiszka
2010-04-14 14:37 ` Gleb Natapov [this message]
2010-04-14 14:41 ` Jan Kiszka
2010-04-14 14:46 ` Gleb Natapov
2010-04-14 17:22 ` Gleb Natapov
2010-04-14 19:55 ` Jan Kiszka
2010-04-15 16:45 ` Marcelo Tosatti
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=20100414143739.GC18132@redhat.com \
--to=gleb@redhat.com \
--cc=avi@redhat.com \
--cc=jan.kiszka@siemens.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox