public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
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.

  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