On Tue, Dec 15, 2015 at 11:25:35AM +0100, Paolo Bonzini wrote: > Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> > --- > config/config-i386.mak | 2 ++ > config/config-x86-common.mak | 4 +++- > config/config-x86_64.mak | 2 ++ > lib/setjmp.h | 12 ++++++++++++ > lib/x86/setjmp32.S | 25 +++++++++++++++++++++++++ > lib/x86/setjmp64.S | 27 +++++++++++++++++++++++++++ > x86/setjmp.c | 19 +++++++++++++++++++ > 7 files changed, 90 insertions(+), 1 deletion(-) > create mode 100644 lib/setjmp.h > create mode 100644 lib/x86/setjmp32.S > create mode 100644 lib/x86/setjmp64.S > create mode 100644 x86/setjmp.c > > diff --git a/config/config-i386.mak b/config/config-i386.mak > index 691381c..e353387 100644 > --- a/config/config-i386.mak > +++ b/config/config-i386.mak > @@ -3,6 +3,8 @@ bits = 32 > ldarch = elf32-i386 > CFLAGS += -I $(KERNELDIR)/include > > +cflatobjs += lib/x86/setjmp32.o > + > tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat \ > $(TEST_DIR)/cmpxchg8b.flat > > diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak > index f64874d..2bb2f46 100644 > --- a/config/config-x86-common.mak > +++ b/config/config-x86-common.mak > @@ -34,7 +34,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ > $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ > $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ > $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \ > - $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat \ > + $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat $(TEST_DIR)/setjmp.flat \ > $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ > $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ > $(TEST_DIR)/hyperv_synic.flat > @@ -115,6 +115,8 @@ $(TEST_DIR)/memory.elf: $(cstart.o) $(TEST_DIR)/memory.o > > $(TEST_DIR)/hyperv_synic.elf: $(cstart.o) $(TEST_DIR)/hyperv_synic.o > > +$(TEST_DIR)/setjmp.elf: $(cstart.o) $(TEST_DIR)/setjmp.o > + > arch_clean: > $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ > $(TEST_DIR)/.*.d lib/x86/.*.d > diff --git a/config/config-x86_64.mak b/config/config-x86_64.mak > index 1764701..d190be8 100644 > --- a/config/config-x86_64.mak > +++ b/config/config-x86_64.mak > @@ -3,6 +3,8 @@ bits = 64 > ldarch = elf64-x86-64 > CFLAGS += -mno-red-zone > > +cflatobjs += lib/x86/setjmp64.o > + > tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ > $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \ > $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \ > diff --git a/lib/setjmp.h b/lib/setjmp.h > new file mode 100644 > index 0000000..334f466 > --- /dev/null > +++ b/lib/setjmp.h > @@ -0,0 +1,12 @@ > +#ifndef LIBCFLAT_SETJMP_H > +#define LIBCFLAT_SETJMP_H 1 > + > +typedef struct jmp_buf_tag { > + long int regs[8]; > +} jmp_buf[1]; > + > +extern int setjmp (struct jmp_buf_tag env[1]); > +extern void longjmp (struct jmp_buf_tag env[1], int val) > + __attribute__ ((__noreturn__)); > + > +#endif /* setjmp.h */ > diff --git a/lib/x86/setjmp32.S b/lib/x86/setjmp32.S > new file mode 100644 > index 0000000..b0be7c2 > --- /dev/null > +++ b/lib/x86/setjmp32.S > @@ -0,0 +1,25 @@ > +.globl setjmp > +setjmp: > + mov (%esp), %ecx // get return EIP > + mov 4(%esp), %eax // get jmp_buf > + mov %ecx, (%eax) > + mov %esp, 4(%eax) > + mov %ebp, 8(%eax) > + mov %ebx, 12(%eax) > + mov %esi, 16(%eax) > + mov %edi, 20(%eax) > + xor %eax, %eax > + ret > + > +.globl longjmp > +longjmp: > + mov 8(%esp), %eax // get return value > + mov 4(%esp), %ecx // get jmp_buf > + mov 20(%ecx), %edi > + mov 16(%ecx), %esi > + mov 12(%ecx), %ebx > + mov 8(%ecx), %ebp > + mov 4(%ecx), %esp > + mov (%ecx), %ecx // get saved EIP > + mov %ecx, (%esp) // and store it on the stack > + ret > diff --git a/lib/x86/setjmp64.S b/lib/x86/setjmp64.S > new file mode 100644 > index 0000000..c8ae790 > --- /dev/null > +++ b/lib/x86/setjmp64.S > @@ -0,0 +1,27 @@ > +.globl setjmp > +setjmp: > + mov (%rsp), %rsi > + mov %rsi, (%rdi) > + mov %rsp, 0x8(%rdi) > + mov %rbp, 0x10(%rdi) > + mov %rbx, 0x18(%rdi) > + mov %r12, 0x20(%rdi) > + mov %r13, 0x28(%rdi) > + mov %r14, 0x30(%rdi) > + mov %r15, 0x38(%rdi) > + xor %eax, %eax > + ret > + > +.globl longjmp > +longjmp: > + mov %esi, %eax > + mov 0x38(%rdi), %r15 > + mov 0x30(%rdi), %r14 > + mov 0x28(%rdi), %r13 > + mov 0x20(%rdi), %r12 > + mov 0x18(%rdi), %rbx > + mov 0x10(%rdi), %rbp > + mov 0x8(%rdi), %rsp > + mov (%rdi), %rsi > + mov %rsi, (%rsp) > + ret > diff --git a/x86/setjmp.c b/x86/setjmp.c > new file mode 100644 > index 0000000..46f0d9c > --- /dev/null > +++ b/x86/setjmp.c > @@ -0,0 +1,19 @@ > +#include "stdio.h" > +#include "setjmp.h" > + > +int main() > +{ > + volatile int i; > + jmp_buf j; > + > + if (setjmp(j) == 0) { > + i = 0; > + } > + printf("%d\n", i); > + if (++i < 10) { > + longjmp(j, 1); > + } > + > + printf("done\n"); > + return 0; How about making this a "real" test, i.e. report("longjmp", i == 10); return report_summary(); I have patches that allow adding timeouts to tests, that I've been thinking about posting upstream. With those we could add a short timeout to this one, allowing us to get the FAIL when we loop forever, as well as when we never loop. Thanks, drew > +} > -- > 2.5.0 > > > -- > 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 -- 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