x86/vdso/doc: Make vDSO examples more portable

This adds a new vdso_test.c that's written entirely in C.  It also
makes all of the vDSO examples work on 32-bit x86.

Cc: Stefani Seibold <stefani@seibold.net>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/62b701fc44b79f118ac2b2d64d19965fc5c291fb.1402620737.git.luto@amacapital.net
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/Documentation/vDSO/vdso_standalone_test_x86.c b/Documentation/vDSO/vdso_standalone_test_x86.c
index 1523f5d..d462402 100644
--- a/Documentation/vDSO/vdso_standalone_test_x86.c
+++ b/Documentation/vDSO/vdso_standalone_test_x86.c
@@ -1,13 +1,14 @@
 /*
- * vdso_test.c: Sample code to test parse_vdso.c on x86_64
- * Copyright (c) 2011 Andy Lutomirski
+ * vdso_test.c: Sample code to test parse_vdso.c on x86
+ * Copyright (c) 2011-2014 Andy Lutomirski
  * Subject to the GNU General Public License, version 2
  *
  * You can amuse yourself by compiling with:
  * gcc -std=gnu99 -nostdlib
- *     -Os -fno-asynchronous-unwind-tables -flto
+ *     -Os -fno-asynchronous-unwind-tables -flto -lgcc_s
  *      vdso_standalone_test_x86.c parse_vdso.c
- * to generate a small binary with no dependencies at all.
+ * to generate a small binary.  On x86_64, you can omit -lgcc_s
+ * if you want the binary to be completely standalone.
  */
 
 #include <sys/syscall.h>
@@ -35,21 +36,31 @@
 	return 0;
 }
 
-/* ...and two syscalls.  This is x86_64-specific. */
-static inline long linux_write(int fd, const void *data, size_t len)
+/* ...and two syscalls.  This is x86-specific. */
+static inline long x86_syscall3(long nr, long a0, long a1, long a2)
 {
-
 	long ret;
-	asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write),
-		      "D" (fd), "S" (data), "d" (len) :
+#ifdef __x86_64__
+	asm volatile ("syscall" : "=a" (ret) : "a" (nr),
+		      "D" (a0), "S" (a1), "d" (a2) :
 		      "cc", "memory", "rcx",
 		      "r8", "r9", "r10", "r11" );
+#else
+	asm volatile ("int $0x80" : "=a" (ret) : "a" (nr),
+		      "b" (a0), "c" (a1), "d" (a2) :
+		      "cc", "memory" );
+#endif
 	return ret;
 }
 
+static inline long linux_write(int fd, const void *data, size_t len)
+{
+	return x86_syscall3(__NR_write, fd, (long)data, (long)len);
+}
+
 static inline void linux_exit(int code)
 {
-	asm volatile ("syscall" : : "a" (__NR_exit), "D" (code));
+	x86_syscall3(__NR_exit, code, 0, 0);
 }
 
 void to_base10(char *lastdig, uint64_t n)
@@ -104,8 +115,14 @@
 asm (
 	".text\n"
 	".global _start\n"
-        ".type _start,@function\n"
-        "_start:\n\t"
-        "mov %rsp,%rdi\n\t"
-        "jmp c_main"
+	".type _start,@function\n"
+	"_start:\n\t"
+#ifdef __x86_64__
+	"mov %rsp,%rdi\n\t"
+	"jmp c_main"
+#else
+	"push %esp\n\t"
+	"call c_main\n\t"
+	"int $3"
+#endif
 	);