[RFC PATCH 08/28] lkl: system call interface and application API

From: Octavian Purdila
Date: Tue Nov 03 2015 - 15:27:09 EST


The LKL application API is based on the kernel system call interface
in order to offer a stable API to applications. Note that we can't
offer the full Linux system call interface due to LKL limitations such
as lack of virtual memory, signal, user processes, etc.

The host is using the LKL interrupt mechanism (lkl_trigger_irq) to
initiate a system call. The system call is executed in the context of
the init process.

To avoid collisions between the Linux API and the LKL API (e.g. struct
stat, MKNOD, etc.) we use a python script to modify the user headers
and to prefix all of the global symbols (structures, typedefs,
defines) with LKL, lkl, _LKL, _lkl, __LKL or __lkl.

Signed-off-by: Octavian Purdila <octavian.purdila@xxxxxxxxx>
---
arch/lkl/include/asm/unistd.h | 93 +++++++++++++
arch/lkl/include/uapi/asm/unistd.h | 256 ++++++++++++++++++++++++++++++++++++
arch/lkl/kernel/syscalls.c | 213 ++++++++++++++++++++++++++++++
arch/lkl/scripts/headers_install.py | 117 ++++++++++++++++
4 files changed, 679 insertions(+)
create mode 100644 arch/lkl/include/asm/unistd.h
create mode 100644 arch/lkl/include/uapi/asm/unistd.h
create mode 100644 arch/lkl/kernel/syscalls.c
create mode 100755 arch/lkl/scripts/headers_install.py

