Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
---
 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


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to