Signed-off-by: Paolo Bonzini <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html