All of lore.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 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.