From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paolo Bonzini Subject: [PATCH kvm-unit-tests 1/4] lib: add setjmp header and x86 implementation Date: Tue, 15 Dec 2015 11:25:35 +0100 Message-ID: <1450175138-1140-2-git-send-email-pbonzini@redhat.com> References: <1450175138-1140-1-git-send-email-pbonzini@redhat.com> Cc: dmatlack@google.com To: kvm@vger.kernel.org Return-path: Received: from mail-wm0-f49.google.com ([74.125.82.49]:37204 "EHLO mail-wm0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964848AbbLOKZx (ORCPT ); Tue, 15 Dec 2015 05:25:53 -0500 Received: by mail-wm0-f49.google.com with SMTP id n186so18470222wmn.0 for ; Tue, 15 Dec 2015 02:25:52 -0800 (PST) In-Reply-To: <1450175138-1140-1-git-send-email-pbonzini@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: Signed-off-by: Paolo Bonzini --- 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; +} -- 2.5.0