enable clone system call for x86

Add __bionic_clone function for x86, which will be
used for clone system call.

Change-Id: I889dc9bf4b7ebb4358476e17e6f3233e26491f4d
Signed-off-by: Jin Wei <wei.a.jin@intel.com>
Signed-off-by: Xiaokang Qin <xiaokang.qin@intel.com>
Signed-off-by: Beare, Bruce J <bruce.j.beare@intel.com>
Signed-off-by: Jack Ren <jack.ren@intel.com>
Author-tracking-BZ: 51414
diff --git a/libc/Android.mk b/libc/Android.mk
index 51cef8a..c66ec59 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -261,6 +261,7 @@
 	tzcode/strftime.c \
 	tzcode/strptime.c \
 	bionic/__set_errno.c \
+	bionic/bionic_clone.c \
 	bionic/cpuacct.c \
 	bionic/arc4random.c \
 	bionic/basename.c \
@@ -361,7 +362,6 @@
 # =========================================================
 ifeq ($(TARGET_ARCH),arm)
 libc_common_src_files += \
-	bionic/bionic_clone.c \
 	arch-arm/bionic/__get_pc.S \
 	arch-arm/bionic/__get_sp.S \
 	arch-arm/bionic/_exit_with_stack_teardown.S \
@@ -451,7 +451,6 @@
 
 ifeq ($(TARGET_ARCH),mips)
 libc_common_src_files += \
-	bionic/bionic_clone.c \
 	arch-mips/bionic/__get_sp.S \
 	arch-mips/bionic/__get_tls.c \
 	arch-mips/bionic/__set_tls.c \
diff --git a/libc/arch-x86/bionic/clone.S b/libc/arch-x86/bionic/clone.S
index 352d23c..54b6ef2 100644
--- a/libc/arch-x86/bionic/clone.S
+++ b/libc/arch-x86/bionic/clone.S
@@ -33,7 +33,7 @@
         test    %eax, %eax
         jns     1f
 
-        # an error occured, set errno and return -1
+        # an error occurred, set errno and return -1
         negl    %eax
         call    __set_errno
         orl     $-1, %eax
@@ -53,7 +53,60 @@
         popl    %ebx
         ret
 
-/* XXX: TODO: Add __bionic_clone here
- *            See bionic/bionic_clone.c and arch-arm/bionic/clone.S
- *            for more details...
+
+/*
+ * int  __bionic_clone(unsigned long clone_flags,
+ *                     void*         newsp,
+ *                     int           *parent_tidptr,
+ *                     void          *new_tls,
+ *                     int           *child_tidptr,
+ *                     int           (*fn)(void *),
+ *                     void          *arg);
  */
+.text
+.globl __bionic_clone
+.type __bionic_clone, @function
+.align 4
+__bionic_clone:
+        pushl   %ebx
+        pushl   %esi
+        pushl   %edi
+
+        # insert arguments onto the child stack
+        movl    20(%esp), %ecx
+        andl    $~15, %ecx
+        movl    36(%esp), %eax
+        movl    %eax, -16(%ecx)
+        movl    40(%esp), %eax
+        movl    %eax, -12(%ecx)
+
+        subl    $16, %ecx
+        movl    16(%esp), %ebx
+        movl    24(%esp), %edx
+        movl    32(%esp), %esi
+        movl    28(%esp), %edi
+        movl    $__NR_clone, %eax
+        int     $0x80
+        test    %eax, %eax
+        jns     1f
+
+        # an error occurred, set errno and return -1
+        negl    %eax
+        call    __set_errno
+        orl     $-1, %eax
+        jmp     2f
+
+1:
+        jnz     2f
+
+        # we're in the child now, call __bionic_clone_entry
+        # with the appropriate arguments on the child stack
+        # we already placed most of them
+        call    __bionic_clone_entry
+        hlt
+
+2:
+        popl    %edi
+        popl    %esi
+        popl    %ebx
+        ret
diff --git a/libc/bionic/bionic_clone.c b/libc/bionic/bionic_clone.c
index 6b2fa58..187b60d 100644
--- a/libc/bionic/bionic_clone.c
+++ b/libc/bionic/bionic_clone.c
@@ -31,9 +31,6 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-/* WARNING: AT THE MOMENT, THIS IS ONLY SUPPORTED ON ARM
- */
-
 extern int  __bionic_clone(unsigned long   clone_flags,
                            void*           newsp,
                            int            *parent_tidptr,