diff --git a/arch/lkl/include/asm/unistd.h b/arch/lkl/include/asm/unistd.h
new file mode 100644
index 0000000..73c1e70
--- /dev/null
+++ b/arch/lkl/include/asm/unistd.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_LKL_UNISTD_H
+#define _ASM_LKL_UNISTD_H
+
+#include <uapi/asm/unistd.h>
+
+/*
+ * Unsupported system calls due to lack of support in LKL (e.g. related to
+ * virtual memory, signal, user processes). We also only support 64bit version
+ * of system calls where we have two version to keep the same APi across 32 and
+ * 64 bit hosts.
+ */
+#define __NR_restart_syscall 0
+#define __NR_exit 0
+#define __NR_fork 0
+#define __NR_execve 0
+#define __NR_ptrace 0
+#define __NR_alarm 0
+#define __NR_pause 0
+#define __NR_kill 0
+#define __NR_brk 0
+#define __NR_uselib 0
+#define __NR_swapon 0
+#define __NR_mmap 0
+#define __NR_munmap 0
+#define __NR_swapoff 0
+#define __NR_clone 0
+#define __NR_mprotect 0
+#define __NR_init_module 0
+#define __NR_quotactl 0
+#define __NR_msync 0
+#define __NR_mlock 0
+#define __NR_munlock 0
+#define __NR_mlockall 0
+#define __NR_munlockall 0
+#define __NR_mremap 0
+#define __NR_rt_sigreturn 0
+#define __NR_rt_sigaction 0
+#define __NR_rt_sigprocmask 0
+#define __NR_rt_sigpending 0
+#define __NR_rt_sigtimedwait 0
+#define __NR_rt_sigqueueinfo 0
+#define __NR_rt_sigsuspend 0
+#define __NR_sigaltstack 0
+#define __NR_vfork 0
+#define __NR_mincore 0
+#define __NR_madvise 0
+#define __NR_getdents 0 /* we use the 64 bit counter part instead */
+#define __NR_tkill 0
+#define __NR_exit_group 0
+#define __NR_remap_file_pages 0
+#define __NR_statfs 0 /* we use the 64 bit counter part instead */
+#define __NR_fstatfs 0 /* we use the 64 bit counter part instead */
+#define __NR_fstat 0 /* we use the 64 bit counter part instead */
+#define __NR_fadvise64_64 0
+#define __NR_mbind 0
+#define __NR_get_mempolicy 0
+#define __NR_set_mempolicy 0
+#define __NR_mq_open 0
+#define __NR_mq_unlink 0
+#define __NR_mq_timedsend 0
+#define __NR_mq_timedreceive 0
+#define __NR_mq_0
+#define __NR_mq_getsetattr 0
+#define __NR_kexec_load 0
+#define __NR_migrate_pages 0
+#define __NR_unshare 0
+#define __NR_set_robust_list 0
+#define __NR_get_robust_list 0
+#define __NR_sync_file_range 0
+#define __NR_vmsplice 0
+#define __NR_move_pages 0
+#define __NR_mq_notify 0
+#define __NR_umount2 0
+#define __NR_delete_module 0
+#define __NR_signalfd4 0
+#define __NR_preadv 0 /* we use the 64 bit counter part instead */
+#define __NR_pwritev 0 /* we use the 64 bit counter part instead */
+#define __NR_rt_tgsigqueueinfo 0
+#define __NR_perf_event_open 0
+#define __NR_setns 0
+#define __NR_process_vm_readv 0
+#define __NR_process_vm_writev 0
+#define __NR_kcmp 0
+#define __NR_finit_module 0
+#define __NR_seccomp 0
+#define __NR_memfd_create 0
+#define __NR_bpf 0
+#define __NR_execveat 0
+#define __NR_lseek 0 /* we use the 64 bit counter part instead */
+
+int run_syscalls(void);
+
+#endif
diff --git a/arch/lkl/include/uapi/asm/unistd.h b/arch/lkl/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..68b5423
--- /dev/null
+++ b/arch/lkl/include/uapi/asm/unistd.h
@@ -0,0 +1,256 @@
+#ifndef _ASM_UAPI_LKL_UNISTD_H
+#define _ASM_UAPI_LKL_UNISTD_H
+
+#ifdef __KERNEL__
+#define __NR_ni_syscall 0
+#define __NR_reboot 1
+#endif
+#define __NR_getpid 2
+#define __NR_write 3
+#define __NR_close 4
+#define __NR_unlink 5
+#define __NR_open 6
+#define __NR_poll 7
+#define __NR_read 8
+#define __NR_rename 10
+#define __NR_flock 11
+#define __NR_newfstat 12
+#define __NR_chmod 13
+#define __NR_newlstat 14
+#define __NR_mkdir 15
+#define __NR_rmdir 16
+#define __NR_getdents64 17
+#define __NR_newstat 18
+#define __NR_utimes 19
+#define __NR_utime 20
+#define __NR_nanosleep 21
+#define __NR_mknod 22
+#define __NR_mount 23
+#define __NR_umount 24
+#define __NR_chdir 25
+#define __NR_chroot 26
+#define __NR_getcwd 27
+#define __NR_chown 28
+#define __NR_umask 29
+#define __NR_getuid 30
+#define __NR_getgid 31
+#define __NR_socketcall 32
+#define __NR_ioctl 33
+#define __NR_readlink 34
+#define __NR_access 35
+#define __NR_truncate 36
+#define __NR_sync 37
+#define __NR_creat 38
+#define __NR_llseek 39
+#define __NR_stat64 40
+#define __NR_lstat64 41
+#define __NR_fstat64 42
+#define __NR_fstatat64 43
+#define __NR_statfs64 44
+#define __NR_fstatfs64 45
+#define __NR_listxattr 46
+#define __NR_llistxattr 47
+#define __NR_flistxattr 48
+#define __NR_getxattr 49
+#define __NR_lgetxattr 50
+#define __NR_fgetxattr 51
+#define __NR_setxattr 52
+#define __NR_lsetxattr 53
+#define __NR_fsetxattr 54
+#ifdef __KERNEL__
+#define NR_syscalls 55
+#endif
+
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_LLSEEK
+
+long lkl_syscall(long no, long *params);
+
+#ifndef __KERNEL__
+
+#define LKL_SYSCALL0(_syscall) \
+ static inline \
+ long lkl_sys_##_syscall(void) \
+ { \
+ long params[6]; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#define LKL_SYSCALL1(_syscall, arg1_t, arg1) \
+ static inline \
+ long lkl_sys_##_syscall(arg1_t arg1) \
+ { \
+ long params[6]; \
+ params[0] = (long)arg1; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#define LKL_SYSCALL2(_syscall, arg1_t, arg1, arg2_t, arg2) \
+ static inline \
+ long lkl_sys_##_syscall(arg1_t arg1, arg2_t arg2) \
+ { \
+ long params[6]; \
+ params[0] = (long)arg1; \
+ params[1] = (long)arg2; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#define LKL_SYSCALL3(_syscall, arg1_t, arg1, arg2_t, arg2, arg3_t, arg3) \
+ static inline \
+ long lkl_sys_##_syscall(arg1_t arg1, arg2_t arg2, arg3_t arg3) \
+ { \
+ long params[6]; \
+ params[0] = (long)arg1; \
+ params[1] = (long)arg2; \
+ params[2] = (long)arg3; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#define LKL_SYSCALL4(_syscall, arg1_t, arg1, arg2_t, arg2, arg3_t, arg3, \
+ arg4_t, arg4) \
+ static inline \
+ long lkl_sys_##_syscall(arg1_t arg1, arg2_t arg2, arg3_t arg3, \
+ arg4_t arg4) \
+ { \
+ long params[6]; \
+ params[0] = (long)arg1; \
+ params[1] = (long)arg2; \
+ params[2] = (long)arg3; \
+ params[3] = (long)arg4; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#define LKL_SYSCALL5(_syscall, arg1_t, arg1, arg2_t, arg2, arg3_t, arg3, \
+ arg4_t, arg4, arg5_t, arg5) \
+ static inline \
+ long lkl_sys_##_syscall(arg1_t arg1, arg2_t arg2, arg3_t arg3, \
+ arg4_t arg4, arg5_t arg5) \
+ { \
+ long params[6]; \
+ params[0] = (long)arg1; \
+ params[1] = (long)arg2; \
+ params[2] = (long)arg3; \
+ params[3] = (long)arg4; \
+ params[4] = (long)arg5; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#define LKL_SYSCALL6(_syscall, arg1_t, arg1, arg2_t, arg2, arg3_t, arg3, \
+ arg4_t, arg4, arg5_t, arg5, arg6_t, arg6) \
+ static inline \
+ long lkl_sys_##_syscall(arg1_t arg1, arg2_t arg2, arg3_t arg3, \
+ arg4_t arg4, arg5_t arg5, arg6_t arg6) \
+ { \
+ long params[6]; \
+ params[0] = (long)arg1; \
+ params[1] = (long)arg2; \
+ params[2] = (long)arg3; \
+ params[3] = (long)arg4; \
+ params[4] = (long)arg5; \
+ params[5] = (long)arg6; \
+ return lkl_syscall(__lkl__NR_##_syscall, params); \
+ }
+
+#include <autoconf.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/time.h>
+#include <linux/utime.h>
+#include <asm/stat.h>
+#include <asm/statfs.h>
+#define __KERNEL__ /* to pull in S_ definitions */
+#include <linux/stat.h>
+#undef __KERNEL__
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <asm/irq.h>
+#include <linux/kdev_t.h>
+
+/* these types are not exported to userspace so we have to do it here */
+typedef unsigned short lkl_umode_t;
+
+struct lkl_dirent64 {
+ unsigned long long d_ino;
+ long long d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[0];
+};
+
+#define LKL_DT_UNKNOWN 0
+#define LKL_DT_FIFO 1
+#define LKL_DT_CHR 2
+#define LKL_DT_DIR 4
+#define LKL_DT_BLK 6
+#define LKL_DT_REG 8
+#define LKL_DT_LNK 10
+#define LKL_DT_SOCK 12
+#define LKL_DT_WHT 14
+
+LKL_SYSCALL0(getpid);
+LKL_SYSCALL3(write, unsigned int, fd, const char *, buf,
+ __lkl__kernel_size_t, count);
+LKL_SYSCALL1(close, unsigned int, fd);
+LKL_SYSCALL1(unlink, const char *, pathname);
+LKL_SYSCALL3(open, const char *, filename, int, flags, lkl_umode_t, mode);
+LKL_SYSCALL2(creat, const char *, filename, lkl_umode_t, mode);
+LKL_SYSCALL3(poll, struct lkl_pollfd *, ufds, unsigned int, nfds, int, timeout);
+LKL_SYSCALL3(read, unsigned int, fd, char *, buf, __lkl__kernel_size_t, count);
+LKL_SYSCALL2(rename, const char *, oldname, const char *, newname);
+LKL_SYSCALL2(flock, unsigned int, fd, unsigned int, cmd);
+LKL_SYSCALL2(chmod, const char *, filename, lkl_umode_t, mode);
+
+LKL_SYSCALL2(mkdir, const char *, pathname, lkl_umode_t, mode);
+LKL_SYSCALL1(rmdir, const char *, pathname);
+LKL_SYSCALL3(getdents64, unsigned int, fd, void *, dirent, unsigned int, size);
+LKL_SYSCALL2(utimes, const char *, filename, struct lkl_timeval *, utimes);
+LKL_SYSCALL2(nanosleep, struct lkl_timespec *, rqtp,
+ struct lkl_timespec *, rmtp);
+LKL_SYSCALL3(mknod, const char *, filename, lkl_umode_t, mode,
+ unsigned int, dev);
+LKL_SYSCALL5(mount, const char *, dev_name, const char *, dir_name,
+ const char *, type, unsigned long, flags, void *, data);
+LKL_SYSCALL2(umount, const char *, name, int, flags);
+LKL_SYSCALL1(chdir, const char *, filename);
+LKL_SYSCALL1(chroot, const char *, filename);
+LKL_SYSCALL2(getcwd, char *, buf, unsigned long, size);
+LKL_SYSCALL2(utime, const char *, filename, const struct lkl_utimbuf *, buf);
+LKL_SYSCALL3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg);
+LKL_SYSCALL1(umask, int, mask);
+LKL_SYSCALL0(getuid);
+LKL_SYSCALL0(getgid);
+LKL_SYSCALL2(access, const char *, filename, int, mode);
+LKL_SYSCALL2(truncate, const char *, path, long, length);
+LKL_SYSCALL0(sync);
+LKL_SYSCALL5(llseek, unsigned int, fd, unsigned long, offset_high,
+ unsigned long, offset_low, __lkl__kernel_loff_t *, result,
+ unsigned int, whence);
+LKL_SYSCALL2(fstat64, unsigned int, fd, struct lkl_stat64 *, statbuf);
+LKL_SYSCALL4(fstatat64, unsigned int, dfd, const char *, filname,
+ struct lkl_stat64 *, statbuf, int, flag);
+LKL_SYSCALL2(stat64, const char *, filename, struct lkl_stat64 *, statbuf);
+LKL_SYSCALL2(lstat64, const char *, filename, struct lkl_stat64 *, statbuf);
+LKL_SYSCALL2(statfs64, const char *, path, struct lkl_statfs64 *, buf);
+LKL_SYSCALL3(readlink, const char *, path, char *, buf, int, bufsiz);
+LKL_SYSCALL3(listxattr, const char *, path, char *, list, int, bufsiz);
+LKL_SYSCALL3(llistxattr, const char *, path, char *, list, int, bufsiz);
+LKL_SYSCALL3(flistxattr, int, fd, char *, list, int, bufsiz);
+LKL_SYSCALL4(getxattr, const char *, path, const char *, name, void *, value,
+ __lkl__kernel_size_t, size);
+LKL_SYSCALL4(lgetxattr, const char *, path, const char *, name, void *, value,
+ __lkl__kernel_size_t, size);
+LKL_SYSCALL4(fgetxattr, int, fd, const char *, name, void *, value,
+ __lkl__kernel_size_t, size);
+LKL_SYSCALL5(setxattr, const char *, path, const char *, name,
+ const void *, value, __lkl__kernel_size_t, size, int, flags);
+LKL_SYSCALL5(lsetxattr, const char *, path, const char *, name,
+ const void *, value, __lkl__kernel_size_t, size, int, flags);
+LKL_SYSCALL5(fsetxattr, int, fd, const char *, name, const void *, value,
+ __lkl__kernel_size_t, size, int, flags);
+
+long lkl_sys_halt(void);
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_UAPI_LKL_UNISTD_H */
diff --git a/arch/lkl/kernel/syscalls.c b/arch/lkl/kernel/syscalls.c
new file mode 100644
index 0000000..48b1296
--- /dev/null
+++ b/arch/lkl/kernel/syscalls.c
@@ -0,0 +1,213 @@
+#include <linux/syscalls.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/syscalls.h>
+#include <linux/net.h>
+#include <linux/task_work.h>
+#include <asm/unistd.h>
+#include <asm/host_ops.h>
+
+typedef long (*syscall_handler_t)(long arg1, ...);
+
+syscall_handler_t syscall_table[NR_syscalls];
+
+static struct syscall_queue {
+ struct list_head list;
+ wait_queue_head_t wqh;
+} syscall_queue;
+
+struct syscall {
+ long no, *params, ret;
+ void *sem;
+ struct list_head lh;
+};
+
+static struct syscall *dequeue_syscall(struct syscall_queue *sq)
+{
+ struct syscall *s = NULL;
+
+ if (!list_empty(&sq->list)) {
+ s = list_first_entry(&sq->list, typeof(*s), lh);
+ list_del(&s->lh);
+ }
+
+ return s;
+}
+
+static long run_syscall(struct syscall *s)
+{
+ int ret;
+
+ if (s->no < 0 || s->no >= NR_syscalls || !syscall_table[s->no])
+ ret = -ENOSYS;
+ else
+ ret = syscall_table[s->no](s->params[0], s->params[1],
+ s->params[2], s->params[3],
+ s->params[4], s->params[5]);
+ s->ret = ret;
+
+ task_work_run();
+
+ if (s->sem)
+ lkl_ops->sem_up(s->sem);
+ return ret;
+}
+
+int run_syscalls(void)
+{
+ struct syscall_queue *sq = &syscall_queue;
+ struct syscall *s;
+
+ current->flags &= ~PF_KTHREAD;
+
+ snprintf(current->comm, sizeof(current->comm), "init");
+
+ while (1) {
+ wait_event(sq->wqh, (s = dequeue_syscall(sq)) != NULL);
+
+ if (s->no == __NR_reboot)
+ break;
+
+ run_syscall(s);
+ }
+
+ s->ret = 0;
+ lkl_ops->sem_up(s->sem);
+
+ return 0;
+}
+
+static irqreturn_t syscall_irq_handler(int irq, void *dev_id)
+{
+ struct pt_regs *regs = get_irq_regs();
+ struct syscall *s = regs->irq_data;
+
+ list_add_tail(&s->lh, &syscall_queue.list);
+ wake_up(&syscall_queue.wqh);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction syscall_irqaction = {
+ .handler = syscall_irq_handler,
+ .flags = IRQF_NOBALANCING,
+ .dev_id = &syscall_irqaction,
+ .name = "syscall"
+};
+
+static int syscall_irq;
+
+long lkl_syscall(long no, long *params)
+{
+ struct syscall s;
+
+ s.no = no;
+ s.params = params;
+
+ s.sem = lkl_ops->sem_alloc(0);
+ if (!s.sem)
+ return -ENOMEM;
+
+ lkl_trigger_irq(syscall_irq, &s);
+
+ lkl_ops->sem_down(s.sem);
+ lkl_ops->sem_free(s.sem);
+
+ return s.ret;
+}
+
+asmlinkage
+ssize_t sys_lkl_pwrite64(unsigned int fd, const char *buf, size_t count,
+ off_t pos_hi, off_t pos_lo)
+{
+ return sys_pwrite64(fd, buf, count, ((loff_t)pos_hi << 32) + pos_lo);
+}
+
+asmlinkage
+ssize_t sys_lkl_pread64(unsigned int fd, char *buf, size_t count,
+ off_t pos_hi, off_t pos_lo)
+{
+ return sys_pread64(fd, buf, count, ((loff_t)pos_hi << 32) + pos_lo);
+}
+
+#define INIT_STE(x) syscall_table[__NR_##x] = (syscall_handler_t)sys_##x
+
+void init_syscall_table(void)
+{
+ int i;
+
+ for (i = 0; i < NR_syscalls; i++)
+ syscall_table[i] = (syscall_handler_t)sys_ni_syscall;
+
+ INIT_STE(sync);
+ INIT_STE(reboot);
+ INIT_STE(write);
+ INIT_STE(close);
+ INIT_STE(unlink);
+ INIT_STE(open);
+ INIT_STE(poll);
+ INIT_STE(read);
+ INIT_STE(rename);
+ INIT_STE(chmod);
+ INIT_STE(llseek);
+ INIT_STE(lstat64);
+ INIT_STE(fstat64);
+ INIT_STE(fstatat64);
+ INIT_STE(stat64);
+ INIT_STE(mkdir);
+ INIT_STE(rmdir);
+ INIT_STE(getdents64);
+ INIT_STE(utimes);
+ INIT_STE(utime);
+ INIT_STE(nanosleep);
+ INIT_STE(mknod);
+ INIT_STE(mount);
+ INIT_STE(umount);
+ INIT_STE(chdir);
+ INIT_STE(statfs64);
+ INIT_STE(chroot);
+ INIT_STE(getcwd);
+ INIT_STE(chown);
+ INIT_STE(umask);
+ INIT_STE(getuid);
+ INIT_STE(getgid);
+#ifdef CONFIG_NET
+ INIT_STE(socketcall);
+#endif
+ INIT_STE(ioctl);
+ INIT_STE(access);
+ INIT_STE(truncate);
+ INIT_STE(getpid);
+ INIT_STE(creat);
+ INIT_STE(llseek);
+ INIT_STE(readlink);
+ INIT_STE(listxattr);
+ INIT_STE(llistxattr);
+ INIT_STE(flistxattr);
+ INIT_STE(getxattr);
+ INIT_STE(lgetxattr);
+ INIT_STE(fgetxattr);
+ INIT_STE(setxattr);
+ INIT_STE(lsetxattr);
+ INIT_STE(fsetxattr);
+}
+
+int __init syscall_init(void)
+{
+ init_syscall_table();
+
+ INIT_LIST_HEAD(&syscall_queue.list);
+ init_waitqueue_head(&syscall_queue.wqh);
+
+ syscall_irq = lkl_get_free_irq("syscall");
+ setup_irq(syscall_irq, &syscall_irqaction);
+
+ pr_info("lkl: syscall interface initialized\n");
+ return 0;
+}
+late_initcall(syscall_init);
diff --git a/arch/lkl/scripts/headers_install.py b/arch/lkl/scripts/headers_install.py
new file mode 100755
index 0000000..eb69a5e
--- /dev/null
+++ b/arch/lkl/scripts/headers_install.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+import re, os, sys, argparse, multiprocessing
+
+header_paths = [ "include/uapi/", "arch/lkl/include/uapi/",
+ "arch/lkl/include/generated/uapi/", "include/generated/" ]
+
+headers = set()
+
+def find_headers(path):
+ headers.add(path)
+ f = open(path)
+ for l in f.readlines():
+ m = re.search("#include <(.*)>", l)
+ try:
+ i = m.group(1)
+ for p in header_paths:
+ if os.access(p + i, os.R_OK):
+ if p + i not in headers:
+ headers.add(p + i)
+ find_headers(p + i)
+ except:
+ pass
+ f.close()
+
+def has_lkl_prefix(w):
+ return w.startswith("lkl") or w.startswith("_lkl") or w.startswith("LKL") or \
+ w.startswith("_LKL")
+
+def find_symbols(regexp, store):
+ for h in headers:
+ f = open(h)
+ for l in f.readlines():
+ m = re.search(regexp, l)
+ try:
+ e = m.group(1)
+ if not has_lkl_prefix(e):
+ store.add(e)
+ except:
+ pass
+ f.close()
+
+def find_ml_symbols(regexp, store):
+ for h in headers:
+ for i in re.finditer(regexp, open(h).read(), re.MULTILINE|re.DOTALL):
+ for j in i.groups():
+ store.add(j)
+
+def lkl_prefix(w):
+ r = ""
+
+ if w.startswith("__"):
+ r = "__"
+ elif w.startswith("_"):
+ r = "_"
+
+ if w.isupper():
+ r += "LKL"
+ else:
+ r += "lkl"
+
+ if not w.startswith("_"):
+ r += "_"
+
+ r += w
+
+ return r
+
+def replace(h):
+ content = open(h).read()
+ content = re.sub("(#[ \t]*include[ \t]<)(.*>)", "\\1lkl/\\2", content,
+ flags = re.MULTILINE)
+ for d in defines:
+ search_str = "([^_a-zA-Z0-9]+)" + d + "([^_a-zA-Z0-9]+)"
+ replace_str = "\\1" + lkl_prefix(d) + "\\2"
+ content = re.sub(search_str, replace_str, content, flags = re.MULTILINE)
+ for s in structs:
+ search_str = "([^_a-zA-Z0-9]*struct\s+)" + s + "([^_a-zA-Z0-9]+)"
+ replace_str = "\\1" + lkl_prefix(s) + "\\2"
+ content = re.sub(search_str, replace_str, content, flags = re.MULTILINE)
+ open(h, 'w').write(content)
+
+parser = argparse.ArgumentParser(description='install lkl headers')
+parser.add_argument('path', help='path to install to', )
+parser.add_argument('-j', '--jobs', help='number of parallel jobs', default=1, type=int)
+args = parser.parse_args()
+
+find_headers("arch/lkl/include/uapi/asm/unistd.h")
+headers.add("arch/lkl/include/uapi/asm/host_ops.h")
+
+defines = set()
+structs = set()
+
+find_symbols("#[ \t]*define[ \t]*([_a-zA-Z]+[_a-zA-Z0-9]*)[^_a-zA-Z0-9]", defines)
+find_symbols("typedef.*\s+([_a-zA-Z]+[_a-zA-Z0-9]*)\s*;", defines)
+find_ml_symbols("typedef\s+struct\s*\{.*\}\s*([_a-zA-Z]+[_a-zA-Z0-9]*)\s*;", defines)
+find_symbols("struct\s+([_a-zA-Z]+[_a-zA-Z0-9]*)\s*\{", structs)
+
+def process_header(h):
+ dir = os.path.dirname(h)
+ out_dir = args.path + "/" + re.sub("(arch/lkl/include/uapi/|arch/lkl/include/generated/uapi/|include/uapi/|include/generated/uapi/|include/generated)(.*)", "lkl/\\2", dir)
+ try:
+ os.makedirs(out_dir)
+ except:
+ pass
+ print " INSTALL\t%s" % (out_dir + "/" + os.path.basename(h))
+ os.system("scripts/headers_install.sh %s %s %s" % (out_dir, dir,
+ os.path.basename(h)))
+ replace(out_dir + "/" + os.path.basename(h))
+
+p = multiprocessing.Pool(args.jobs)
+try:
+ p.map_async(process_header, headers).wait(999999)
+ p.close()
+except:
+ p.terminate()
+finally:
+ p.join()
--
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/