[klibc] [PATCH 1/1] Porting klibc to AArch64

Anil Singhar anil.singhar at linaro.org
Wed Oct 9 02:53:21 PDT 2013


Details of the changes in second patch set as outlined in the first mail of
this series:
--------------------------------------------------------------------------------------------------------------------------

diff --git a/usr/include/arch/aarch64/klibc/archconfig.h
b/usr/include/arch/aarch64/klibc/archconfig.h
index 5cc1e7e..5ee278d 100644
--- a/usr/include/arch/aarch64/klibc/archconfig.h
+++ b/usr/include/arch/aarch64/klibc/archconfig.h
@@ -11,5 +11,7 @@

 /* Use rt_* signals */
 #define _KLIBC_USE_RT_SIG 1
+#define _KLIBC_NO_MMU 0
+#define _KLIBC_REAL_VFORK 1

 #endif                /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/aarch64/klibc/archsetjmp.h
b/usr/include/arch/aarch64/klibc/archsetjmp.h
index 38ffb67..d959988 100644
--- a/usr/include/arch/aarch64/klibc/archsetjmp.h
+++ b/usr/include/arch/aarch64/klibc/archsetjmp.h
@@ -5,12 +5,12 @@
 #ifndef _KLIBC_ARCHSETJMP_H
 #define _KLIBC_ARCHSETJMP_H

-/* 0-7 are temporary, starting at x8, skip x16, go up to x30
-also store the d registers, d8 to d15.
+/* 0-7 are temporary, starting at x8, skip x16, go up to x30,
+include sp, also store the d registers, d8 to d15.
 */

 struct __jmp_buf {
-    uint64_t __gregs[22];
+    uint64_t __gregs[23];
     uint64_t __fpregs[8];
 };

diff --git a/usr/include/arch/aarch64/klibc/archstat.h
b/usr/include/arch/aarch64/klibc/archstat.h
index 451a370..a7c854d 100644
--- a/usr/include/arch/aarch64/klibc/archstat.h
+++ b/usr/include/arch/aarch64/klibc/archstat.h
@@ -6,21 +6,26 @@
 #define _STATBUF_ST_NSEC

 struct stat {
-    __stdev64    (st_dev);
-    unsigned long    st_ino;
-    unsigned long    st_nlink;
-    unsigned int    st_mode;
-    unsigned int    st_uid;
-    unsigned int    st_gid;
-    unsigned int    __pad1;
-    __stdev64    (st_rdev);
-    unsigned long    st_size;
-    struct timespec    st_atim;
-    struct timespec    st_mtim;
-    struct timespec    st_ctim;
-    unsigned long    st_blksize;
-    long        st_blocks;
-    unsigned long    __unused[3];
-};
+          unsigned long   st_dev;         /* Device.  */
+          unsigned long   st_ino;         /* File serial number.  */
+          unsigned int    st_mode;        /* File mode.  */
+          unsigned int    st_nlink;       /* Link count.  */
+          unsigned int    st_uid;         /* User ID of the file's owner.
*/
+          unsigned int    st_gid;         /* Group ID of the file's group.
*/
+          unsigned long   st_rdev;        /* Device number, if device.  */
+          unsigned long   __pad1;
+          long            st_size;        /* Size of file, in bytes.  */
+          int             st_blksize;     /* Optimal block size for I/O.
*/
+          int             __pad2;
+          long            st_blocks;      /* Number 512-byte blocks
allocated. */
+          long            st_atime;       /* Time of last access.  */
+          unsigned long   st_atime_nsec;
+          long            st_mtime;       /* Time of last modification.  */
+          unsigned long   st_mtime_nsec;
+          long            st_ctime;       /* Time of last status change.
*/
+          unsigned long   st_ctime_nsec;
+          unsigned int    __unused4;
+          unsigned int    __unused5;
+  };

-#endif
+#endif
diff --git a/usr/include/sys/stat.h b/usr/include/sys/stat.h
index 4850429..4e3c170 100644
--- a/usr/include/sys/stat.h
+++ b/usr/include/sys/stat.h
@@ -56,12 +56,6 @@

 #endif

-#ifdef _STATBUF_ST_NSEC
-  /* struct stat has struct timespec instead of time_t */
-# define st_atime  st_atim.tv_sec
-# define st_mtime  st_mtim.tv_sec
-# define st_ctime  st_ctim.tv_sec
-#endif

 __extern int stat(const char *, struct stat *);
 __extern int fstat(int, struct stat *);
@@ -69,7 +63,7 @@ __extern int fstatat(int, const char *, struct stat *,
int);
 __extern int lstat(const char *, struct stat *);
 __extern mode_t umask(mode_t);
 __extern int mknod(const char *, mode_t, dev_t);
-__extern int mknodat(int, const char *, const char *, mode_t, dev_t);
+__extern int mknodat(int, const char *, mode_t, dev_t);
 __extern int mkfifo(const char *, mode_t);

 __extern_inline int mkfifo(const char *__p, mode_t __m)
diff --git a/usr/include/unistd.h b/usr/include/unistd.h
index f0e19c2..ff08a40 100644
--- a/usr/include/unistd.h
+++ b/usr/include/unistd.h
@@ -61,22 +61,22 @@ __extern int setfsuid(uid_t);
 __extern int access(const char *, int);
 __extern int faccessat(int, const char *, int, int);
 __extern int link(const char *, const char *);
-__extern int linkat(int, const char *, int, const char *);
+__extern int linkat(int, const char *, int, const char *, int);
 __extern int unlink(const char *);
 __extern int unlinkat(int, const char *, int);
 __extern int chdir(const char *);
 __extern int fchdir(int);
 __extern int chmod(const char *, mode_t);
 __extern int fchmod(int, mode_t);
-__extern int fchmodat(int, const char *, mode_t);
+__extern int fchmodat(int, const char *, mode_t, int);
 __extern int mkdir(const char *, mode_t);
-__extern int mkdirat(int, const char *, const char *, mode_t);
+__extern int mkdirat(int, const char *, mode_t);
 __extern int rmdir(const char *);
 __extern int pipe(int *);
 __extern int pipe2(int *, int);
 __extern int chroot(const char *);
 __extern int symlink(const char *, const char *);
-__extern int symlinkat(int, const char *, const char *);
+__extern int symlinkat(const char *, int, const char *);
 __extern int readlink(const char *, char *, size_t);
 __extern int readlinkat(int, const char *, char *, size_t);
 __extern int chown(const char *, uid_t, gid_t);
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 1cadb87..ba2d7e4 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -21,7 +21,7 @@ void _exit,exit::_exit(int);
 <?!ia64> pid_t clone::__clone(unsigned long, void *);
 <?ia64> pid_t clone::__clone2(unsigned long, void *, void *);
 # if ! _KLIBC_NO_MMU
-<!sparc,sparc64,ia64> pid_t fork();
+<!sparc,sparc64,ia64,aarch64> pid_t fork();
 <sparc,sparc64> pid_t fork at forkish();
 #endif
 #if _KLIBC_REAL_VFORK
@@ -91,7 +91,7 @@ int mount(const char *, const char *, const char *,
unsigned long, const void *)
 <?> int pivot_root(const char *, const char *);
 int sync();
 #ifdef __NR_statfs64
-int statfs64::__statfs64(const char *, size_t, struct statfs *);
+int statfs64::__statfs64(const char *, struct statfs *);
 #else
 int statfs(const char *, struct statfs *);
 #endif
@@ -109,7 +109,7 @@ int swapoff(const char *);
 <!aarch64> int access(const char *, int);
 int faccessat(int, const char *, int, int);
 <!aarch64> int link(const char *, const char *);
-<?> int linkat(int, const char *, int, const char *);
+<?> int linkat(int, const char *, int, const char *, int);
 <!aarch64> int unlink(const char *);
 <?> int unlinkat(int, const char *, int);
 int chdir(const char *);
@@ -117,12 +117,12 @@ int fchdir(int);
 <!aarch64> int rename(const char *, const char *);
 <?> int renameat(int, const char *, int, const char *);
 <!aarch64> int mknod(const char *, mode_t, dev_t);
-<?> int mknodat(int, const char *, const char *, mode_t, dev_t);
+<?> int mknodat(int, const char *, mode_t, dev_t);
 <!aarch64> int chmod(const char *, mode_t);
 int fchmod(int, mode_t);
-<?> int fchmodat(int, const char *, mode_t);
+<?> int fchmodat(int, const char *, mode_t, int);
 <!aarch64> int mkdir(const char *, mode_t);
-<?> int mkdirat(int, const char *, const char *, mode_t);
+<?> int mkdirat(int, const char *, mode_t);
 <!aarch64> int rmdir(const char *);
 <!alpha,aarch64,ia64,mips,mips64,sh,sparc,sparc64> int pipe(int *);
 int pipe2(int *, int);
diff --git a/usr/klibc/arch/aarch64/Kbuild b/usr/klibc/arch/aarch64/Kbuild
index 7f3664d..6d61c07 100644
--- a/usr/klibc/arch/aarch64/Kbuild
+++ b/usr/klibc/arch/aarch64/Kbuild
@@ -1,8 +1,8 @@
-#
+
 # klibc files for aarch64
 #

-klib-y := setjmp.o dup2.o unlink.o rmdir.o utimes.o fork.o open.o \
+klib-y := setjmp.o syscall.o dup2.o unlink.o rmdir.o utimes.o open.o \
  select.o poll.o stat.o lstat.o mkdir.o access.o mknod.o vfork.o pipe.o \
  chmod.o link.o symlink.o rename.o readlink.o chown.o lchown.o
 always  := crt0.o
diff --git a/usr/klibc/arch/aarch64/MCONFIG b/usr/klibc/arch/aarch64/MCONFIG
index 03a8cde..d86b303 100644
--- a/usr/klibc/arch/aarch64/MCONFIG
+++ b/usr/klibc/arch/aarch64/MCONFIG
@@ -18,7 +18,7 @@ KLIBCREQFLAGS += -fno-exceptions
 # Extra linkflags when building the shared version of the library
 # This address needs to be reachable using normal inter-module
 # calls, and work on the memory models for this architecture
-#KLIBCSHAREDFLAGS = -Ttext 0x01800200
+KLIBCSHAREDFLAGS = -Ttext 0x01800200
 #KLIBCREQFLAGS +=
 #KLIBCOPTFLAGS += -mgeneral-regs-only

diff --git a/usr/klibc/arch/aarch64/crt0.S b/usr/klibc/arch/aarch64/crt0.S
index b0de74b..21406c2 100644
--- a/usr/klibc/arch/aarch64/crt0.S
+++ b/usr/klibc/arch/aarch64/crt0.S
@@ -13,7 +13,7 @@
     .globl _start

 _start:
-    stp    x29, x30, [sp, -16]!
-    mov    x29, sp
+    mov    x0, sp
+    mov    x1, #0
     bl    __libc_init
     .size _start,.-_start
diff --git a/usr/klibc/arch/aarch64/link.c b/usr/klibc/arch/aarch64/link.c
index 7a04e27..f1dedfb 100644
--- a/usr/klibc/arch/aarch64/link.c
+++ b/usr/klibc/arch/aarch64/link.c
@@ -3,5 +3,5 @@

 int link(const char *oldpath, const char *newpath)
 {
-    return linkat (AT_FDCWD, oldpath, AT_FDCWD, newpath);
+    return linkat (AT_FDCWD, oldpath, AT_FDCWD, newpath, 0);
 }
diff --git a/usr/klibc/arch/aarch64/mknod.c b/usr/klibc/arch/aarch64/mknod.c
index 61836e4..cf7aca2 100644
--- a/usr/klibc/arch/aarch64/mknod.c
+++ b/usr/klibc/arch/aarch64/mknod.c
@@ -3,9 +3,7 @@
 #include <fcntl.h>
 #include <unistd.h>

-// FIXME what is the second const char * ?
-
 int mknod(const char *pathname, mode_t mode, dev_t dev)
 {
-    return mknodat(AT_FDCWD, pathname, pathname, mode, dev);
+    return mknodat(AT_FDCWD, pathname, mode, dev);
 }
