Re: [PATCH] kvm test: Add 32-bit task switch micro-test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx>
> ---
> 
> 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.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux