]> git.karo-electronics.de Git - linux-beck.git/commitdiff
selftests/powerpc: Test the preservation of FPU and VMX regs across syscall
authorCyril Bur <cyrilbur@gmail.com>
Mon, 29 Feb 2016 06:53:43 +0000 (17:53 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 2 Mar 2016 12:34:46 +0000 (23:34 +1100)
Test that the non volatile floating point and Altivec registers get
correctly preserved across the fork() syscall.

fork() works nicely for this purpose, the registers should be the same for
both parent and child

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
[mpe: Add include guards to basic_asm.h, minor formatting]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
tools/testing/selftests/powerpc/Makefile
tools/testing/selftests/powerpc/basic_asm.h [new file with mode: 0644]
tools/testing/selftests/powerpc/math/.gitignore [new file with mode: 0644]
tools/testing/selftests/powerpc/math/Makefile [new file with mode: 0644]
tools/testing/selftests/powerpc/math/fpu_asm.S [new file with mode: 0644]
tools/testing/selftests/powerpc/math/fpu_syscall.c [new file with mode: 0644]
tools/testing/selftests/powerpc/math/vmx_asm.S [new file with mode: 0644]
tools/testing/selftests/powerpc/math/vmx_syscall.c [new file with mode: 0644]

index 7925a9655bfbcdc8be0f7df1bb59e4962874bf09..b08f77cbe31ba72baf5e773866dc8d488622a0b7 100644 (file)
@@ -22,7 +22,8 @@ SUB_DIRS = benchmarks                 \
           switch_endian        \
           syscalls             \
           tm                   \
-          vphn
+          vphn         \
+          math
 
 endif
 
diff --git a/tools/testing/selftests/powerpc/basic_asm.h b/tools/testing/selftests/powerpc/basic_asm.h
new file mode 100644 (file)
index 0000000..3349a07
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _SELFTESTS_POWERPC_BASIC_ASM_H
+#define _SELFTESTS_POWERPC_BASIC_ASM_H
+
+#include <ppc-asm.h>
+#include <asm/unistd.h>
+
+#define LOAD_REG_IMMEDIATE(reg,expr) \
+       lis     reg,(expr)@highest;     \
+       ori     reg,reg,(expr)@higher;  \
+       rldicr  reg,reg,32,31;  \
+       oris    reg,reg,(expr)@high;    \
+       ori     reg,reg,(expr)@l;
+
+/*
+ * Note: These macros assume that variables being stored on the stack are
+ * doublewords, while this is usually the case it may not always be the
+ * case for each use case.
+ */
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+#define STACK_FRAME_MIN_SIZE 32
+#define STACK_FRAME_TOC_POS  24
+#define __STACK_FRAME_PARAM(_param)  (32 + ((_param)*8))
+#define __STACK_FRAME_LOCAL(_num_params,_var_num)  ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8))
+#else
+#define STACK_FRAME_MIN_SIZE 112
+#define STACK_FRAME_TOC_POS  40
+#define __STACK_FRAME_PARAM(i)  (48 + ((i)*8))
+
+/*
+ * Caveat: if a function passed more than 8 doublewords, the caller will have
+ * made more space... which would render the 112 incorrect.
+ */
+#define __STACK_FRAME_LOCAL(_num_params,_var_num)  (112 + ((_var_num)*8))
+#endif
+
+/* Parameter x saved to the stack */
+#define STACK_FRAME_PARAM(var)    __STACK_FRAME_PARAM(var)
+
+/* Local variable x saved to the stack after x parameters */
+#define STACK_FRAME_LOCAL(num_params,var)    __STACK_FRAME_LOCAL(num_params,var)
+#define STACK_FRAME_LR_POS   16
+#define STACK_FRAME_CR_POS   8
+
+/*
+ * It is very important to note here that _extra is the extra amount of
+ * stack space needed. This space can be accessed using STACK_FRAME_PARAM()
+ * or STACK_FRAME_LOCAL() macros.
+ *
+ * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp
+ * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence
+ * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets
+ * preprocessed incorrectly, hence r0.
+ */
+#define PUSH_BASIC_STACK(_extra) \
+       mflr    r0; \
+       std     r0,STACK_FRAME_LR_POS(%r1); \
+       stdu    %r1,-(_extra + STACK_FRAME_MIN_SIZE)(%r1); \
+       mfcr    r0; \
+       stw     r0,STACK_FRAME_CR_POS(%r1); \
+       std     %r2,STACK_FRAME_TOC_POS(%r1);
+
+#define POP_BASIC_STACK(_extra) \
+       ld      %r2,STACK_FRAME_TOC_POS(%r1); \
+       lwz     r0,STACK_FRAME_CR_POS(%r1); \
+       mtcr    r0; \
+       addi    %r1,%r1,(_extra + STACK_FRAME_MIN_SIZE); \
+       ld      r0,STACK_FRAME_LR_POS(%r1); \
+       mtlr    r0;
+
+#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */
diff --git a/tools/testing/selftests/powerpc/math/.gitignore b/tools/testing/selftests/powerpc/math/.gitignore
new file mode 100644 (file)
index 0000000..b19b269
--- /dev/null
@@ -0,0 +1,2 @@
+fpu_syscall
+vmx_syscall
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
new file mode 100644 (file)
index 0000000..418bef1
--- /dev/null
@@ -0,0 +1,14 @@
+TEST_PROGS := fpu_syscall vmx_syscall
+
+all: $(TEST_PROGS)
+
+$(TEST_PROGS): ../harness.c
+$(TEST_PROGS): CFLAGS += -O2 -g -pthread -m64 -maltivec
+
+fpu_syscall: fpu_asm.S
+vmx_syscall: vmx_asm.S
+
+include ../../lib.mk
+
+clean:
+       rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S
new file mode 100644 (file)
index 0000000..7617da3
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "../basic_asm.h"
+
+#define PUSH_FPU(pos) \
+       stfd    f14,pos(sp); \
+       stfd    f15,pos+8(sp); \
+       stfd    f16,pos+16(sp); \
+       stfd    f17,pos+24(sp); \
+       stfd    f18,pos+32(sp); \
+       stfd    f19,pos+40(sp); \
+       stfd    f20,pos+48(sp); \
+       stfd    f21,pos+56(sp); \
+       stfd    f22,pos+64(sp); \
+       stfd    f23,pos+72(sp); \
+       stfd    f24,pos+80(sp); \
+       stfd    f25,pos+88(sp); \
+       stfd    f26,pos+96(sp); \
+       stfd    f27,pos+104(sp); \
+       stfd    f28,pos+112(sp); \
+       stfd    f29,pos+120(sp); \
+       stfd    f30,pos+128(sp); \
+       stfd    f31,pos+136(sp);
+
+#define POP_FPU(pos) \
+       lfd     f14,pos(sp); \
+       lfd     f15,pos+8(sp); \
+       lfd     f16,pos+16(sp); \
+       lfd     f17,pos+24(sp); \
+       lfd     f18,pos+32(sp); \
+       lfd     f19,pos+40(sp); \
+       lfd     f20,pos+48(sp); \
+       lfd     f21,pos+56(sp); \
+       lfd     f22,pos+64(sp); \
+       lfd     f23,pos+72(sp); \
+       lfd     f24,pos+80(sp); \
+       lfd     f25,pos+88(sp); \
+       lfd     f26,pos+96(sp); \
+       lfd     f27,pos+104(sp); \
+       lfd     f28,pos+112(sp); \
+       lfd     f29,pos+120(sp); \
+       lfd     f30,pos+128(sp); \
+       lfd     f31,pos+136(sp);
+
+# Careful calling this, it will 'clobber' fpu (by design)
+# Don't call this from C
+FUNC_START(load_fpu)
+       lfd     f14,0(r3)
+       lfd     f15,8(r3)
+       lfd     f16,16(r3)
+       lfd     f17,24(r3)
+       lfd     f18,32(r3)
+       lfd     f19,40(r3)
+       lfd     f20,48(r3)
+       lfd     f21,56(r3)
+       lfd     f22,64(r3)
+       lfd     f23,72(r3)
+       lfd     f24,80(r3)
+       lfd     f25,88(r3)
+       lfd     f26,96(r3)
+       lfd     f27,104(r3)
+       lfd     f28,112(r3)
+       lfd     f29,120(r3)
+       lfd     f30,128(r3)
+       lfd     f31,136(r3)
+       blr
+FUNC_END(load_fpu)
+
+FUNC_START(check_fpu)
+       mr r4,r3
+       li      r3,1 # assume a bad result
+       lfd     f0,0(r4)
+       fcmpu   cr1,f0,f14
+       bne     cr1,1f
+       lfd     f0,8(r4)
+       fcmpu   cr1,f0,f15
+       bne     cr1,1f
+       lfd     f0,16(r4)
+       fcmpu   cr1,f0,f16
+       bne     cr1,1f
+       lfd     f0,24(r4)
+       fcmpu   cr1,f0,f17
+       bne     cr1,1f
+       lfd     f0,32(r4)
+       fcmpu   cr1,f0,f18
+       bne     cr1,1f
+       lfd     f0,40(r4)
+       fcmpu   cr1,f0,f19
+       bne     cr1,1f
+       lfd     f0,48(r4)
+       fcmpu   cr1,f0,f20
+       bne     cr1,1f
+       lfd     f0,56(r4)
+       fcmpu   cr1,f0,f21
+       bne     cr1,1f
+       lfd     f0,64(r4)
+       fcmpu   cr1,f0,f22
+       bne     cr1,1f
+       lfd     f0,72(r4)
+       fcmpu   cr1,f0,f23
+       bne     cr1,1f
+       lfd     f0,80(r4)
+       fcmpu   cr1,f0,f24
+       bne     cr1,1f
+       lfd     f0,88(r4)
+       fcmpu   cr1,f0,f25
+       bne     cr1,1f
+       lfd     f0,96(r4)
+       fcmpu   cr1,f0,f26
+       bne     cr1,1f
+       lfd     f0,104(r4)
+       fcmpu   cr1,f0,f27
+       bne     cr1,1f
+       lfd     f0,112(r4)
+       fcmpu   cr1,f0,f28
+       bne     cr1,1f
+       lfd     f0,120(r4)
+       fcmpu   cr1,f0,f29
+       bne     cr1,1f
+       lfd     f0,128(r4)
+       fcmpu   cr1,f0,f30
+       bne     cr1,1f
+       lfd     f0,136(r4)
+       fcmpu   cr1,f0,f31
+       bne     cr1,1f
+       li      r3,0 # Success!!!
+1:     blr
+
+FUNC_START(test_fpu)
+       # r3 holds pointer to where to put the result of fork
+       # r4 holds pointer to the pid
+       # f14-f31 are non volatiles
+       PUSH_BASIC_STACK(256)
+       std     r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
+       std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
+       PUSH_FPU(STACK_FRAME_LOCAL(2,0))
+
+       bl load_fpu
+       nop
+       li      r0,__NR_fork
+       sc
+
+       # pass the result of the fork to the caller
+       ld      r9,STACK_FRAME_PARAM(1)(sp)
+       std     r3,0(r9)
+
+       ld r3,STACK_FRAME_PARAM(0)(sp)
+       bl check_fpu
+       nop
+
+       POP_FPU(STACK_FRAME_LOCAL(2,0))
+       POP_BASIC_STACK(256)
+       blr
+FUNC_END(test_fpu)
diff --git a/tools/testing/selftests/powerpc/math/fpu_syscall.c b/tools/testing/selftests/powerpc/math/fpu_syscall.c
new file mode 100644 (file)
index 0000000..949e672
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the FPU registers change across a syscall (fork).
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+extern int test_fpu(double *darray, pid_t *pid);
+
+double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
+                    1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
+                    2.1};
+
+int syscall_fpu(void)
+{
+       pid_t fork_pid;
+       int i;
+       int ret;
+       int child_ret;
+       for (i = 0; i < 1000; i++) {
+               /* test_fpu will fork() */
+               ret = test_fpu(darray, &fork_pid);
+               if (fork_pid == -1)
+                       return -1;
+               if (fork_pid == 0)
+                       exit(ret);
+               waitpid(fork_pid, &child_ret, 0);
+               if (ret || child_ret)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int test_syscall_fpu(void)
+{
+       /*
+        * Setup an environment with much context switching
+        */
+       pid_t pid2;
+       pid_t pid = fork();
+       int ret;
+       int child_ret;
+       FAIL_IF(pid == -1);
+
+       pid2 = fork();
+       /* Can't FAIL_IF(pid2 == -1); because already forked once */
+       if (pid2 == -1) {
+               /*
+                * Couldn't fork, ensure test is a fail
+                */
+               child_ret = ret = 1;
+       } else {
+               ret = syscall_fpu();
+               if (pid2)
+                       waitpid(pid2, &child_ret, 0);
+               else
+                       exit(ret);
+       }
+
+       ret |= child_ret;
+
+       if (pid)
+               waitpid(pid, &child_ret, 0);
+       else
+               exit(ret);
+
+       FAIL_IF(ret || child_ret);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_syscall_fpu, "syscall_fpu");
+
+}
diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S
new file mode 100644 (file)
index 0000000..4ce6421
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "../basic_asm.h"
+
+#define PUSH_VMX(pos,reg) \
+       li      reg,pos; \
+       stvx    v20,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v21,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v22,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v23,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v24,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v25,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v26,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v27,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v28,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v29,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v30,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v31,reg,sp;
+
+#define POP_VMX(pos,reg) \
+       li      reg,pos; \
+       lvx     v20,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v21,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v22,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v23,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v24,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v25,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v26,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v27,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v28,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v29,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v30,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v31,reg,sp;
+
+# Carefull this will 'clobber' vmx (by design)
+# Don't call this from C
+FUNC_START(load_vmx)
+       li      r5,0
+       lvx     v20,r5,r3
+       addi    r5,r5,16
+       lvx     v21,r5,r3
+       addi    r5,r5,16
+       lvx     v22,r5,r3
+       addi    r5,r5,16
+       lvx     v23,r5,r3
+       addi    r5,r5,16
+       lvx     v24,r5,r3
+       addi    r5,r5,16
+       lvx     v25,r5,r3
+       addi    r5,r5,16
+       lvx     v26,r5,r3
+       addi    r5,r5,16
+       lvx     v27,r5,r3
+       addi    r5,r5,16
+       lvx     v28,r5,r3
+       addi    r5,r5,16
+       lvx     v29,r5,r3
+       addi    r5,r5,16
+       lvx     v30,r5,r3
+       addi    r5,r5,16
+       lvx     v31,r5,r3
+       blr
+FUNC_END(load_vmx)
+
+# Should be safe from C, only touches r4, r5 and v0,v1,v2
+FUNC_START(check_vmx)
+       PUSH_BASIC_STACK(16)
+       mr r4,r3
+       li      r3,1 # assume a bad result
+       li      r5,0
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v20
+       vmr     v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v21
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v22
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v23
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v24
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v25
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v26
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v27
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v28
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v29
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v30
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v31
+       vand    v2,v2,v1
+
+       li      r5,STACK_FRAME_LOCAL(0,0)
+       stvx    v2,r5,sp
+       ldx     r0,r5,sp
+       cmpdi   r0,0xffffffffffffffff
+       bne     1f
+       li      r3,0
+1:     POP_BASIC_STACK(16)
+       blr
+FUNC_END(check_vmx)
+
+# Safe from C
+FUNC_START(test_vmx)
+       # r3 holds pointer to where to put the result of fork
+       # r4 holds pointer to the pid
+       # v20-v31 are non-volatile
+       PUSH_BASIC_STACK(512)
+       std     r3,STACK_FRAME_PARAM(0)(sp) # Address of varray
+       std r4,STACK_FRAME_PARAM(1)(sp) # address of pid
+       PUSH_VMX(STACK_FRAME_LOCAL(2,0),r4)
+
+       bl load_vmx
+       nop
+
+       li      r0,__NR_fork
+       sc
+       # Pass the result of fork back to the caller
+       ld      r9,STACK_FRAME_PARAM(1)(sp)
+       std     r3,0(r9)
+
+       ld r3,STACK_FRAME_PARAM(0)(sp)
+       bl check_vmx
+       nop
+
+       POP_VMX(STACK_FRAME_LOCAL(2,0),r4)
+       POP_BASIC_STACK(512)
+       blr
+FUNC_END(test_vmx)
diff --git a/tools/testing/selftests/powerpc/math/vmx_syscall.c b/tools/testing/selftests/powerpc/math/vmx_syscall.c
new file mode 100644 (file)
index 0000000..a017918
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the VMX registers change across a syscall (fork).
+ */
+
+#include <altivec.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "utils.h"
+
+vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
+       {13,14,15,16},{17,18,19,20},{21,22,23,24},
+       {25,26,27,28},{29,30,31,32},{33,34,35,36},
+       {37,38,39,40},{41,42,43,44},{45,46,47,48}};
+
+extern int test_vmx(vector int *varray, pid_t *pid);
+
+int vmx_syscall(void)
+{
+       pid_t fork_pid;
+       int i;
+       int ret;
+       int child_ret;
+       for (i = 0; i < 1000; i++) {
+               /* test_vmx will fork() */
+               ret = test_vmx(varray, &fork_pid);
+               if (fork_pid == -1)
+                       return -1;
+               if (fork_pid == 0)
+                       exit(ret);
+               waitpid(fork_pid, &child_ret, 0);
+               if (ret || child_ret)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int test_vmx_syscall(void)
+{
+       /*
+        * Setup an environment with much context switching
+        */
+       pid_t pid2;
+       pid_t pid = fork();
+       int ret;
+       int child_ret;
+       FAIL_IF(pid == -1);
+
+       pid2 = fork();
+       ret = vmx_syscall();
+       /* Can't FAIL_IF(pid2 == -1); because we've already forked */
+       if (pid2 == -1) {
+               /*
+                * Couldn't fork, ensure child_ret is set and is a fail
+                */
+               ret = child_ret = 1;
+       } else {
+               if (pid2)
+                       waitpid(pid2, &child_ret, 0);
+               else
+                       exit(ret);
+       }
+
+       ret |= child_ret;
+
+       if (pid)
+               waitpid(pid, &child_ret, 0);
+       else
+               exit(ret);
+
+       FAIL_IF(ret || child_ret);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_vmx_syscall, "vmx_syscall");
+
+}