diff --git a/usr/klibc/arch/aarch64/select.c
b/usr/klibc/arch/aarch64/select.c
index a326e59..59c569d 100644
--- a/usr/klibc/arch/aarch64/select.c
+++ b/usr/klibc/arch/aarch64/select.c
@@ -14,8 +14,8 @@ int select(int nfds, fd_set *readfds, fd_set *writefds,
     }
     result = __pselect6 (nfds, readfds, writefds, exceptfds, &ts, NULL);
     if (timeout) {
-        ts.tv_sec = timeout->tv_sec;
-        ts.tv_nsec = timeout->tv_usec * 1000;
+        timeout->tv_sec = ts.tv_sec;
+        timeout->tv_usec = ts.tv_nsec / 1000;
     }
     return result;
 }
diff --git a/usr/klibc/arch/aarch64/setjmp.S
b/usr/klibc/arch/aarch64/setjmp.S
index 695a797..3f2f2ac 100644
--- a/usr/klibc/arch/aarch64/setjmp.S
+++ b/usr/klibc/arch/aarch64/setjmp.S
@@ -29,6 +29,8 @@ setjmp:
     stp    d10, d11, [x0, #192]
     stp    d12, d13, [x0, #208]
     stp    d14, d15, [x0, #224]
+    mov    x1, sp
+    str    x1, [x0, #240]
     mov x0, #0             // set the return value of setjmp
     br x30
     .size setjmp,.-setjmp
@@ -53,6 +55,8 @@ longjmp:
     ldp    d10, d11, [x0, #192]
     ldp    d12, d13, [x0, #208]
     ldp    d14, d15, [x0, #224]
+    ldr    x2, [x0, #240]
+    mov    sp, x2
     mov x0, x1
     cbnz x1, 1f // if x1 is not zero, branch to 1:
     mov x0, #1
diff --git a/usr/klibc/arch/aarch64/symlink.c
b/usr/klibc/arch/aarch64/symlink.c
index 67d56bb..b66e8ab 100644
--- a/usr/klibc/arch/aarch64/symlink.c
+++ b/usr/klibc/arch/aarch64/symlink.c
@@ -3,5 +3,5 @@

 int symlink (const char *oldpath, const char *newpath)
 {
-    return symlinkat (AT_FDCWD, oldpath, newpath);
+    return symlinkat (oldpath, AT_FDCWD, newpath);
 }
diff --git a/usr/klibc/arch/aarch64/syscall.S
b/usr/klibc/arch/aarch64/syscall.S
new file mode 100644
index 0000000..e409aa2
--- /dev/null
+++ b/usr/klibc/arch/aarch64/syscall.S
@@ -0,0 +1,27 @@
+/*
+ * arch/aarch64/syscall.S
+ *
+ * System call common handling - if the return
+ * value from the system call is negative, then
+ * extra the magnitude and return it as errno and
+ * return -1, if the return value is 0 that is
+ * success case.
+ */
+
+    .type    __syscall_common,#function
+    .globl  __syscall_common
+
+    .balign 8
+__syscall_common:
+    cmp    x0, #0x0
+    b.ge    2f
+    neg    x0, x0
+    ldr    x8, 1f
+    str    x0, [x8]
+    mov    x0, #0xffffffffffffffff
+2:
+    ret
+
+    .balign 8
+1:
+    .dword    errno
diff --git a/usr/klibc/arch/aarch64/sysstub.ph b/usr/klibc/arch/aarch64/
sysstub.ph
index 3e29dfd..db9bdc6 100644
--- a/usr/klibc/arch/aarch64/sysstub.ph
+++ b/usr/klibc/arch/aarch64/sysstub.ph
@@ -16,14 +16,11 @@ sub make_sysstub($$$$$@) {
     print  OUT "    .globl    ${fname}\n";
     print  out "    .balign    8\n";
     print  OUT "${fname}:\n";
-    print  OUT "    mov x0,__NR_${sname}\n";
+    print  OUT "    mov w8,__NR_${sname}\n";
     print  OUT "    svc    0\n";
+    print  OUT "    b    __syscall_common\n";
     print  OUT "    .word    __NR_${sname}\n";
     print  OUT "    .size    ${fname},.-${fname}\n";
-# branch if not set
-#    print  OUT "    b .__syscall_error\n";
-#    print  OUT "    .size .${fname},.-.${fname}\n";
-
 }

 1;
diff --git a/usr/klibc/arch/aarch64/vfork.S b/usr/klibc/arch/aarch64/vfork.S
index 378098c..23869d3 100644
--- a/usr/klibc/arch/aarch64/vfork.S
+++ b/usr/klibc/arch/aarch64/vfork.S
@@ -13,10 +13,35 @@
     .globl    vfork
     .balign    8
 vfork:
-    mov    x0, #0x4111    /* CLONE_VM | CLONE_VFORK | SIGCHLD */
-    mov    x1, sp
-    cmn    x0, #4095
-    b.cs    1f
-    RET
+    /* Prepare for the system call */
+        /* 1. Push the function pointer and argument location
+              on to the child process stack */
+        /* 2. Gather the Flags */
+        /* New sp is already in x1.  */
+        mov     x0, #0x4111     /* CLONE_VM | CLONE_VFORK | SIGCHLD */
+        mov     x1, sp
+        mov     w8,__NR_clone
+        svc     0
+        cmp     x0, #0x0
+        b.eq    2f
+        b.gt    3f
+        neg     x0, x0
+        ldr     x8, 1f
+        str     x0, [x8]
+        mov     x0, #0xffffffffffffffff
+3:
+        ret
+2:
+        /* We are in the child process because clone syscall
+           returned 0. So just pull the function name and
+           args from stack and executei as follows.
+           ldp     x1, x0, [sp], #16
+           blr     x1
+       However, for vfork, we simply return to continue.
+    */
+        ret
 1:
-    .word    errno
+        .dword   errno
+        .word   __NR_clone
+        .size   vfork,.-vfork
+
diff --git a/usr/klibc/statfs.c b/usr/klibc/statfs.c
index b8b8700..3e2e716 100644
--- a/usr/klibc/statfs.c
+++ b/usr/klibc/statfs.c
@@ -3,17 +3,17 @@
  *
  * On architectures which do statfs64, wrap the system call
  */
-
+#include <fcntl.h>
 #include <sys/syscall.h>
 #include <sys/vfs.h>

 #ifdef __NR_statfs64

-extern int __statfs64(const char *, size_t, struct statfs *);
+extern int __statfs64(const char *, struct statfs *);

 int statfs(const char *path, struct statfs *buf)
 {
-    return __statfs64(path, sizeof *buf, buf);
+    return __statfs64(path, buf);
 }

 #endif
diff --git a/usr/klibc/tests/stat.c b/usr/klibc/tests/stat.c
index 4410833..ff97d12 100644
--- a/usr/klibc/tests/stat.c
+++ b/usr/klibc/tests/stat.c
@@ -36,12 +36,12 @@ static void do_stat(const char *path)
            (uintmax_t) st.st_blksize, (uintmax_t) st.st_blocks);

 #ifdef _STATBUF_ST_NSEC
-    printf("   st_atim      = %jd.%09u\n"
-           "   st.mtim      = %jd.%09u\n"
-           "   st.ctim      = %jd.%09u\n",
-           (uintmax_t) st.st_atim.tv_sec, (unsigned int)st.st_atim.tv_nsec,
-           (uintmax_t) st.st_mtim.tv_sec, (unsigned int)st.st_mtim.tv_nsec,
-           (uintmax_t) st.st_ctim.tv_sec, (unsigned
int)st.st_ctim.tv_nsec);
+    printf("   st.atime      = %jd.%09u\n"
+           "   st.mtime      = %jd.%09u\n"
+           "   st.ctime      = %jd.%09u\n",
+           (uintmax_t) st.st_atime, (unsigned int)st.st_atime_nsec,
+           (uintmax_t) st.st_mtime, (unsigned int)st.st_mtime_nsec,
+           (uintmax_t) st.st_ctime, (unsigned int)st.st_ctime_nsec);
 #else
     printf("   st_atime     = %jd\n"
            "   st.mtime     = %jd\n"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.zytor.com/pipermail/klibc/attachments/20131009/bc012e4e/attachment-0001.html>


More information about the klibc mailing list