LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
@ 2015-03-24 13:10 Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
                   ` (12 more replies)
  0 siblings, 13 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

This is an introduction of library operating system (LibOS) for Linux.

Our objective is to build the kernel network stack as a shared library
that can be linked to by userspace programs to provide network stack
personalization and testing facilities, and allow researchers to more
easily simulate complex network topologies of linux routers/hosts.

Although the architecture itself can virtualize various things, the
current design only focuses on the network stack. You can benefit
network stack feature such as TCP, UDP, SCTP, DCCP (IPv4 and IPv6),
Mobie IPv6, Multipath TCP (IPv4/IPv6, out-of-tree at the present
moment), and netlink with various userspace applications (quagga,
iproute2, iperf, wget, and thttpd).

== What is LibOS ? ==

The library exposes an entry point as API, which is lib_init(), in
order to connect userspace applications to the (userspace-version)
kernel network stack. The clock source, virtual struct net_device, and
scheduler are provided by caller while kernel resource like system
calls is provided by callee.

Once the LibOS is initialized via the API, userspace applications with
POSIX socket can use the system calls defined in LibOS by replacing
from the original socket-related symbols to the LibOS-specific
one. Then application can benefit the network stack of LibOS without
involving the host network stack.

Currently, there are two users of LibOS: Network Stack in Userspace
(NUSE) and ns-3 network simulatior with Direct Code Execution
(DCE). These codes are managed at an external repository(*1).


== How to use it ? ==

to build the library,
% make {defconfig,menuconfig} ARCH=lib

then, build it.
% make library ARCH=lib

You will see liblinux-$(KERNELVERSION).so in the top directory.

== More information ==

The crucial difference between UML (user-mode linux) and this approach
is that we allow multiple network stack instances to co-exist within a
single process with dlmopen(3) like linking for easy debugging.


These patches are also available on this branch:

git://github.com/libos-nuse/net-next-nuse.git for-asm-upstream


For further information, here is a slideset presented at the last
netdev0.1 conference.

http://www.slideshare.net/hajimetazaki/library-operating-system-for-linux-netdev01

I would appreciate any kind of your feedback regarding to upstream
this feature.

*1 https://github.com/libos-nuse/linux-libos-tools


Hajime Tazaki (11):
  sysctl: make some functions unstatic to access by arch/lib
  slab: add private memory allocator header for arch/lib
  lib: public headers and API implementations for userspace programs
  lib: memory management (kernel glue code)
  lib: time handling (kernel glue code)
  lib: context and scheduling handling (kernel glue code)
  lib: sysctl handling (kernel glue code)
  lib: other kernel glue layer code
  lib: asm-generic files
  lib: libos build scripts and documentation
  lib: tools used for test scripts

 Documentation/virtual/libos-howto.txt | 143 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   8 +
 arch/lib/Kconfig                      | 121 +++++++
 arch/lib/Makefile                     | 248 +++++++++++++
 arch/lib/Makefile.print               |  44 +++
 arch/lib/cred.c                       |  16 +
 arch/lib/dcache.c                     |  93 +++++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/filemap.c                    |  27 ++
 arch/lib/fs.c                         | 287 +++++++++++++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/glue.c                       | 336 +++++++++++++++++
 arch/lib/hrtimer.c                    | 122 +++++++
 arch/lib/include/asm/Kbuild           |  55 +++
 arch/lib/include/asm/atomic.h         |  47 +++
 arch/lib/include/asm/barrier.h        |   8 +
 arch/lib/include/asm/bitsperlong.h    |  12 +
 arch/lib/include/asm/current.h        |   7 +
 arch/lib/include/asm/elf.h            |  10 +
 arch/lib/include/asm/hardirq.h        |   8 +
 arch/lib/include/asm/page.h           |  14 +
 arch/lib/include/asm/pgtable.h        |  30 ++
 arch/lib/include/asm/processor.h      |  19 +
 arch/lib/include/asm/ptrace.h         |   4 +
 arch/lib/include/asm/segment.h        |   6 +
 arch/lib/include/asm/sembuf.h         |   4 +
 arch/lib/include/asm/shmbuf.h         |   4 +
 arch/lib/include/asm/shmparam.h       |   4 +
 arch/lib/include/asm/sigcontext.h     |   6 +
 arch/lib/include/asm/slab.h           |  21 ++
 arch/lib/include/asm/stat.h           |   4 +
 arch/lib/include/asm/statfs.h         |   4 +
 arch/lib/include/asm/swab.h           |   7 +
 arch/lib/include/asm/thread_info.h    |  35 ++
 arch/lib/include/asm/uaccess.h        |  14 +
 arch/lib/include/asm/unistd.h         |   4 +
 arch/lib/include/sim-assert.h         |  23 ++
 arch/lib/include/sim-init.h           | 134 +++++++
 arch/lib/include/sim-printf.h         |  13 +
 arch/lib/include/sim-types.h          |  53 +++
 arch/lib/include/sim.h                |  51 +++
 arch/lib/include/uapi/asm/byteorder.h |   6 +
 arch/lib/inode.c                      | 146 ++++++++
 arch/lib/lib-device.c                 | 187 ++++++++++
 arch/lib/lib-socket.c                 | 410 +++++++++++++++++++++
 arch/lib/lib.c                        | 289 +++++++++++++++
 arch/lib/lib.h                        |  21 ++
 arch/lib/modules.c                    |  36 ++
 arch/lib/pid.c                        |  29 ++
 arch/lib/print.c                      |  56 +++
 arch/lib/proc.c                       | 164 +++++++++
 arch/lib/processor.mk                 |   7 +
 arch/lib/random.c                     |  53 +++
 arch/lib/sched.c                      | 365 +++++++++++++++++++
 arch/lib/security.c                   |  45 +++
 arch/lib/seq.c                        | 122 +++++++
 arch/lib/slab.c                       | 200 +++++++++++
 arch/lib/softirq.c                    | 104 ++++++
 arch/lib/splice.c                     |  20 ++
 arch/lib/super.c                      | 210 +++++++++++
 arch/lib/sysctl.c                     | 284 +++++++++++++++
 arch/lib/sysfs.c                      |  83 +++++
 arch/lib/tasklet-hrtimer.c            |  57 +++
 arch/lib/tasklet.c                    |  76 ++++
 arch/lib/time.c                       | 149 ++++++++
 arch/lib/timer.c                      | 230 ++++++++++++
 arch/lib/vmscan.c                     |  26 ++
 arch/lib/workqueue.c                  | 242 +++++++++++++
 fs/proc/proc_sysctl.c                 |  16 +-
 include/linux/slab.h                  |  12 +
 tools/testing/libos/.gitignore        |   6 +
 tools/testing/libos/Makefile          |  38 ++
 tools/testing/libos/README            |  15 +
 tools/testing/libos/bisect.sh         |  10 +
 tools/testing/libos/dce-test.sh       |  23 ++
 tools/testing/libos/nuse-test.sh      |  57 +++
 77 files changed, 6544 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/cred.c
 create mode 100644 arch/lib/dcache.c
 create mode 100644 arch/lib/defconfig
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/slab.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h
 create mode 100644 arch/lib/inode.c
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/processor.mk
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/security.c
 create mode 100644 arch/lib/seq.c
 create mode 100644 arch/lib/slab.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/splice.c
 create mode 100644 arch/lib/super.c
 create mode 100644 arch/lib/sysctl.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c
 create mode 100644 arch/lib/vmscan.c
 create mode 100644 arch/lib/workqueue.c
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 16:13   ` Joe Perches
  2015-03-24 13:10 ` [RFC PATCH 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

libos (arch/lib) emulates a sysctl-like interface by a function call of
userspace by enumerating sysctl tree from sysctl_table_root. It requires
to be publicly accessible to this symbol and related functions.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 fs/proc/proc_sysctl.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f92d5dd..e3de095 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -35,7 +35,7 @@ static struct ctl_table root_table[] = {
 	},
 	{ }
 };
-static struct ctl_table_root sysctl_table_root = {
+struct ctl_table_root sysctl_table_root = {
 	.default_set.dir.header = {
 		{{.count = 1,
 		  .nreg = 1,
@@ -61,7 +61,7 @@ static void sysctl_print_dir(struct ctl_dir *dir)
 	pr_cont("%s/", dir->header.ctl_table[0].procname);
 }
 
-static int namecmp(const char *name1, int len1, const char *name2, int len2)
+int namecmp(const char *name1, int len1, const char *name2, int len2)
 {
 	int minlen;
 	int cmp;
@@ -77,7 +77,7 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
 }
 
 /* Called under sysctl_lock */
-static struct ctl_table *find_entry(struct ctl_table_header **phead,
+struct ctl_table *find_entry(struct ctl_table_header **phead,
 	struct ctl_dir *dir, const char *name, int namelen)
 {
 	struct ctl_table_header *head;
@@ -309,7 +309,7 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
 	return entry;
 }
 
-static struct ctl_node *first_usable_entry(struct rb_node *node)
+struct ctl_node *first_usable_entry(struct rb_node *node)
 {
 	struct ctl_node *ctl_node;
 
@@ -321,7 +321,7 @@ static struct ctl_node *first_usable_entry(struct rb_node *node)
 	return NULL;
 }
 
-static void first_entry(struct ctl_dir *dir,
+void first_entry(struct ctl_dir *dir,
 	struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = NULL;
@@ -339,7 +339,7 @@ static void first_entry(struct ctl_dir *dir,
 	*pentry = entry;
 }
 
-static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
+void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = *phead;
 	struct ctl_table *entry = *pentry;
@@ -822,7 +822,7 @@ static const struct dentry_operations proc_sys_dentry_operations = {
 	.d_compare	= proc_sys_compare,
 };
 
-static struct ctl_dir *find_subdir(struct ctl_dir *dir,
+struct ctl_dir *find_subdir(struct ctl_dir *dir,
 				   const char *name, int namelen)
 {
 	struct ctl_table_header *head;
@@ -924,7 +924,7 @@ failed:
 	return subdir;
 }
 
-static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
+struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
 {
 	struct ctl_dir *parent;
 	const char *procname;
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 02/11] slab: add private memory allocator header for arch/lib
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 03/11] lib: public headers and API implementations for userspace programs Hajime Tazaki
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

add header includion for CONFIG_LIB to wrap kmalloc and co. This will
bring malloc(3) based allocator used by arch/lib.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 include/linux/slab.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 9a139b6..6914e1f 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -205,6 +205,14 @@ size_t ksize(const void *);
 #endif
 #endif
 
+#ifdef CONFIG_LIB
+#define KMALLOC_SHIFT_MAX	30
+#define KMALLOC_SHIFT_HIGH	PAGE_SHIFT
+#ifndef KMALLOC_SHIFT_LOW
+#define KMALLOC_SHIFT_LOW	3
+#endif
+#endif
+
 /* Maximum allocatable size */
 #define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_MAX)
 /* Maximum size for which we actually use a slab cache */
@@ -350,6 +358,9 @@ kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
 }
 #endif
 
+#ifdef CONFIG_LIB
+#include <asm/slab.h>
+#else
 static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 {
 	unsigned int order = get_order(size);
@@ -428,6 +439,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 	}
 	return __kmalloc(size, flags);
 }
+#endif
 
 /*
  * Determine size used for the nth kmalloc cache.
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 03/11] lib: public headers and API implementations for userspace programs
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 04/11] lib: memory management (kernel glue code) Hajime Tazaki
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage, Ryo Nakamura

userspace programs access via public API, lib_init(), with passed
arguments struct SimImported and struct SimExported.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 arch/lib/include/sim-assert.h |  23 +++
 arch/lib/include/sim-init.h   | 134 ++++++++++++++
 arch/lib/include/sim-printf.h |  13 ++
 arch/lib/include/sim-types.h  |  53 ++++++
 arch/lib/include/sim.h        |  51 ++++++
 arch/lib/lib-device.c         | 187 +++++++++++++++++++
 arch/lib/lib-socket.c         | 410 ++++++++++++++++++++++++++++++++++++++++++
 arch/lib/lib.c                | 289 +++++++++++++++++++++++++++++
 arch/lib/lib.h                |  21 +++
 9 files changed, 1181 insertions(+)
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h

diff --git a/arch/lib/include/sim-assert.h b/arch/lib/include/sim-assert.h
new file mode 100644
index 0000000..974122c
--- /dev/null
+++ b/arch/lib/include/sim-assert.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_ASSERT_H
+#define SIM_ASSERT_H
+
+#include "sim-printf.h"
+
+#define lib_assert(v) {							\
+		while (!(v)) {						\
+			lib_printf("Assert failed %s:%u \"" #v "\"\n",	\
+				__FILE__, __LINE__);			\
+			char *p = 0;					\
+			*p = 1;						\
+		}							\
+	}
+
+
+#endif /* SIM_ASSERT_H */
diff --git a/arch/lib/include/sim-init.h b/arch/lib/include/sim-init.h
new file mode 100644
index 0000000..e871a59
--- /dev/null
+++ b/arch/lib/include/sim-init.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_INIT_H
+#define SIM_INIT_H
+
+#include <linux/socket.h>
+#include "sim-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
+
+struct SimExported {
+	struct SimTask *(*task_create)(void *priv, unsigned long pid);
+	void (*task_destroy)(struct SimTask *task);
+	void *(*task_get_private)(struct SimTask *task);
+
+	int (*sock_socket)(int domain, int type, int protocol,
+			struct SimSocket **socket);
+	int (*sock_close)(struct SimSocket *socket);
+	ssize_t (*sock_recvmsg)(struct SimSocket *socket, struct msghdr *msg,
+				int flags);
+	ssize_t (*sock_sendmsg)(struct SimSocket *socket,
+				const struct msghdr *msg, int flags);
+	int (*sock_getsockname)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_getpeername)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_bind)(struct SimSocket *socket, const struct sockaddr *name,
+			int namelen);
+	int (*sock_connect)(struct SimSocket *socket,
+			const struct sockaddr *name, int namelen,
+			int flags);
+	int (*sock_listen)(struct SimSocket *socket, int backlog);
+	int (*sock_shutdown)(struct SimSocket *socket, int how);
+	int (*sock_accept)(struct SimSocket *socket,
+			struct SimSocket **newSocket, int flags);
+	int (*sock_ioctl)(struct SimSocket *socket, int request, char *argp);
+	int (*sock_setsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			const void *optval, int optlen);
+	int (*sock_getsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			void *optval, int *optlen);
+
+	void (*sock_poll)(struct SimSocket *socket, void *ret);
+	void (*sock_pollfreewait)(void *polltable);
+
+	struct SimDevice *(*dev_create)(const char *ifname, void *priv,
+					enum SimDevFlags flags);
+	void (*dev_destroy)(struct SimDevice *dev);
+	void *(*dev_get_private)(struct SimDevice *task);
+	void (*dev_set_address)(struct SimDevice *dev,
+				unsigned char buffer[6]);
+	void (*dev_set_mtu)(struct SimDevice *dev, int mtu);
+	struct SimDevicePacket (*dev_create_packet)(struct SimDevice *dev,
+						int size);
+	void (*dev_rx)(struct SimDevice *dev, struct SimDevicePacket packet);
+
+	void (*sys_iterate_files)(const struct SimSysIterator *iter);
+	int (*sys_file_read)(const struct SimSysFile *file, char *buffer,
+			int size, int offset);
+	int (*sys_file_write)(const struct SimSysFile *file,
+			const char *buffer, int size, int offset);
+};
+
+struct SimImported {
+	int (*vprintf)(struct SimKernel *kernel, const char *str,
+		va_list args);
+	void *(*malloc)(struct SimKernel *kernel, unsigned long size);
+	void (*free)(struct SimKernel *kernel, void *buffer);
+	void *(*memcpy)(struct SimKernel *kernel, void *dst, const void *src,
+			unsigned long size);
+	void *(*memset)(struct SimKernel *kernel, void *dst, char value,
+			unsigned long size);
+	int (*atexit)(struct SimKernel *kernel, void (*function)(void));
+	int (*access)(struct SimKernel *kernel, const char *pathname,
+		int mode);
+	char *(*getenv)(struct SimKernel *kernel, const char *name);
+	int (*mkdir)(struct SimKernel *kernel, const char *pathname,
+		mode_t mode);
+	int (*open)(struct SimKernel *kernel, const char *pathname, int flags);
+	int (*__fxstat)(struct SimKernel *kernel, int ver, int fd, void *buf);
+	int (*fseek)(struct SimKernel *kernel, FILE *stream, long offset,
+		int whence);
+	void (*setbuf)(struct SimKernel *kernel, FILE *stream, char *buf);
+	FILE *(*fdopen)(struct SimKernel *kernel, int fd, const char *mode);
+	long (*ftell)(struct SimKernel *kernel, FILE *stream);
+	int (*fclose)(struct SimKernel *kernel, FILE *fp);
+	size_t (*fread)(struct SimKernel *kernel, void *ptr, size_t size,
+			size_t nmemb, FILE *stream);
+	size_t (*fwrite)(struct SimKernel *kernel, const void *ptr, size_t size,
+			 size_t nmemb, FILE *stream);
+
+	unsigned long (*random)(struct SimKernel *kernel);
+	void *(*event_schedule_ns)(struct SimKernel *kernel, __u64 ns,
+				void (*fn)(void *context), void *context,
+				void (*pre_fn)(void));
+	void (*event_cancel)(struct SimKernel *kernel, void *event);
+	__u64 (*current_ns)(struct SimKernel *kernel);
+
+	struct SimTask *(*task_start)(struct SimKernel *kernel,
+				void (*callback)(void *),
+				void *context);
+	void (*task_wait)(struct SimKernel *kernel);
+	struct SimTask *(*task_current)(struct SimKernel *kernel);
+	int (*task_wakeup)(struct SimKernel *kernel, struct SimTask *task);
+	void (*task_yield)(struct SimKernel *kernel);
+
+	void (*dev_xmit)(struct SimKernel *kernel, struct SimDevice *dev,
+			unsigned char *data, int len);
+	void (*signal_raised)(struct SimKernel *kernel, struct SimTask *task,
+			int sig);
+	void (*poll_event)(int flag, void *context);
+};
+
+typedef void (*SimInit)(struct SimExported *, const struct SimImported *,
+			struct SimKernel *kernel);
+void sim_init(struct SimExported *exported, const struct SimImported *imported,
+	struct SimKernel *kernel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_INIT_H */
diff --git a/arch/lib/include/sim-printf.h b/arch/lib/include/sim-printf.h
new file mode 100644
index 0000000..2bf8245
--- /dev/null
+++ b/arch/lib/include/sim-printf.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_PRINTF_H
+#define SIM_PRINTF_H
+
+void lib_printf(const char *str, ...);
+
+#endif /* SIM_PRINTF_H */
diff --git a/arch/lib/include/sim-types.h b/arch/lib/include/sim-types.h
new file mode 100644
index 0000000..d50b99b
--- /dev/null
+++ b/arch/lib/include/sim-types.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_TYPES_H
+#define SIM_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBOS_API_VERSION     2
+
+struct SimTask;
+struct SimDevice;
+struct SimSocket;
+struct SimKernel;
+struct SimSysFile;
+
+enum SimDevFlags {
+	SIM_DEV_NOARP         = (1 << 0),
+	SIM_DEV_POINTTOPOINT  = (1 << 1),
+	SIM_DEV_MULTICAST     = (1 << 2),
+	SIM_DEV_BROADCAST     = (1 << 3),
+};
+
+struct SimDevicePacket {
+	void *buffer;
+	void *token;
+};
+
+enum SimSysFileFlags {
+	SIM_SYS_FILE_READ  = 1 << 0,
+	SIM_SYS_FILE_WRITE = 1 << 1,
+};
+
+struct SimSysIterator {
+	void (*report_start_dir)(const struct SimSysIterator *iter,
+				const char *dirname);
+	void (*report_end_dir)(const struct SimSysIterator *iter);
+	void (*report_file)(const struct SimSysIterator *iter,
+			const char *filename,
+			int flags, struct SimSysFile *file);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_TYPES_H */
diff --git a/arch/lib/include/sim.h b/arch/lib/include/sim.h
new file mode 100644
index 0000000..b30d7e8
--- /dev/null
+++ b/arch/lib/include/sim.h
@@ -0,0 +1,51 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_H
+#define SIM_H
+
+#include <stdarg.h>
+#include <linux/types.h>
+
+#include "sim-types.h"
+
+/* API called from within linux kernel. Forwards to SimImported. */
+int lib_vprintf(const char *str, va_list args);
+void *lib_malloc(unsigned long size);
+void lib_free(void *buffer);
+void *lib_memcpy(void *dst, const void *src, unsigned long size);
+void *lib_memset(void *dst, char value, unsigned long size);
+unsigned long lib_random(void);
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context),
+			    void *context);
+void lib_event_cancel(void *event);
+__u64 lib_current_ns(void);
+
+struct SimTask *lib_task_start(void (*callback) (void *), void *context);
+void lib_task_wait(void);
+void lib_task_yield(void);
+struct SimTask *lib_task_current(void);
+/* returns 1 if task was woken up, 0 if it was already running. */
+int lib_task_wakeup(struct SimTask *task);
+struct SimTask *lib_task_create(void *priv, unsigned long pid);
+void lib_task_destroy(struct SimTask *task);
+void *lib_task_get_private(struct SimTask *task);
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len);
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size);
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet);
+
+void lib_signal_raised(struct SimTask *task, int sig);
+
+void lib_poll_event(int flag, void *context);
+void lib_softirq_wakeup(void);
+void lib_update_jiffies(void);
+void *lib_dev_get_private(struct SimDevice *);
+void lib_proc_net_initialize(void);
+
+#endif /* SIM_H */
diff --git a/arch/lib/lib-device.c b/arch/lib/lib-device.c
new file mode 100644
index 0000000..1efa6460
--- /dev/null
+++ b/arch/lib/lib-device.c
@@ -0,0 +1,187 @@
+/*
+ * virtual net_device feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ethtool.h>
+
+struct SimDevice {
+	struct net_device dev;
+	void *priv;
+};
+
+static netdev_tx_t
+kernel_dev_xmit(struct sk_buff *skb,
+		struct net_device *dev)
+{
+	int err;
+
+	netif_stop_queue(dev);
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		err = skb_checksum_help(skb);
+		if (unlikely(err)) {
+			pr_err("checksum error (%d)\n", err);
+			return 0;
+		}
+	}
+
+	lib_dev_xmit((struct SimDevice *)dev, skb->data, skb->len);
+	dev_kfree_skb(skb);
+	netif_wake_queue(dev);
+	return 0;
+}
+
+static u32 always_on(struct net_device *dev)
+{
+	return 1;
+}
+
+
+static const struct ethtool_ops lib_ethtool_ops = {
+	.get_link		= always_on,
+};
+
+static const struct net_device_ops lib_dev_ops = {
+	.ndo_start_xmit		= kernel_dev_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static void lib_dev_setup(struct net_device *dev)
+{
+	dev->mtu                = (16 * 1024) + 20 + 20 + 12;
+	dev->hard_header_len    = ETH_HLEN;     /* 14   */
+	dev->addr_len           = ETH_ALEN;     /* 6    */
+	dev->tx_queue_len       = 0;
+	dev->type               = ARPHRD_ETHER;
+	dev->flags              = 0;
+	/* dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE; */
+	dev->features           = 0
+				  | NETIF_F_HIGHDMA
+				  | NETIF_F_NETNS_LOCAL;
+	/* disabled  NETIF_F_TSO NETIF_F_SG  NETIF_F_FRAGLIST NETIF_F_LLTX */
+	dev->ethtool_ops        = &lib_ethtool_ops;
+	dev->header_ops         = &eth_header_ops;
+	dev->netdev_ops         = &lib_dev_ops;
+	dev->destructor         = &free_netdev;
+}
+
+
+struct SimDevice *lib_dev_create(const char *ifname, void *priv,
+				 enum SimDevFlags flags)
+{
+	int err;
+	struct SimDevice *dev =
+		(struct SimDevice *)alloc_netdev(sizeof(struct SimDevice),
+						 ifname, NET_NAME_UNKNOWN,
+						 &lib_dev_setup);
+	ether_setup((struct net_device *)dev);
+
+	if (flags & SIM_DEV_NOARP)
+		dev->dev.flags |= IFF_NOARP;
+	if (flags & SIM_DEV_POINTTOPOINT)
+		dev->dev.flags |= IFF_POINTOPOINT;
+	if (flags & SIM_DEV_MULTICAST)
+		dev->dev.flags |= IFF_MULTICAST;
+	if (flags & SIM_DEV_BROADCAST) {
+		dev->dev.flags |= IFF_BROADCAST;
+		memset(dev->dev.broadcast, 0xff, 6);
+	}
+	dev->priv = priv;
+	err = register_netdev(&dev->dev);
+	return dev;
+}
+void lib_dev_destroy(struct SimDevice *dev)
+{
+	unregister_netdev(&dev->dev);
+	/* XXX */
+	free_netdev(&dev->dev);
+}
+void *lib_dev_get_private(struct SimDevice *dev)
+{
+	return dev->priv;
+}
+
+void lib_dev_set_mtu(struct SimDevice *dev, int mtu)
+{
+	/* called by ns-3 to synchronize the kernel mtu with */
+	/* the simulation mtu */
+	dev->dev.mtu = mtu;
+}
+
+static int lib_ndo_change_mtu(struct net_device *dev,
+			      int new_mtu)
+{
+	/* called by kernel to change the mtu when the user */
+	/* asks for it. */
+	/* XXX should forward the set call to ns-3 and wait for */
+	/* ns-3 to notify of the change in the function above */
+	/* but I am way too tired to do this now. */
+	return 0;
+}
+
+void lib_dev_set_address(struct SimDevice *dev, unsigned char buffer[6])
+{
+	/* called by ns-3 to synchronize the kernel address with */
+	/* the simulation address. */
+	struct sockaddr sa;
+
+	sa.sa_family = dev->dev.type;
+	lib_memcpy(&sa.sa_data, buffer, 6);
+	dev->dev.netdev_ops->ndo_set_mac_address(&dev->dev, &sa);
+	/* Note that we don't call   dev_set_mac_address (&dev->dev, &sa); */
+	/* because this function expects to be called from within */
+	/* the netlink layer so, it expects to hold */
+	/* the netlink lock during the execution of the associated notifiers */
+}
+static int get_hack_size(int size)
+{
+	/* Note: this hack is coming from nsc */
+	/* Bit of a hack... */
+	/* Note that the size allocated here effects the offered window
+	   somewhat. I've got this heuristic here to try and match up with
+	   what we observe on the emulation network and by looking at the
+	   driver code of the eepro100. In both cases we allocate enough
+	   space for our packet, which  is the important thing. The amount
+	   of slack at the end can make linux decide the grow the window
+	   differently. This is quite subtle, but the code in question is
+	   in the tcp_grow_window function. It checks skb->truesize, which
+	   is the size of the skbuff allocated for the incoming data
+	   packet -- what we are allocating right now! */
+	if (size < 1200)
+		return size + 36;
+	else if (size <= 1500)
+		return 1536;
+	else
+		return size + 36;
+}
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size)
+{
+	struct SimDevicePacket packet;
+	int len = get_hack_size(size);
+	struct sk_buff *skb = __dev_alloc_skb(len, __GFP_WAIT);
+
+	packet.token = skb;
+	packet.buffer = skb_put(skb, len);
+	return packet;
+}
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet)
+{
+	struct sk_buff *skb = packet.token;
+	struct net_device *dev = &device->dev;
+
+	skb->protocol = eth_type_trans(skb, dev);
+	/* Do the TCP checksum (FIXME: should be configurable) */
+	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	netif_rx(skb);
+}
diff --git a/arch/lib/lib-socket.c b/arch/lib/lib-socket.c
new file mode 100644
index 0000000..bc253f9
--- /dev/null
+++ b/arch/lib/lib-socket.c
@@ -0,0 +1,410 @@
+/*
+ * socket feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/net.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/inet_connection_sock.h>
+
+struct SimSocket {};
+
+static struct iovec *copy_iovec(const struct iovec *input, int len)
+{
+	int size = sizeof(struct iovec) * len;
+	struct iovec *output = lib_malloc(size);
+
+	if (!output)
+		return NULL;
+	lib_memcpy(output, input, size);
+	return output;
+}
+
+int lib_sock_socket(int domain, int type, int protocol,
+		    struct SimSocket **socket)
+{
+	struct socket **kernel_socket = (struct socket **)socket;
+	int flags;
+
+	/* from net/socket.c */
+	flags = type & ~SOCK_TYPE_MASK;
+	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+		return -EINVAL;
+	type &= SOCK_TYPE_MASK;
+
+	int retval = sock_create(domain, type, protocol, kernel_socket);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	struct file *fp = lib_malloc(sizeof(struct file));
+	(*kernel_socket)->file = fp;
+	fp->f_cred = lib_malloc(sizeof(struct cred));
+	return retval;
+}
+int lib_sock_close(struct SimSocket *socket)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+
+	sock_release(kernel_socket);
+	return 0;
+}
+static size_t iov_size(const struct user_msghdr *msg)
+{
+	size_t i;
+	size_t size = 0;
+
+	for (i = 0; i < msg->msg_iovlen; i++)
+		size += msg->msg_iov[i].iov_len;
+	return size;
+}
+ssize_t lib_sock_recvmsg(struct SimSocket *socket,
+			struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct msghdr msg_sys;
+	struct cmsghdr *user_cmsgh = msg->msg_control;
+	size_t user_cmsghlen = msg->msg_controllen;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, READ,
+		msg->msg_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_recvmsg(kernel_socket, &msg_sys, iov_size(msg), flags);
+
+	msg->msg_name = msg_sys.msg_name;
+	msg->msg_namelen = msg_sys.msg_namelen;
+	msg->msg_control = user_cmsgh;
+	msg->msg_controllen = user_cmsghlen - msg_sys.msg_controllen;
+	return retval;
+}
+ssize_t lib_sock_sendmsg(struct SimSocket *socket,
+			const struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct iovec *kernel_iov = copy_iovec(msg->msg_iov, msg->msg_iovlen);
+	struct msghdr msg_sys;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, WRITE,
+		kernel_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_sendmsg(kernel_socket, &msg_sys, iov_size(msg));
+	lib_free(kernel_iov);
+	return retval;
+}
+int lib_sock_getsockname(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 0);
+
+	return retval;
+}
+int lib_sock_getpeername(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 1);
+
+	return retval;
+}
+int lib_sock_bind(struct SimSocket *socket, const struct sockaddr *name,
+		  int namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	int retval =
+		sock->ops->bind(sock, (struct sockaddr *)&address, namelen);
+	return retval;
+}
+int lib_sock_connect(struct SimSocket *socket, const struct sockaddr *name,
+		     int namelen, int flags)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	sock->file->f_flags = flags;
+	int retval = sock->ops->connect(sock, (struct sockaddr *)&address,
+					namelen, flags);
+	return retval;
+}
+int lib_sock_listen(struct SimSocket *socket, int backlog)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->listen(sock, backlog);
+
+	return retval;
+}
+int lib_sock_shutdown(struct SimSocket *socket, int how)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->shutdown(sock, how);
+
+	return retval;
+}
+int lib_sock_accept(struct SimSocket *socket, struct SimSocket **new_socket,
+		    int flags)
+{
+	struct socket *sock, *newsock;
+	int err;
+
+	sock = (struct socket *)socket;
+
+	/* the fields do not matter here. If we could, */
+	/* we would call sock_alloc but it's not exported. */
+	err = sock_create_lite(0, 0, 0, &newsock);
+	if (err < 0)
+		return err;
+	newsock->type = sock->type;
+	newsock->ops = sock->ops;
+
+	err = sock->ops->accept(sock, newsock, flags);
+	if (err < 0) {
+		sock_release(newsock);
+		return err;
+	}
+	*new_socket = (struct SimSocket *)newsock;
+	return 0;
+}
+int lib_sock_ioctl(struct SimSocket *socket, int request, char *argp)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sock *sk;
+	struct net *net;
+	int err;
+
+	sk = sock->sk;
+	net = sock_net(sk);
+
+	err = sock->ops->ioctl(sock, request, (long)argp);
+
+	/*
+	 * If this ioctl is unknown try to hand it down
+	 * to the NIC driver.
+	 */
+	if (err == -ENOIOCTLCMD)
+		err = dev_ioctl(net, request, argp);
+	return err;
+}
+int lib_sock_setsockopt(struct SimSocket *socket, int level, int optname,
+			const void *optval, int optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	char *coptval = (char *)optval;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_setsockopt(sock, level, optname, coptval, optlen);
+	else
+		err = sock->ops->setsockopt(sock, level, optname, coptval,
+					    optlen);
+	return err;
+}
+int lib_sock_getsockopt(struct SimSocket *socket, int level, int optname,
+			void *optval, int *optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_getsockopt(sock, level, optname, optval, optlen);
+	else
+		err =
+			sock->ops->getsockopt(sock, level, optname, optval,
+					      optlen);
+	return err;
+}
+
+int lib_sock_canrecv(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct inet_connection_sock *icsk;
+
+	switch (sock->sk->sk_state) {
+	case TCP_CLOSE:
+		if (SOCK_STREAM == sock->sk->sk_type)
+			return 1;
+	case TCP_ESTABLISHED:
+		return sock->sk->sk_receive_queue.qlen > 0;
+	case TCP_SYN_SENT:
+	case TCP_SYN_RECV:
+	case TCP_LAST_ACK:
+	case TCP_CLOSING:
+		return 0;
+	case TCP_FIN_WAIT1:
+	case TCP_FIN_WAIT2:
+	case TCP_TIME_WAIT:
+	case TCP_CLOSE_WAIT:
+		return 1;
+	case TCP_LISTEN:
+	{
+		icsk = inet_csk(sock->sk);
+		return !reqsk_queue_empty(&icsk->icsk_accept_queue);
+	}
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+int lib_sock_cansend(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+
+	return sock_writeable(sock->sk);
+}
+
+/**
+ * Struct used to pass pool table context between DCE and Kernel and back from
+ * Kernel to DCE
+ *
+ * When calling sock_poll we provide in ret field the wanted eventmask, and in
+ * the opaque field the DCE poll table
+ *
+ * if a corresponding event occurs later, the PollEvent will be called by kernel
+ * with the DCE poll table in context variable, then we will able to wake up the
+ * thread blocked in poll call.
+ *
+ * Back from sock_poll method the kernel change ret field with the response from
+ * poll return of the corresponding kernel socket, and in opaque field there is
+ * a reference to the kernel poll table we will use this reference to remove us
+ * from the file wait queue when ending the DCE poll call or when ending the DCE
+ * process which is currently polling.
+ *
+ */
+struct poll_table_ref {
+	int ret;
+	void *opaque;
+};
+
+/* Because the poll main loop code is in NS3/DCE we have only on entry
+   in our kernel poll table */
+struct lib_ptable_entry {
+	wait_queue_t wait;
+	wait_queue_head_t *wait_address;
+	int eventMask;  /* Poll wanted event mask. */
+	void *opaque;   /* Pointeur to DCE poll table */
+};
+
+static int lib_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)wait->private;
+
+	/* Filter only wanted events */
+	if (key && !((unsigned long)key & entry->eventMask))
+		return 0;
+
+	lib_poll_event((unsigned long)key, entry->opaque);
+	return 1;
+}
+
+static void lib_pollwait(struct file *filp, wait_queue_head_t *wait_address,
+			 poll_table *p)
+{
+	struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)
+		lib_malloc(sizeof(struct lib_ptable_entry));
+	struct poll_table_ref *fromDCE =  (struct poll_table_ref *)pwq->table;
+
+	if (!entry)
+		return;
+
+	entry->opaque = fromDCE->opaque; /* Copy DCE poll table reference */
+	entry->eventMask = fromDCE->ret; /* Copy poll mask of wanted events. */
+
+	pwq->table = (struct poll_table_page *)entry;
+
+	init_waitqueue_func_entry(&entry->wait, lib_pollwake);
+	entry->wait.private = entry;
+	entry->wait_address = wait_address;
+	add_wait_queue(wait_address, &entry->wait);
+}
+
+void dce_poll_initwait(struct poll_wqueues *pwq)
+{
+	init_poll_funcptr(&pwq->pt, lib_pollwait);
+	pwq->polling_task = current;
+	pwq->triggered = 0;
+	pwq->error = 0;
+	pwq->table = NULL;
+	pwq->inline_index = 0;
+}
+
+/* call poll on socket ... */
+void lib_sock_poll(struct SimSocket *socket, struct poll_table_ref *ret)
+{
+	struct socket *sock = (struct socket *)socket;
+	/* Provide a fake file structure */
+	struct file zero;
+	poll_table *pwait = 0;
+	struct poll_wqueues *ptable = 0;
+
+	lib_memset(&zero, 0, sizeof(struct file));
+
+	if (ret->opaque) {
+		ptable =
+			(struct poll_wqueues *)lib_malloc(sizeof(struct
+								 poll_wqueues));
+		if (!ptable)
+			return;
+
+		dce_poll_initwait(ptable);
+
+		pwait = &(ptable->pt);
+		/* Pass the DCE pool table to lib_pollwait function */
+		ptable->table = (struct poll_table_page *)ret;
+	}
+
+	ret->ret = sock->ops->poll(&zero, sock, pwait);
+	/* Pass back the kernel poll table to DCE in order to DCE to */
+	/* remove from wait queue */
+	/* using lib_sock_pollfreewait method below */
+	ret->opaque = ptable;
+}
+
+void lib_sock_pollfreewait(void *polltable)
+{
+	struct poll_wqueues *ptable = (struct poll_wqueues *)polltable;
+
+	if (ptable && ptable->table) {
+		struct lib_ptable_entry *entry =
+			(struct lib_ptable_entry *)ptable->table;
+		remove_wait_queue(entry->wait_address, &entry->wait);
+		lib_free(entry);
+	}
+	lib_free(ptable);
+}
+
+
+
+
diff --git a/arch/lib/lib.c b/arch/lib/lib.c
new file mode 100644
index 0000000..af98e42
--- /dev/null
+++ b/arch/lib/lib.c
@@ -0,0 +1,289 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/init.h>         /* initcall_t */
+#include <linux/kernel.h>       /* SYSTEM_BOOTING */
+#include <linux/sched.h>        /* struct task_struct */
+#include <linux/device.h>
+#include <drivers/base/base.h>
+#include <linux/idr.h>
+#include <linux/rcupdate.h>
+#include "sim-init.h"
+#include "sim.h"
+
+enum system_states system_state = SYSTEM_BOOTING;
+
+struct SimImported g_imported;
+
+
+#define RETURN_void(rettype, v)				     \
+	({						     \
+		(v);					     \
+		lib_softirq_wakeup();			     \
+	})
+
+#define RETURN_nvoid(rettype, v)			     \
+	({						     \
+		rettype x = (v);			     \
+		lib_softirq_wakeup();			     \
+		x;					     \
+	})
+
+#define FORWARDER1(name, type, rettype, t0)			    \
+	extern rettype name(t0);				    \
+	static rettype name ## _forwarder(t0 v0)		    \
+	{							    \
+		lib_update_jiffies();				    \
+		return RETURN_ ## type(rettype, (name(v0)));        \
+	}
+
+#define FORWARDER2(name, type, rettype, t0, t1)				\
+	extern rettype name(t0, t1);					\
+	static rettype name ## _forwarder(t0 v0, t1 v1)			\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1)));	\
+	}
+#define FORWARDER3(name, type, rettype, t0, t1, t2)			\
+	extern rettype name(t0, t1, t2);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2)		\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2)));	\
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER5(name, type, rettype, t0, t1, t2, t3, t4)		\
+	extern rettype name(t0, t1, t2, t3, t4);			\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3, t4 v4) \
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3, v4))); \
+	}
+
+FORWARDER3(lib_dev_create, nvoid, struct SimDevice *, const char *, void *,
+	   enum SimDevFlags);
+FORWARDER1(lib_dev_destroy, void, void, struct SimDevice *);
+FORWARDER2(lib_dev_set_address, void, void, struct SimDevice *,
+	   unsigned char *);
+FORWARDER2(lib_dev_set_mtu, void, void, struct SimDevice *, int);
+FORWARDER2(lib_dev_create_packet, nvoid, struct SimDevicePacket,
+	   struct SimDevice *, int);
+FORWARDER2(lib_dev_rx, void, void, struct SimDevice *, struct SimDevicePacket);
+
+FORWARDER4(lib_sock_socket, nvoid, int, int, int, int, struct SimSocket **);
+FORWARDER1(lib_sock_close, nvoid, int, struct SimSocket *);
+FORWARDER3(lib_sock_recvmsg, nvoid, ssize_t, struct SimSocket *,
+	   struct msghdr *, int);
+FORWARDER3(lib_sock_sendmsg, nvoid, ssize_t, struct SimSocket *,
+	   const struct msghdr *, int);
+FORWARDER3(lib_sock_getsockname, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_getpeername, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_bind, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int);
+FORWARDER4(lib_sock_connect, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int, int);
+FORWARDER2(lib_sock_listen, nvoid, int, struct SimSocket *, int);
+FORWARDER2(lib_sock_shutdown, nvoid, int, struct SimSocket *, int);
+FORWARDER3(lib_sock_accept, nvoid, int, struct SimSocket *,
+	   struct SimSocket **, int);
+FORWARDER3(lib_sock_ioctl, nvoid, int, struct SimSocket *, int, char *);
+FORWARDER5(lib_sock_setsockopt, nvoid, int, struct SimSocket *, int, int,
+	   const void *, int);
+FORWARDER5(lib_sock_getsockopt, nvoid, int, struct SimSocket *, int, int,
+	   void *, int *);
+
+FORWARDER2(lib_sock_poll, void, void, struct SimSocket *, void *);
+FORWARDER1(lib_sock_pollfreewait, void, void, void *);
+
+FORWARDER1(lib_sys_iterate_files, void, void, const struct SimSysIterator *);
+FORWARDER4(lib_sys_file_read, nvoid, int, const struct SimSysFile *, char *,
+	   int, int);
+FORWARDER4(lib_sys_file_write, nvoid, int, const struct SimSysFile *,
+	   const char *, int, int);
+
+struct SimKernel *g_kernel;
+
+void lib_init(struct SimExported *exported, const struct SimImported *imported,
+	      struct SimKernel *kernel)
+{
+	/* make sure we can call the callbacks */
+	g_imported = *imported;
+	g_kernel = kernel;
+	exported->task_create = lib_task_create;
+	exported->task_destroy = lib_task_destroy;
+	exported->task_get_private = lib_task_get_private;
+	exported->sock_socket = lib_sock_socket_forwarder;
+	exported->sock_close = lib_sock_close_forwarder;
+	exported->sock_recvmsg = lib_sock_recvmsg_forwarder;
+	exported->sock_sendmsg = lib_sock_sendmsg_forwarder;
+	exported->sock_getsockname = lib_sock_getsockname_forwarder;
+	exported->sock_getpeername = lib_sock_getpeername_forwarder;
+	exported->sock_bind = lib_sock_bind_forwarder;
+	exported->sock_connect = lib_sock_connect_forwarder;
+	exported->sock_listen = lib_sock_listen_forwarder;
+	exported->sock_shutdown = lib_sock_shutdown_forwarder;
+	exported->sock_accept = lib_sock_accept_forwarder;
+	exported->sock_ioctl = lib_sock_ioctl_forwarder;
+	exported->sock_setsockopt = lib_sock_setsockopt_forwarder;
+	exported->sock_getsockopt = lib_sock_getsockopt_forwarder;
+
+	exported->sock_poll = lib_sock_poll_forwarder;
+	exported->sock_pollfreewait = lib_sock_pollfreewait_forwarder;
+
+	exported->dev_create = lib_dev_create_forwarder;
+	exported->dev_destroy = lib_dev_destroy_forwarder;
+	exported->dev_get_private = lib_dev_get_private;
+	exported->dev_set_address = lib_dev_set_address_forwarder;
+	exported->dev_set_mtu = lib_dev_set_mtu_forwarder;
+	exported->dev_create_packet = lib_dev_create_packet_forwarder;
+	exported->dev_rx = lib_dev_rx_forwarder;
+
+	exported->sys_iterate_files = lib_sys_iterate_files_forwarder;
+	exported->sys_file_write = lib_sys_file_write_forwarder;
+	exported->sys_file_read = lib_sys_file_read_forwarder;
+
+	pr_notice("%s", linux_banner);
+
+	rcu_init();
+
+	/* in drivers/base/core.c (called normally by drivers/base/init.c) */
+	devices_init();
+	/* in lib/idr.c (called normally by init/main.c) */
+	idr_init_cache();
+
+	lib_proc_net_initialize();
+
+	/* and, then, call the normal initcalls */
+	initcall_t *call;
+	extern initcall_t __initcall_start[], __initcall_end[];
+
+	call = __initcall_start;
+	do {
+		(*call)();
+		call++;
+	} while (call < __initcall_end);
+
+	/* finally, put the system in RUNNING state. */
+	system_state = SYSTEM_RUNNING;
+}
+
+int lib_vprintf(const char *str, va_list args)
+{
+	return g_imported.vprintf(g_kernel, str, args);
+}
+void *lib_malloc(unsigned long size)
+{
+	return g_imported.malloc(g_kernel, size);
+}
+void lib_free(void *buffer)
+{
+	return g_imported.free(g_kernel, buffer);
+}
+void *lib_memcpy(void *dst, const void *src, unsigned long size)
+{
+	return g_imported.memcpy(g_kernel, dst, src, size);
+}
+void *lib_memset(void *dst, char value, unsigned long size)
+{
+	return g_imported.memset(g_kernel, dst, value, size);
+}
+unsigned long lib_random(void)
+{
+	return g_imported.random(g_kernel);
+}
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context), void *context)
+{
+	return g_imported.event_schedule_ns(g_kernel, ns, fn, context,
+					    lib_update_jiffies);
+}
+void lib_event_cancel(void *event)
+{
+	return g_imported.event_cancel(g_kernel, event);
+}
+__u64 lib_current_ns(void)
+{
+	return g_imported.current_ns(g_kernel);
+}
+struct SimTaskTrampolineContext {
+	void (*callback)(void *);
+	void *context;
+};
+static void lib_task_start_trampoline(void *context)
+{
+	/* we use this trampoline solely for the purpose of executing
+	   lib_update_jiffies prior to calling the callback. */
+	struct SimTaskTrampolineContext *ctx = context;
+	void (*callback)(void *) = ctx->callback;
+	void *callback_context = ctx->context;
+
+	lib_free(ctx);
+	lib_update_jiffies();
+	callback(callback_context);
+}
+struct SimTask *lib_task_start(void (*callback) (void *), void *context)
+{
+	struct SimTaskTrampolineContext *ctx =
+		lib_malloc(sizeof(struct SimTaskTrampolineContext));
+
+	if (!ctx)
+		return NULL;
+	ctx->callback = callback;
+	ctx->context = context;
+	return g_imported.task_start(g_kernel, &lib_task_start_trampoline, ctx);
+}
+void lib_task_wait(void)
+{
+	rcu_sched_qs();
+	g_imported.task_wait(g_kernel);
+	lib_update_jiffies();
+}
+struct SimTask *lib_task_current(void)
+{
+	return g_imported.task_current(g_kernel);
+}
+int lib_task_wakeup(struct SimTask *task)
+{
+	return g_imported.task_wakeup(g_kernel, task);
+}
+void lib_task_yield(void)
+{
+	rcu_idle_enter();
+	g_imported.task_yield(g_kernel);
+	rcu_idle_exit();
+	lib_update_jiffies();
+}
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len)
+{
+	return g_imported.dev_xmit(g_kernel, dev, data, len);
+}
+
+void lib_signal_raised(struct SimTask *task, int sig)
+{
+	g_imported.signal_raised(g_kernel, task, sig);
+}
+
+void lib_poll_event(int flag, void *context)
+{
+	g_imported.poll_event(flag, context);
+}
diff --git a/arch/lib/lib.h b/arch/lib/lib.h
new file mode 100644
index 0000000..abf2a26
--- /dev/null
+++ b/arch/lib/lib.h
@@ -0,0 +1,21 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#ifndef LIB_H
+#define LIB_H
+
+#include <linux/sched.h>
+
+struct SimTask {
+	struct list_head head;
+	struct task_struct kernel_task;
+	void *private;
+};
+
+#endif /* LIB_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 04/11] lib: memory management (kernel glue code)
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (2 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 03/11] lib: public headers and API implementations for userspace programs Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 05/11] lib: time handling " Hajime Tazaki
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/slab.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 200 insertions(+)
 create mode 100644 arch/lib/slab.c

diff --git a/arch/lib/slab.c b/arch/lib/slab.c
new file mode 100644
index 0000000..93ff183c
--- /dev/null
+++ b/arch/lib/slab.c
@@ -0,0 +1,200 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/page-flags.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+void kfree(const void *p)
+{
+	unsigned long start;
+
+	if (p == 0)
+		return;
+	start = (unsigned long)p;
+	start -= sizeof(size_t);
+	lib_free((void *)start);
+}
+size_t ksize(const void *p)
+{
+	size_t *psize = (size_t *)p;
+
+	psize--;
+	return *psize;
+}
+void *__kmalloc(size_t size, gfp_t flags)
+{
+	void *p = lib_malloc(size + sizeof(size));
+	unsigned long start;
+
+	if (!p)
+		return NULL;
+
+	if (p != 0 && (flags & __GFP_ZERO))
+		lib_memset(p, 0, size + sizeof(size));
+	lib_memcpy(p, &size, sizeof(size));
+	start = (unsigned long)p;
+	return (void *)(start + sizeof(size));
+}
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
+{
+	return kmalloc(size, flags);
+}
+
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+
+	if (!new_size) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ret = __kmalloc(new_size, flags);
+	if (ret && p != ret)
+		kfree(p);
+
+	return ret;
+}
+
+struct kmem_cache *
+kmem_cache_create(const char *name, size_t size, size_t align,
+		  unsigned long flags, void (*ctor)(void *))
+{
+	struct kmem_cache *cache = kmalloc(sizeof(struct kmem_cache), flags);
+
+	if (!cache)
+		return NULL;
+	cache->name = name;
+	cache->size = size;
+	cache->align = align;
+	cache->flags = flags;
+	cache->ctor = ctor;
+	return cache;
+}
+void kmem_cache_destroy(struct kmem_cache *cache)
+{
+	kfree(cache);
+}
+int kmem_cache_shrink(struct kmem_cache *cache)
+{
+	return 1;
+}
+const char *kmem_cache_name(struct kmem_cache *cache)
+{
+	return cache->name;
+}
+void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+	void *p = kmalloc(cache->size, flags);
+
+	if (p == 0)
+		return NULL;
+	if (cache->ctor)
+		(cache->ctor)(p);
+	return p;
+
+}
+void kmem_cache_free(struct kmem_cache *cache, void *p)
+{
+	kfree(p);
+}
+
+struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+		       struct zonelist *zonelist, nodemask_t *nodemask)
+{
+	void *p;
+	struct page *page;
+	unsigned long pointer;
+
+	/* typically, called from networking code by alloc_page or */
+	/* directly with an order = 0. */
+	if (order)
+		return NULL;
+	p = lib_malloc(sizeof(struct page) + (1 << PAGE_SHIFT));
+	page = (struct page *)p;
+
+	atomic_set(&page->_count, 1);
+	page->flags = 0;
+	pointer = (unsigned long)page;
+	pointer += sizeof(struct page);
+	page->virtual = (void *)pointer;
+	return page;
+}
+void __free_pages(struct page *page, unsigned int order)
+{
+	/* typically, called from networking code by __free_page */
+	lib_assert(order == 0);
+	lib_free(page);
+}
+
+void put_page(struct page *page)
+{
+	if (atomic_dec_and_test(&page->_count))
+		lib_free(page);
+}
+unsigned long get_zeroed_page(gfp_t gfp_mask)
+{
+	return __get_free_pages(gfp_mask | __GFP_ZERO, 0);
+}
+
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+	return alloc_pages(gfp_mask, get_order(size));
+}
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+{
+	int size = (1 << order) * PAGE_SIZE;
+	void *p = kmalloc(size, gfp_mask);
+
+	return (unsigned long)p;
+}
+void free_pages(unsigned long addr, unsigned int order)
+{
+	if (addr != 0)
+		kfree((void *)addr);
+}
+
+void *vmalloc(unsigned long size)
+{
+	return lib_malloc(size);
+}
+void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return kmalloc(size, gfp_mask);
+}
+void vfree(const void *addr)
+{
+	lib_free((void *)addr);
+}
+void *vmalloc_node(unsigned long size, int node)
+{
+	return lib_malloc(size);
+}
+void vmalloc_sync_all(void)
+{
+}
+void *__alloc_percpu(size_t size, size_t align)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+void free_percpu(void __percpu *ptr)
+{
+	kfree(ptr);
+}
+void *__alloc_bootmem_nopanic(unsigned long size,
+			      unsigned long align,
+			      unsigned long goal)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 05/11] lib: time handling (kernel glue code)
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (3 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 04/11] lib: memory management (kernel glue code) Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 06/11] lib: context and scheduling " Hajime Tazaki
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/hrtimer.c         | 122 ++++++++++++++++++++++++
 arch/lib/tasklet-hrtimer.c |  57 +++++++++++
 arch/lib/time.c            | 149 +++++++++++++++++++++++++++++
 arch/lib/timer.c           | 230 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 558 insertions(+)
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c

diff --git a/arch/lib/hrtimer.c b/arch/lib/hrtimer.c
new file mode 100644
index 0000000..4565b59
--- /dev/null
+++ b/arch/lib/hrtimer.c
@@ -0,0 +1,122 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/hrtimer.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ * @timer:      the timer to be initialized
+ * @clock_id:   the clock to be used
+ * @mode:       timer mode abs/rel
+ */
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+		  enum hrtimer_mode mode)
+{
+	memset(timer, 0, sizeof(*timer));
+}
+static void trampoline(void *context)
+{
+	struct hrtimer *timer = context;
+	enum hrtimer_restart restart = timer->function(timer);
+
+	if (restart == HRTIMER_RESTART) {
+		void *event =
+			lib_event_schedule_ns(ktime_to_ns(timer->_softexpires),
+					      &trampoline, timer);
+		timer->base = event;
+	} else {
+		/* mark as completed. */
+		timer->base = 0;
+	}
+}
+/**
+ * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
+ * @timer:      the timer to be added
+ * @tim:        expiry time
+ * @delta_ns:   "slack" range for the timer
+ * @mode:       expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
+ *
+ * Returns:
+ *  0 on success
+ *  1 when the timer was active
+ */
+int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			     unsigned long delta_ns,
+			     const enum hrtimer_mode mode,
+			     int wakeup)
+{
+	int ret = hrtimer_cancel(timer);
+	s64 ns = ktime_to_ns(tim);
+	void *event;
+
+	if (mode == HRTIMER_MODE_ABS)
+		ns -= lib_current_ns();
+	timer->_softexpires = ns_to_ktime(ns);
+	event = lib_event_schedule_ns(ns, &trampoline, timer);
+	timer->base = event;
+	return ret;
+}
+/**
+ * hrtimer_try_to_cancel - try to deactivate a timer
+ * @timer:      hrtimer to stop
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ * -1 when the timer is currently excuting the callback function and
+ *    cannot be stopped
+ */
+int hrtimer_try_to_cancel(struct hrtimer *timer)
+{
+	/* Note: we cannot return -1 from this function.
+	   see comment in hrtimer_cancel. */
+	if (timer->base == 0)
+		/* timer was not active yet */
+		return 1;
+	lib_event_cancel(timer->base);
+	timer->base = 0;
+	return 0;
+}
+/**
+ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
+ * @timer:      the timer to be cancelled
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ */
+int hrtimer_cancel(struct hrtimer *timer)
+{
+	/* Note: because we assume a uniprocessor non-interruptible */
+	/* system when running in the kernel, we know that the timer */
+	/* is not running when we execute this code, so, know that */
+	/* try_to_cancel cannot return -1 and we don't need to retry */
+	/* the cancel later to wait for the handler to finish. */
+	int ret = hrtimer_try_to_cancel(timer);
+
+	lib_assert(ret >= 0);
+	return ret;
+}
+int
+hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
+}
+int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			   unsigned long delta_ns, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, delta_ns, mode, 1);
+}
+
+int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+{
+	*tp = ns_to_timespec(1);
+	return 0;
+}
diff --git a/arch/lib/tasklet-hrtimer.c b/arch/lib/tasklet-hrtimer.c
new file mode 100644
index 0000000..fef4902
--- /dev/null
+++ b/arch/lib/tasklet-hrtimer.c
@@ -0,0 +1,57 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
+{
+	struct tasklet_hrtimer *ttimer =
+		container_of(timer, struct tasklet_hrtimer, timer);
+
+	tasklet_schedule(&ttimer->tasklet);
+	return HRTIMER_NORESTART;
+}
+static void __tasklet_hrtimer_trampoline(unsigned long data)
+{
+	struct tasklet_hrtimer *ttimer = (void *)data;
+	enum hrtimer_restart restart;
+
+	restart = ttimer->function(&ttimer->timer);
+	if (restart != HRTIMER_NORESTART)
+		hrtimer_restart(&ttimer->timer);
+}
+/**
+ * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
+ * @ttimer:      tasklet_hrtimer which is initialized
+ * @function:    hrtimer callback function which gets called from softirq context
+ * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
+ * @mode:        hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
+ */
+void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+			  enum hrtimer_restart (*function)(struct hrtimer *),
+			  clockid_t which_clock, enum hrtimer_mode mode)
+{
+	hrtimer_init(&ttimer->timer, which_clock, mode);
+	ttimer->timer.function = __hrtimer_tasklet_trampoline;
+	tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
+		     (unsigned long)ttimer);
+	ttimer->function = function;
+}
+
+void __tasklet_hi_schedule(struct tasklet_struct *t)
+{
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	void *event =
+		lib_event_schedule_ns(0, (void *)&t->func, (void *)t->data);
+	t->next = event;
+}
diff --git a/arch/lib/time.c b/arch/lib/time.c
new file mode 100644
index 0000000..5474e01
--- /dev/null
+++ b/arch/lib/time.c
@@ -0,0 +1,149 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/ktime.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+unsigned long volatile jiffies = INITIAL_JIFFIES;
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+struct timespec xtime;
+seqlock_t xtime_lock;
+/* accessed from wrap_clock from do_sys_settimeofday.
+   We don't call the latter so we should never access this variable. */
+struct timespec wall_to_monotonic;
+
+uint64_t ns_to_jiffies(uint64_t ns)
+{
+	do_div(ns, (1000000000 / HZ));
+	return ns;
+}
+
+void lib_update_jiffies(void)
+{
+	jiffies = ns_to_jiffies(lib_current_ns());
+	jiffies_64 = ns_to_jiffies(lib_current_ns());
+}
+
+struct timespec current_kernel_time(void)
+{
+	u64 ns = lib_current_ns();
+	struct timespec spec = ns_to_timespec(ns);
+
+	return spec;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	u64 ns = lib_current_ns();
+
+	*tv = ns_to_timeval(ns);
+}
+
+int cap_settime(struct timespec *ts, struct timezone *tz)
+{
+	lib_assert(false);
+	return -EPERM;
+}
+int do_adjtimex(struct timex *timex)
+{
+	lib_assert(false);
+	return -EPERM;
+}
+ktime_t ktime_get(void)
+{
+	u64 ns = lib_current_ns();
+
+	return ns_to_ktime(ns);
+}
+ktime_t ktime_get_with_offset(enum tk_offsets offs)
+{
+	/* FIXME */
+	return ktime_get();
+}
+
+/* copied from kernel/time/hrtimeer.c */
+#if BITS_PER_LONG < 64
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+u64 __ktime_divns(const ktime_t kt, s64 div)
+{
+	u64 dclc;
+	int sft = 0;
+
+	dclc = ktime_to_ns(kt);
+	/* Make sure the divisor is less than 2^32: */
+	while (div >> 32) {
+		sft++;
+		div >>= 1;
+	}
+	dclc >>= sft;
+	do_div(dclc, (unsigned long)div);
+
+	return dclc;
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+void update_xtime_cache(u64 nsec)
+{
+}
+unsigned long get_seconds(void)
+{
+	u64 ns = lib_current_ns();
+
+	do_div(ns, 1000000000);
+	return ns;
+}
+static unsigned long
+round_jiffies_common(unsigned long j,
+		     bool force_up)
+{
+	int rem;
+	unsigned long original = j;
+
+	rem = j % HZ;
+	if (rem < HZ / 4 && !force_up)  /* round down */
+		j = j - rem;
+	else                            /* round up */
+		j = j - rem + HZ;
+	if (j <= jiffies)               /* rounding ate our timeout entirely; */
+		return original;
+	return j;
+}
+unsigned long round_jiffies(unsigned long j)
+{
+	return round_jiffies_common(j, false);
+}
+unsigned long round_jiffies_relative(unsigned long j)
+{
+	unsigned long j0 = jiffies;
+
+	/* Use j0 because jiffies might change while we run */
+	return round_jiffies_common(j + j0, false) - j0;
+}
+unsigned long round_jiffies_up(unsigned long j)
+{
+	return round_jiffies_common(j, true);
+}
+static void msleep_trampoline(void *context)
+{
+	struct SimTask *task = context;
+
+	lib_task_wakeup(task);
+}
+void msleep(unsigned int msecs)
+{
+	lib_event_schedule_ns(((__u64)msecs) * 1000000, &msleep_trampoline,
+			      lib_task_current());
+	lib_task_wait();
+}
diff --git a/arch/lib/timer.c b/arch/lib/timer.c
new file mode 100644
index 0000000..4d19626
--- /dev/null
+++ b/arch/lib/timer.c
@@ -0,0 +1,230 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * init_timer_key - initialize a timer
+ * @timer: the timer to be initialized
+ * @name: name of the timer
+ * @key: lockdep class key of the fake lock used for tracking timer
+ *       sync lock dependencies
+ *
+ * init_timer_key() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void init_timer_key(struct timer_list *timer,
+		    unsigned int flags,
+		    const char *name,
+		    struct lock_class_key *key)
+{
+	/**
+	 * Note: name and key are used for debugging. We ignore them
+	 * unconditionally.
+	 * Note: we do not initialize the lockdep map either because we
+	 * don't care.
+	 * and, finally, we never care about the base field either.
+	 *
+	 * So, for now, we have a timer which is marked as "not started"
+	 * thanks to its entry.next field set to NULL (timer_pending
+	 * will return 0)
+	 */
+	timer->entry.next = NULL;
+	timer->base = 0;
+}
+
+struct list_head g_expired_events = LIST_HEAD_INIT(g_expired_events);
+struct list_head g_pending_events = LIST_HEAD_INIT(g_pending_events);
+
+static void run_timer_softirq(struct softirq_action *h)
+{
+	while (!list_empty(&g_expired_events)) {
+		struct timer_list *timer = list_first_entry(&g_expired_events,
+							    struct timer_list,
+							    entry);
+		void (*fn)(unsigned long);
+		unsigned long data;
+
+		fn = timer->function;
+		data = timer->data;
+		lib_assert(timer->base == 0);
+		if (timer->entry.prev != LIST_POISON2) {
+			list_del(&timer->entry);
+			timer->entry.next = NULL;
+			fn(data);
+		}
+	}
+}
+
+static void ensure_softirq_opened(void)
+{
+	static bool opened = false;
+
+	if (opened)
+		return;
+	opened = true;
+	open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
+}
+static void timer_trampoline(void *context)
+{
+	struct timer_list *timer;
+
+	ensure_softirq_opened();
+	timer = context;
+	timer->base = 0;
+	if (timer->entry.prev != LIST_POISON2)
+		list_del(&timer->entry);
+	list_add_tail(&timer->entry, &g_expired_events);
+	raise_softirq(TIMER_SOFTIRQ);
+}
+/**
+ * add_timer - start a timer
+ * @timer: the timer to be added
+ *
+ * The kernel will do a ->function(->data) callback from the
+ * timer interrupt at the ->expires point in the future. The
+ * current time is 'jiffies'.
+ *
+ * The timer's ->expires, ->function (and if the handler uses it, ->data)
+ * fields must be set prior calling this function.
+ *
+ * Timers with an ->expires field in the past will be executed in the next
+ * timer tick.
+ */
+void add_timer(struct timer_list *timer)
+{
+	__u64 delay_ns = 0;
+
+	lib_assert(!timer_pending(timer));
+	if (timer->expires <= jiffies)
+		delay_ns = (1000000000 / HZ); /* next tick. */
+	else
+		delay_ns =
+			((__u64)timer->expires *
+			 (1000000000 / HZ)) - lib_current_ns();
+	void *event = lib_event_schedule_ns(delay_ns, &timer_trampoline, timer);
+	/* store the external event in the base field */
+	/* to be able to retrieve it from del_timer */
+	timer->base = event;
+	/* finally, store timer in list of pending events. */
+	list_add_tail(&timer->entry, &g_pending_events);
+}
+/**
+ * del_timer - deactive a timer.
+ * @timer: the timer to be deactivated
+ *
+ * del_timer() deactivates a timer - this works on both active and inactive
+ * timers.
+ *
+ * The function returns whether it has deactivated a pending timer or not.
+ * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
+ * active timer returns 1.)
+ */
+int del_timer(struct timer_list *timer)
+{
+	int retval;
+
+	if (timer->entry.next == 0)
+		return 0;
+	if (timer->base != 0) {
+		lib_event_cancel(timer->base);
+		retval = 1;
+	} else
+		retval = 0;
+	if (timer->entry.prev != LIST_POISON2) {
+		list_del(&timer->entry);
+		timer->entry.next = NULL;
+	}
+	return retval;
+}
+
+/* ////////////////////// */
+
+void init_timer_deferrable_key(struct timer_list *timer,
+			       const char *name,
+			       struct lock_class_key *key)
+{
+	/**
+	 * From lwn.net:
+	 * Timers which are initialized in this fashion will be
+	 * recognized as deferrable by the kernel. They will not
+	 * be considered when the kernel makes its "when should
+	 * the next timer interrupt be?" decision. When the system
+	 * is busy these timers will fire at the scheduled time. When
+	 * things are idle, instead, they will simply wait until
+	 * something more important wakes up the processor.
+	 *
+	 * Note: Our implementation of deferrable timers uses
+	 * non-deferrable timers for simplicity.
+	 */
+	init_timer_key(timer, 0, name, key);
+}
+/**
+ * add_timer_on - start a timer on a particular CPU
+ * @timer: the timer to be added
+ * @cpu: the CPU to start it on
+ *
+ * This is not very scalable on SMP. Double adds are not possible.
+ */
+void add_timer_on(struct timer_list *timer, int cpu)
+{
+	/* we ignore the cpu: we have only one. */
+	add_timer(timer);
+}
+/**
+ * mod_timer - modify a timer's timeout
+ * @timer: the timer to be modified
+ * @expires: new timeout in jiffies
+ *
+ * mod_timer() is a more efficient way to update the expire field of an
+ * active timer (if the timer is inactive it will be activated)
+ *
+ * mod_timer(timer, expires) is equivalent to:
+ *
+ *     del_timer(timer); timer->expires = expires; add_timer(timer);
+ *
+ * Note that if there are multiple unserialized concurrent users of the
+ * same timer, then mod_timer() is the only safe way to modify the timeout,
+ * since add_timer() cannot modify an already running timer.
+ *
+ * The function returns whether it has modified a pending timer or not.
+ * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
+ * active timer returns 1.)
+ */
+int mod_timer(struct timer_list *timer, unsigned long expires)
+{
+	int ret;
+
+	/* common optimization stolen from kernel */
+	if (timer_pending(timer) && timer->expires == expires)
+		return 1;
+
+	ret = del_timer(timer);
+	timer->expires = expires;
+	add_timer(timer);
+	return ret;
+}
+/**
+ * mod_timer_pending - modify a pending timer's timeout
+ * @timer: the pending timer to be modified
+ * @expires: new timeout in jiffies
+ *
+ * mod_timer_pending() is the same for pending timers as mod_timer(),
+ * but will not re-activate and modify already deleted timers.
+ *
+ * It is useful for unserialized use of timers.
+ */
+int mod_timer_pending(struct timer_list *timer, unsigned long expires)
+{
+	if (timer_pending(timer))
+		return 0;
+	return mod_timer(timer, expires);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 06/11] lib: context and scheduling handling (kernel glue code)
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (4 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 05/11] lib: time handling " Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 07/11] lib: sysctl " Hajime Tazaki
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/sched.c     | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/softirq.c   | 104 +++++++++++++++
 arch/lib/tasklet.c   |  76 +++++++++++
 arch/lib/workqueue.c | 242 ++++++++++++++++++++++++++++++++++
 4 files changed, 787 insertions(+)
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/workqueue.c

diff --git a/arch/lib/sched.c b/arch/lib/sched.c
new file mode 100644
index 0000000..168e744
--- /dev/null
+++ b/arch/lib/sched.c
@@ -0,0 +1,365 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
+#include "lib.h"
+#include "sim.h"
+#include "sim-assert.h"
+
+/**
+   called by wait_event macro:
+   - prepare_to_wait
+   - schedule
+   - finish_wait
+ */
+
+struct SimTask *lib_task_create(void *private, unsigned long pid)
+{
+	struct SimTask *task = lib_malloc(sizeof(struct SimTask));
+	struct cred *cred;
+	struct nsproxy *ns;
+	struct user_struct *user;
+	struct thread_info *info;
+	struct pid *kpid;
+
+	if (!task)
+		return NULL;
+	memset(task, 0, sizeof(struct SimTask));
+	cred = lib_malloc(sizeof(struct cred));
+	if (!cred)
+		return NULL;
+	/* XXX: we could optimize away this allocation by sharing it
+	   for all tasks */
+	ns = lib_malloc(sizeof(struct nsproxy));
+	if (!ns)
+		return NULL;
+	user = lib_malloc(sizeof(struct user_struct));
+	if (!user)
+		return NULL;
+	info = alloc_thread_info(&task->kernel_task);
+	if (!info)
+		return NULL;
+	kpid = lib_malloc(sizeof(struct pid));
+	if (!kpid)
+		return NULL;
+	kpid->numbers[0].nr = pid;
+	cred->fsuid = make_kuid(current_user_ns(), 0);
+	cred->fsgid = make_kgid(current_user_ns(), 0);
+	cred->user = user;
+	atomic_set(&cred->usage, 1);
+	info->task = &task->kernel_task;
+	info->preempt_count = 0;
+	info->flags = 0;
+	atomic_set(&ns->count, 1);
+	ns->uts_ns = 0;
+	ns->ipc_ns = 0;
+	ns->mnt_ns = 0;
+	ns->pid_ns_for_children = 0;
+	ns->net_ns = &init_net;
+	task->kernel_task.cred = cred;
+	task->kernel_task.pid = pid;
+	task->kernel_task.pids[PIDTYPE_PID].pid = kpid;
+	task->kernel_task.pids[PIDTYPE_PGID].pid = kpid;
+	task->kernel_task.pids[PIDTYPE_SID].pid = kpid;
+	task->kernel_task.nsproxy = ns;
+	task->kernel_task.stack = info;
+	/* this is a hack. */
+	task->kernel_task.group_leader = &task->kernel_task;
+	task->private = private;
+	return task;
+}
+void lib_task_destroy(struct SimTask *task)
+{
+	lib_free((void *)task->kernel_task.nsproxy);
+	lib_free((void *)task->kernel_task.cred);
+	lib_free((void *)task->kernel_task.cred->user);
+	free_thread_info(task->kernel_task.stack);
+	lib_free(task);
+}
+void *lib_task_get_private(struct SimTask *task)
+{
+	return task->private;
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct SimTask *task = lib_task_start((void (*)(void *))fn, arg);
+
+	return task->kernel_task.pid;
+}
+
+struct task_struct *get_current(void)
+{
+	struct SimTask *lib_task = lib_task_current();
+
+	return &lib_task->kernel_task;
+}
+
+struct thread_info *current_thread_info(void)
+{
+	return task_thread_info(get_current());
+}
+struct thread_info *alloc_thread_info(struct task_struct *task)
+{
+	return lib_malloc(sizeof(struct thread_info));
+}
+void free_thread_info(struct thread_info *ti)
+{
+	lib_free(ti);
+}
+
+
+void __put_task_struct(struct task_struct *t)
+{
+	lib_free(t);
+}
+
+void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+	list_add(&wait->task_list, &q->task_list);
+}
+void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	list_add_tail(&wait->task_list, &q->task_list);
+}
+void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	if (wait->task_list.prev != LIST_POISON2)
+		list_del(&wait->task_list);
+}
+void
+prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	if (list_empty(&wait->task_list))
+		list_add_tail(&wait->task_list, &q->task_list);
+	set_current_state(state);
+}
+void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	unsigned long flags;
+
+	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+	spin_lock_irqsave(&q->lock, flags);
+	if (list_empty(&wait->task_list))
+		__add_wait_queue(q, wait);
+	set_current_state(state);
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	set_current_state(TASK_RUNNING);
+	if (!list_empty(&wait->task_list))
+		list_del_init(&wait->task_list);
+}
+int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync,
+			     void *key)
+{
+	int ret = default_wake_function(wait, mode, sync, key);
+
+	if (ret && (wait->task_list.prev != LIST_POISON2))
+		list_del_init(&wait->task_list);
+
+	return ret;
+}
+
+int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	wait->flags |= WQ_FLAG_WOKEN;
+	return default_wake_function(wait, mode, sync, key);
+}
+
+void __init_waitqueue_head(wait_queue_head_t *q, const char *name,
+			   struct lock_class_key *k)
+{
+	INIT_LIST_HEAD(&q->task_list);
+}
+/**
+ * wait_for_completion: - waits for completion of a task
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It is NOT
+ * interruptible and there is no timeout.
+ *
+ * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
+ * and interrupt capability. Also see complete().
+ */
+void wait_for_completion(struct completion *x)
+{
+	wait_for_completion_timeout(x, MAX_SCHEDULE_TIMEOUT);
+}
+unsigned long wait_for_completion_timeout(struct completion *x,
+					  unsigned long timeout)
+{
+	if (!x->done) {
+		DECLARE_WAITQUEUE(wait, current);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		wait.flags |= WQ_FLAG_EXCLUSIVE;
+		list_add_tail(&wait.task_list, &x->wait.task_list);
+		do
+			timeout = schedule_timeout(timeout);
+		while (!x->done && timeout);
+		if (wait.task_list.prev != LIST_POISON2)
+			list_del(&wait.task_list);
+
+		if (!x->done)
+			return timeout;
+	}
+	x->done--;
+	return timeout ? : 1;
+}
+
+/**
+ * __wake_up - wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ * @key: is directly passed to the wakeup function
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void __wake_up(wait_queue_head_t *q, unsigned int mode,
+	       int nr_exclusive, void *key)
+{
+	wait_queue_t *curr, *next;
+
+	list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
+		unsigned flags = curr->flags;
+
+		if (curr->func(curr, mode, 0, key) &&
+		    (flags & WQ_FLAG_EXCLUSIVE) &&
+		    !--nr_exclusive)
+			break;
+	}
+}
+void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
+			int nr_exclusive, void *key)
+{
+	__wake_up(q, mode, nr_exclusive, key);
+}
+int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
+			  void *key)
+{
+	struct task_struct *task = (struct task_struct *)curr->private;
+	struct SimTask *lib_task = container_of(task, struct SimTask,
+						kernel_task);
+
+	return lib_task_wakeup(lib_task);
+}
+
+
+void schedule(void)
+{
+	lib_task_wait();
+}
+
+static void trampoline(void *context)
+{
+	struct SimTask *task = context;
+
+	lib_task_wakeup(task);
+}
+
+signed long schedule_timeout(signed long timeout)
+{
+	u64 ns;
+	struct SimTask *self;
+
+	if (timeout == MAX_SCHEDULE_TIMEOUT) {
+		lib_task_wait();
+		return MAX_SCHEDULE_TIMEOUT;
+	}
+	lib_assert(timeout >= 0);
+	ns = ((__u64)timeout) * (1000000000 / HZ);
+	self = lib_task_current();
+	lib_event_schedule_ns(ns, &trampoline, self);
+	lib_task_wait();
+	/* we know that we are always perfectly on time. */
+	return 0;
+}
+
+signed long schedule_timeout_uninterruptible(signed long timeout)
+{
+	return schedule_timeout(timeout);
+}
+signed long schedule_timeout_interruptible(signed long timeout)
+{
+	return schedule_timeout(timeout);
+}
+
+void yield(void)
+{
+	lib_task_yield();
+}
+
+void complete_all(struct completion *x)
+{
+	x->done += UINT_MAX / 2;
+	__wake_up(&x->wait, TASK_NORMAL, 0, 0);
+}
+void complete(struct completion *x)
+{
+	x->done++;
+	__wake_up(&x->wait, TASK_NORMAL, 1, 0);
+}
+
+long wait_for_completion_interruptible_timeout(
+	struct completion *x, unsigned long timeout)
+{
+	return wait_for_completion_timeout(x, timeout);
+}
+int wait_for_completion_interruptible(struct completion *x)
+{
+	wait_for_completion_timeout(x, MAX_SCHEDULE_TIMEOUT);
+	return 0;
+}
+int wake_up_process(struct task_struct *tsk)
+{
+	struct SimTask *lib_task =
+		container_of(tsk, struct SimTask, kernel_task);
+
+	return lib_task_wakeup(lib_task);
+}
+int _cond_resched(void)
+{
+	/* we never schedule to decrease latency. */
+	return 0;
+}
+int idle_cpu(int cpu)
+{
+	/* we are never idle: we call this from rcutiny.c and the answer */
+	/* does not matter, really. */
+	return 0;
+}
+
+unsigned long long __attribute__((weak)) sched_clock(void)
+{
+	return (unsigned long long)(jiffies - INITIAL_JIFFIES)
+	       * (NSEC_PER_SEC / HZ);
+}
+
+u64 local_clock(void)
+{
+	return sched_clock();
+}
+
+void __sched schedule_preempt_disabled(void)
+{
+}
+
+void resched_cpu(int cpu)
+{
+	rcu_sched_qs();
+}
diff --git a/arch/lib/softirq.c b/arch/lib/softirq.c
new file mode 100644
index 0000000..609db7e
--- /dev/null
+++ b/arch/lib/softirq.c
@@ -0,0 +1,104 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim-init.h"
+#include "sim.h"
+#include "sim-assert.h"
+
+
+static struct softirq_action softirq_vec[NR_SOFTIRQS];
+static struct SimTask *g_softirq_task = 0;
+static int g_n_raises = 0;
+
+void lib_softirq_wakeup(void)
+{
+	g_n_raises++;
+	lib_task_wakeup(g_softirq_task);
+}
+
+static void softirq_task_function(void *context)
+{
+	while (true) {
+		do_softirq();
+		g_n_raises--;
+		if (g_n_raises == 0 || local_softirq_pending() == 0) {
+			g_n_raises = 0;
+			lib_task_wait();
+		}
+	}
+}
+
+static void ensure_task_created(void)
+{
+	if (g_softirq_task != 0)
+		return;
+	g_softirq_task = lib_task_start(&softirq_task_function, 0);
+}
+
+void open_softirq(int nr, void (*action)(struct softirq_action *))
+{
+	ensure_task_created();
+	softirq_vec[nr].action = action;
+}
+#define MAX_SOFTIRQ_RESTART 10
+
+void do_softirq(void)
+{
+	__u32 pending;
+	int max_restart = MAX_SOFTIRQ_RESTART;
+	struct softirq_action *h;
+
+	pending = local_softirq_pending();
+
+restart:
+	/* Reset the pending bitmask before enabling irqs */
+	set_softirq_pending(0);
+
+	local_irq_enable();
+
+	h = softirq_vec;
+
+	do {
+		if (pending & 1)
+			h->action(h);
+		h++;
+		pending >>= 1;
+	} while (pending);
+
+	local_irq_disable();
+
+	pending = local_softirq_pending();
+	if (pending && --max_restart)
+		goto restart;
+}
+void raise_softirq_irqoff(unsigned int nr)
+{
+	__raise_softirq_irqoff(nr);
+
+	lib_softirq_wakeup();
+}
+void __raise_softirq_irqoff(unsigned int nr)
+{
+	/* trace_softirq_raise(nr); */
+	or_softirq_pending(1UL << nr);
+}
+int __cond_resched_softirq(void)
+{
+	/* tell the caller that we did not need to re-schedule. */
+	return 0;
+}
+void raise_softirq(unsigned int nr)
+{
+	/* copy/paste from kernel/softirq.c */
+	unsigned long flags;
+
+	local_irq_save(flags);
+	raise_softirq_irqoff(nr);
+	local_irq_restore(flags);
+}
diff --git a/arch/lib/tasklet.c b/arch/lib/tasklet.c
new file mode 100644
index 0000000..6cc68f4
--- /dev/null
+++ b/arch/lib/tasklet.c
@@ -0,0 +1,76 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+void tasklet_init(struct tasklet_struct *t,
+		  void (*func)(unsigned long), unsigned long data)
+{
+	t->next = NULL;
+	t->state = 0;
+	atomic_set(&t->count, 0);
+	t->func = func;
+	t->data = data;
+}
+
+void tasklet_kill(struct tasklet_struct *t)
+{
+	/* theoretically, called from user context */
+	while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
+		do
+			lib_task_yield();
+		while (test_bit(TASKLET_STATE_SCHED, &t->state));
+	}
+	clear_bit(TASKLET_STATE_SCHED, &t->state);
+}
+struct tasklet_struct *g_sched_events = NULL;
+static void run_tasklet_softirq(struct softirq_action *h)
+{
+	/* while (!list_empty (&g_sched_events)) */
+	/*   { */
+	struct tasklet_struct *tasklet = g_sched_events;
+
+	if (atomic_read(&tasklet->count) == 0) {
+		/* this tasklet is enabled so, we run it. */
+		test_and_clear_bit(TASKLET_STATE_SCHED, &tasklet->state);
+		tasklet->func(tasklet->data);
+	}
+	/* } */
+}
+static void ensure_softirq_opened(void)
+{
+	static bool opened = false;
+
+	if (opened)
+		return;
+	opened = true;
+	open_softirq(TASKLET_SOFTIRQ, run_tasklet_softirq);
+}
+static void trampoline(void *context)
+{
+	ensure_softirq_opened();
+	struct tasklet_struct *tasklet = context;
+	/* allow the tasklet to re-schedule itself */
+	lib_assert(tasklet->next != 0);
+	tasklet->next = 0;
+	g_sched_events = tasklet;
+	raise_softirq(TASKLET_SOFTIRQ);
+}
+void __tasklet_schedule(struct tasklet_struct *t)
+{
+	void *event;
+
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	event = lib_event_schedule_ns(0, &trampoline, t);
+	t->next = event;
+}
diff --git a/arch/lib/workqueue.c b/arch/lib/workqueue.c
new file mode 100644
index 0000000..bd0e9c5
--- /dev/null
+++ b/arch/lib/workqueue.c
@@ -0,0 +1,242 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+/* copy from kernel/workqueue.c */
+typedef unsigned long mayday_mask_t;
+struct workqueue_struct {
+	unsigned int flags;                     /* W: WQ_* flags */
+	union {
+		struct cpu_workqueue_struct __percpu *pcpu;
+		struct cpu_workqueue_struct *single;
+		unsigned long v;
+	} cpu_wq;                               /* I: cwq's */
+	struct list_head list;                  /* W: list of all workqueues */
+
+	struct mutex flush_mutex;               /* protects wq flushing */
+	int work_color;                         /* F: current work color */
+	int flush_color;                        /* F: current flush color */
+	atomic_t nr_cwqs_to_flush;              /* flush in progress */
+	struct wq_flusher *first_flusher;       /* F: first flusher */
+	struct list_head flusher_queue;         /* F: flush waiters */
+	struct list_head flusher_overflow;      /* F: flush overflow list */
+
+	mayday_mask_t mayday_mask;              /* cpus requesting rescue */
+	struct worker *rescuer;                 /* I: rescue worker */
+
+	int nr_drainers;                        /* W: drain in progress */
+	int saved_max_active;                   /* W: saved cwq max_active */
+#ifdef CONFIG_LOCKDEP
+	struct lockdep_map lockdep_map;
+#endif
+	char name[];                            /* I: workqueue name */
+};
+
+struct wq_barrier {
+	struct SimTask *waiter;
+	struct workqueue_struct wq;
+};
+
+static void
+workqueue_function(void *context)
+{
+	struct workqueue_struct *wq = context;
+
+	while (true) {
+		lib_task_wait();
+		while (!list_empty(&wq->list)) {
+			struct work_struct *work =
+				list_first_entry(&wq->list, struct work_struct,
+						entry);
+			work_func_t f = work->func;
+
+			if (work->entry.prev != LIST_POISON2) {
+				list_del_init(&work->entry);
+				clear_bit(WORK_STRUCT_PENDING_BIT,
+					  work_data_bits(work));
+				f(work);
+			}
+		}
+	}
+}
+
+static struct SimTask *workqueue_task(struct workqueue_struct *wq)
+{
+	struct wq_barrier *barr = container_of(wq, struct wq_barrier, wq);
+
+	if (barr->waiter == 0)
+		barr->waiter = lib_task_start(&workqueue_function, wq);
+	return barr->waiter;
+}
+
+static int flush_entry(struct workqueue_struct *wq, struct list_head *prev)
+{
+	int active = 0;
+
+	if (!list_empty(&wq->list)) {
+		active = 1;
+		lib_task_wakeup(workqueue_task(wq));
+		/* XXX: should wait for completion? but this will block
+		   and init won't return.. */
+		/* lib_task_wait (); */
+	}
+
+	return active;
+}
+
+void delayed_work_timer_fn(unsigned long data)
+{
+	struct delayed_work *dwork = (struct delayed_work *)data;
+	struct work_struct *work = &dwork->work;
+
+	list_add_tail(&work->entry, &dwork->wq->list);
+	lib_task_wakeup(workqueue_task(dwork->wq));
+}
+
+bool queue_work_on(int cpu, struct workqueue_struct *wq,
+		   struct work_struct *work)
+{
+	int ret = 0;
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
+		list_add_tail(&work->entry, &wq->list);
+		lib_task_wakeup(workqueue_task(wq));
+		ret = 1;
+	}
+	return ret;
+}
+
+void flush_scheduled_work(void)
+{
+	flush_entry(system_wq, system_wq->list.prev);
+}
+bool flush_work(struct work_struct *work)
+{
+	return flush_entry(system_wq, &work->entry);
+}
+void flush_workqueue(struct workqueue_struct *wq)
+{
+	flush_entry(wq, wq->list.prev);
+}
+bool cancel_work_sync(struct work_struct *work)
+{
+	int retval = 0;
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)))
+		/* work was not yet queued */
+		return 0;
+	if (!list_empty(&work->entry)) {
+		/* work was queued. now unqueued. */
+		if (work->entry.prev != LIST_POISON2) {
+			list_del_init(&work->entry);
+			clear_bit(WORK_STRUCT_PENDING_BIT,
+				  work_data_bits(work));
+			retval = 1;
+		}
+	}
+	return retval;
+}
+bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+			   struct delayed_work *dwork, unsigned long delay)
+{
+	int ret = 0;
+	struct timer_list *timer = &dwork->timer;
+	struct work_struct *work = &dwork->work;
+
+	if (delay == 0)
+		return queue_work(wq, work);
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
+		lib_assert(!timer_pending(timer));
+		dwork->wq = wq;
+		/* This stores cwq for the moment, for the timer_fn */
+		timer->expires = jiffies + delay;
+		timer->data = (unsigned long)dwork;
+		timer->function = delayed_work_timer_fn;
+		add_timer(timer);
+		ret = 1;
+	}
+	return ret;
+}
+bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
+			 struct delayed_work *dwork, unsigned long delay)
+{
+	del_timer(&dwork->timer);
+	__clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&dwork->work));
+	return queue_delayed_work(wq, dwork, delay);
+}
+bool cancel_delayed_work(struct delayed_work *dwork)
+{
+	del_timer(&dwork->timer);
+	return cancel_work_sync(&dwork->work);
+}
+
+struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
+					       unsigned int flags,
+					       int max_active,
+					       struct lock_class_key *key,
+					       const char *lock_name, ...)
+{
+	va_list args, args1;
+	struct wq_barrier *barr;
+	struct workqueue_struct *wq;
+	size_t namelen;
+
+	/* determine namelen, allocate wq and format name */
+	va_start(args, lock_name);
+	va_copy(args1, args);
+	namelen = vsnprintf(NULL, 0, fmt, args) + 1;
+
+	barr = kzalloc(sizeof(*barr) + namelen, GFP_KERNEL);
+	if (!barr)
+		goto err;
+	barr->waiter = 0;
+	wq = &barr->wq;
+
+	vsnprintf(wq->name, namelen, fmt, args1);
+	va_end(args);
+	va_end(args1);
+
+	max_active = max_active ? : WQ_DFL_ACTIVE;
+	/* init wq */
+	wq->flags = flags;
+	wq->saved_max_active = max_active;
+	mutex_init(&wq->flush_mutex);
+	atomic_set(&wq->nr_cwqs_to_flush, 0);
+	INIT_LIST_HEAD(&wq->flusher_queue);
+	INIT_LIST_HEAD(&wq->flusher_overflow);
+
+	lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
+	INIT_LIST_HEAD(&wq->list);
+
+	/* start waiter task */
+	workqueue_task(wq);
+	return wq;
+err:
+	if (barr)
+		kfree(barr);
+	return NULL;
+}
+
+struct workqueue_struct *system_wq __read_mostly;
+struct workqueue_struct *system_power_efficient_wq __read_mostly;
+/* from linux/workqueue.h */
+#define system_nrt_wq                   __system_nrt_wq()
+
+static int __init init_workqueues(void)
+{
+	system_wq = alloc_workqueue("events", 0, 0);
+	system_power_efficient_wq = alloc_workqueue("events_power_efficient",
+						    WQ_POWER_EFFICIENT, 0);
+	return 0;
+}
+early_initcall(init_workqueues);
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 07/11] lib: sysctl handling (kernel glue code)
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (5 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 06/11] lib: context and scheduling " Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 08/11] lib: other kernel glue layer code Hajime Tazaki
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

This interacts with fs/proc_fs.c for sysctl-like interface accessed via
lib_init() API.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/sysctl.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 284 insertions(+)
 create mode 100644 arch/lib/sysctl.c

diff --git a/arch/lib/sysctl.c b/arch/lib/sysctl.c
new file mode 100644
index 0000000..1f74bbd
--- /dev/null
+++ b/arch/lib/sysctl.c
@@ -0,0 +1,284 @@
+/*
+ * sysctl wrapper for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/mman.h>
+#include <linux/ratelimit.h>
+#include <linux/proc_fs.h>
+#include "sim-assert.h"
+#include "sim-types.h"
+
+int drop_caches_sysctl_handler(struct ctl_table *table, int write,
+			       void *buffer, size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *table, int write,
+					void *buffer, size_t *length,
+					loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write,
+					    void *buffer, size_t *length,
+					    loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_background_ratio_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *lenp,
+				   loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_background_bytes_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *lenp,
+				   loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_ratio_handler(struct ctl_table *table, int write,
+			void *buffer, size_t *lenp,
+			loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_bytes_handler(struct ctl_table *table, int write,
+			void *buffer, size_t *lenp,
+			loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_writeback_centisecs_handler(struct ctl_table *table, int write,
+				      void *buffer, size_t *length,
+				      loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int scan_unevictable_handler(struct ctl_table *table, int write,
+			     void __user *buffer,
+			     size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int sched_rt_handler(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS;
+int sysctl_overcommit_ratio = 50;
+int sysctl_panic_on_oom = 0;
+int sysctl_oom_dump_tasks = 0;
+int sysctl_oom_kill_allocating_task = 0;
+int sysctl_nr_open = 1024 * 1024;
+int sysctl_nr_open_min = BITS_PER_LONG;
+int sysctl_nr_open_max = 1024 * 1024;
+int sysctl_nr_trim_pages = 0;
+int sysctl_drop_caches = 0;
+int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES - 1] = { 32 };
+int sysctl_vfs_cache_pressure = 100;
+unsigned int sysctl_sched_child_runs_first = 0;
+unsigned int sysctl_sched_compat_yield = 0;
+unsigned int sysctl_sched_rt_period = 1000000;
+int sysctl_sched_rt_runtime = 950000;
+
+int vm_highmem_is_dirtyable;
+unsigned long vm_dirty_bytes = 0;
+int vm_dirty_ratio = 20;
+int dirty_background_ratio = 10;
+unsigned int dirty_expire_interval = 30 * 100;
+unsigned int dirty_writeback_interval = 5 * 100;
+unsigned long dirty_background_bytes = 0;
+int percpu_pagelist_fraction = 0;
+int panic_timeout = 0;
+int panic_on_oops = 0;
+int printk_delay_msec = 0;
+int panic_on_warn = 0;
+DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
+
+#define RESERVED_PIDS 300
+int pid_max = PID_MAX_DEFAULT;
+int pid_max_min = RESERVED_PIDS + 1;
+int pid_max_max = PID_MAX_LIMIT;
+int min_free_kbytes = 1024;
+int max_threads = 100;
+int laptop_mode = 0;
+
+#define DEFAULT_MESSAGE_LOGLEVEL 4
+#define MINIMUM_CONSOLE_LOGLEVEL 1
+#define DEFAULT_CONSOLE_LOGLEVEL 7
+int console_printk[4] = {
+	DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
+	DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
+	MINIMUM_CONSOLE_LOGLEVEL,       /* minimum_console_loglevel */
+	DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
+};
+
+int print_fatal_signals = 0;
+unsigned int core_pipe_limit = 0;
+int core_uses_pid = 0;
+int vm_swappiness = 60;
+int nr_pdflush_threads = 0;
+unsigned long scan_unevictable_pages = 0;
+int suid_dumpable = 0;
+int page_cluster = 0;
+int block_dump = 0;
+int C_A_D = 0;
+#include <linux/nsproxy.h>
+struct nsproxy init_nsproxy;
+#include <linux/reboot.h>
+char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
+#include <linux/pipe_fs_i.h>
+unsigned int pipe_max_pages =  PIPE_DEF_BUFFERS * 16;
+unsigned int pipe_max_size = 1048576;
+unsigned int pipe_min_size = PAGE_SIZE;
+unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
+unsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */
+
+int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
+		 size_t *lenp, loff_t *ppos)
+{
+	return -1;
+}
+
+int pdflush_proc_obsolete(struct ctl_table *table, int write,
+			  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return nr_pdflush_threads;
+}
+
+#include <linux/fs.h>
+
+/**
+ * Honestly, I don't understand half of that code.
+ * It was modeled after fs/proc/proc_sysctl.c proc_sys_readdir
+ *
+ * Me either ;) (Hajime, Jan 2013)
+ */
+
+/* from proc_sysctl.c (XXX) */
+extern struct ctl_table_root sysctl_table_root;
+void first_entry(struct ctl_dir *dir,
+		 struct ctl_table_header **phead, struct ctl_table **pentry);
+void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry);
+struct ctl_table *find_entry(struct ctl_table_header **phead,
+			     struct ctl_dir *dir, const char *name,
+			     int namelen);
+struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir);
+/* for init_net (XXX, should be fixed) */
+#include <net/net_namespace.h>
+
+static void iterate_table_recursive(const struct SimSysIterator *iter,
+				    struct ctl_table_header *head)
+{
+	struct ctl_table *entry;
+
+	for (entry = head->ctl_table; entry->procname; entry++) {
+		bool may_read = (head->ctl_table->mode & MAY_READ);
+		bool may_write = (head->ctl_table->mode & MAY_WRITE);
+		int flags = 0;
+
+		flags |= may_read ? SIM_SYS_FILE_READ : 0;
+		flags |= may_write ? SIM_SYS_FILE_WRITE : 0;
+		iter->report_file(iter, entry->procname, flags,
+				  (struct SimSysFile *)entry);
+	}
+}
+
+
+static void iterate_recursive(const struct SimSysIterator *iter,
+			      struct ctl_table_header *head)
+{
+	struct ctl_table_header *h = NULL;
+	struct ctl_table *entry;
+	struct ctl_dir *ctl_dir;
+
+	ctl_dir = container_of(head, struct ctl_dir, header);
+	for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
+		struct ctl_dir *dir;
+		int ret;
+		const char *procname;
+
+		/* copy from sysctl_follow_link () */
+		if (S_ISLNK(entry->mode)) {
+			dir = xlate_dir(&init_net.sysctls, h->parent);
+			if (IS_ERR(dir)) {
+				ret = PTR_ERR(dir);
+				lib_assert(false);
+			} else {
+				procname = entry->procname;
+				h = NULL;
+				entry =
+					find_entry(&h, dir, procname,
+						   strlen(procname));
+				ret = -ENOENT;
+			}
+		}
+
+		if (S_ISDIR(entry->mode)) {
+			iter->report_start_dir(iter, entry->procname);
+			iterate_recursive(iter, h);
+			iter->report_end_dir(iter);
+		} else
+			iterate_table_recursive(iter, h);
+	}
+
+}
+
+
+void lib_sys_iterate_files(const struct SimSysIterator *iter)
+{
+	struct ctl_table_header *root =
+		&sysctl_table_root.default_set.dir.header;
+
+	iterate_recursive(iter, root);
+}
+
+int lib_sys_file_read(const struct SimSysFile *file, char *buffer, int size,
+		      int offset)
+{
+	struct ctl_table *table = (struct ctl_table *)file;
+	loff_t ppos = offset;
+	size_t result = size;
+	int error;
+
+	error = table->proc_handler(table, 0, buffer, &result, &ppos);
+	return result;
+}
+int lib_sys_file_write(const struct SimSysFile *file, const char *buffer,
+		       int size, int offset)
+{
+	struct ctl_table *table = (struct ctl_table *)file;
+	loff_t ppos = offset;
+	size_t result = size;
+	int error;
+
+	error = table->proc_handler(table, 1, (char *)buffer, &result, &ppos);
+	return result;
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 08/11] lib: other kernel glue layer code
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (6 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 07/11] lib: sysctl " Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-29 18:17   ` Richard Weinberger
  2015-03-24 13:10 ` [RFC PATCH 09/11] lib: asm-generic files Hajime Tazaki
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage,
	Christoph Paasch

These files are used to provide the same function calls so that other
network stack code keeps untouched.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Christoph Paasch <christoph.paasch@gmail.com>
---
 arch/lib/cred.c     |  16 +++
 arch/lib/dcache.c   |  93 +++++++++++++++
 arch/lib/filemap.c  |  27 +++++
 arch/lib/fs.c       | 287 ++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/glue.c     | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/inode.c    | 146 +++++++++++++++++++++++
 arch/lib/modules.c  |  36 ++++++
 arch/lib/pid.c      |  29 +++++
 arch/lib/print.c    |  56 +++++++++
 arch/lib/proc.c     | 164 +++++++++++++++++++++++++
 arch/lib/random.c   |  53 +++++++++
 arch/lib/security.c |  45 +++++++
 arch/lib/seq.c      | 122 +++++++++++++++++++
 arch/lib/splice.c   |  20 ++++
 arch/lib/super.c    | 210 ++++++++++++++++++++++++++++++++
 arch/lib/sysfs.c    |  83 +++++++++++++
 arch/lib/vmscan.c   |  26 ++++
 17 files changed, 1749 insertions(+)
 create mode 100644 arch/lib/cred.c
 create mode 100644 arch/lib/dcache.c
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/inode.c
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/security.c
 create mode 100644 arch/lib/seq.c
 create mode 100644 arch/lib/splice.c
 create mode 100644 arch/lib/super.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/vmscan.c

diff --git a/arch/lib/cred.c b/arch/lib/cred.c
new file mode 100644
index 0000000..50e37cc5
--- /dev/null
+++ b/arch/lib/cred.c
@@ -0,0 +1,16 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/cred.h>
+void __put_cred(struct cred *cred)
+{
+}
+struct cred *prepare_creds(void)
+{
+	return 0;
+}
diff --git a/arch/lib/dcache.c b/arch/lib/dcache.c
new file mode 100644
index 0000000..a007c20
--- /dev/null
+++ b/arch/lib/dcache.c
@@ -0,0 +1,93 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <linux/fs.h>
+#include <linux/dcache.h>
+#include <linux/slab.h>
+#include "sim-assert.h"
+
+static struct kmem_cache *dentry_cache __read_mostly;
+struct kmem_cache *names_cachep __read_mostly;
+
+/**
+ * __d_alloc	-	allocate a dcache entry
+ * @sb: filesystem it will belong to
+ * @name: qstr of the name
+ *
+ * Allocates a dentry. It returns %NULL if there is insufficient memory
+ * available. On a success the dentry is returned. The name passed in is
+ * copied and the copy passed in may be reused after this call.
+ */
+struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
+{
+	struct dentry *dentry;
+	unsigned char *dname;
+
+	dentry = kmalloc(sizeof(struct dentry), GFP_KERNEL);
+	if (!dentry)
+		return NULL;
+
+	if (name->len > DNAME_INLINE_LEN - 1) {
+		dname = kmalloc(name->len + 1, GFP_KERNEL);
+		if (!dname) {
+			kmem_cache_free(dentry_cache, dentry);
+			return NULL;
+		}
+	} else
+		dname = dentry->d_iname;
+	dentry->d_name.name = dname;
+
+	dentry->d_name.len = name->len;
+	dentry->d_name.hash = name->hash;
+	memcpy(dname, name->name, name->len);
+	dname[name->len] = 0;
+
+	dentry->d_lockref.count = 1;
+	dentry->d_flags = 0;
+	spin_lock_init(&dentry->d_lock);
+	seqcount_init(&dentry->d_seq);
+	dentry->d_inode = NULL;
+	dentry->d_parent = dentry;
+	dentry->d_sb = sb;
+	dentry->d_op = NULL;
+	dentry->d_fsdata = NULL;
+	INIT_HLIST_BL_NODE(&dentry->d_hash);
+	INIT_LIST_HEAD(&dentry->d_lru);
+	INIT_LIST_HEAD(&dentry->d_subdirs);
+	INIT_HLIST_NODE(&dentry->d_u.d_alias);
+	INIT_LIST_HEAD(&dentry->d_child);
+	d_set_d_op(dentry, dentry->d_sb->s_d_op);
+
+/*	this_cpu_inc(nr_dentry); */
+
+	return dentry;
+}
+
+void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
+{
+	WARN_ON_ONCE(dentry->d_op);
+	WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH  |
+					DCACHE_OP_COMPARE       |
+					DCACHE_OP_REVALIDATE    |
+					DCACHE_OP_DELETE));
+	dentry->d_op = op;
+	if (!op)
+		return;
+	if (op->d_hash)
+		dentry->d_flags |= DCACHE_OP_HASH;
+	if (op->d_compare)
+		dentry->d_flags |= DCACHE_OP_COMPARE;
+	if (op->d_revalidate)
+		dentry->d_flags |= DCACHE_OP_REVALIDATE;
+	if (op->d_delete)
+		dentry->d_flags |= DCACHE_OP_DELETE;
+	if (op->d_prune)
+		dentry->d_flags |= DCACHE_OP_PRUNE;
+
+}
diff --git a/arch/lib/filemap.c b/arch/lib/filemap.c
new file mode 100644
index 0000000..9a9837c
--- /dev/null
+++ b/arch/lib/filemap.c
@@ -0,0 +1,27 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/fs.h>
+
+
+ssize_t generic_file_aio_read(struct kiocb *a, const struct iovec *b,
+			      unsigned long c, loff_t d)
+{
+	lib_assert(false);
+
+	return 0;
+}
+
+int generic_file_readonly_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return -ENOSYS;
+}
+
diff --git a/arch/lib/fs.c b/arch/lib/fs.c
new file mode 100644
index 0000000..766a9a8
--- /dev/null
+++ b/arch/lib/fs.c
@@ -0,0 +1,287 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <linux/fs.h>
+#include <linux/splice.h>
+#include <linux/mount.h>
+#include <linux/sysctl.h>
+#include <fs/mount.h>
+#include <linux/slab.h>
+#include <linux/backing-dev.h>
+#include <linux/pagemap.h>
+#include <linux/user_namespace.h>
+#include <linux/lglock.h>
+
+#include "sim-assert.h"
+
+__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
+struct super_block;
+
+struct user_namespace init_user_ns;
+
+int get_sb_pseudo(struct file_system_type *type, char *str,
+		  const struct super_operations *ops, unsigned long z,
+		  struct vfsmount *mnt)
+{
+	/* called from sockfs_get_sb by kern_mount_data */
+	mnt->mnt_sb->s_root = 0;
+	mnt->mnt_sb->s_op = ops;
+	return 0;
+}
+struct inode *new_inode(struct super_block *sb)
+{
+	/* call sock_alloc_inode through s_op */
+	struct inode *inode = sb->s_op->alloc_inode(sb);
+
+	inode->i_ino = 0;
+	inode->i_sb = sb;
+	atomic_set(&inode->i_count, 1);
+	inode->i_state = 0;
+	return inode;
+}
+void iput(struct inode *inode)
+{
+	if (atomic_dec_and_test(&inode->i_count))
+		/* call sock_destroy_inode */
+		inode->i_sb->s_op->destroy_inode(inode);
+}
+void inode_init_once(struct inode *inode)
+{
+	memset(inode, 0, sizeof(*inode));
+}
+
+/* Implementation taken from vfs_kern_mount from linux/namespace.c */
+struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
+{
+	static struct mount local_mnt;
+	struct mount *mnt = &local_mnt;
+	struct dentry *root = 0;
+
+	memset(mnt, 0, sizeof(struct mount));
+	if (!type)
+		return ERR_PTR(-ENODEV);
+	int flags = MS_KERNMOUNT;
+	char *name = (char *)type->name;
+
+	if (flags & MS_KERNMOUNT)
+		mnt->mnt.mnt_flags = MNT_INTERNAL;
+
+	root = type->mount(type, flags, name, data);
+	if (IS_ERR(root))
+		return ERR_CAST(root);
+
+	mnt->mnt.mnt_root = root;
+	mnt->mnt.mnt_sb = root->d_sb;
+	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+	mnt->mnt_parent = mnt;
+	/* DCE is monothreaded , so we do not care of lock here */
+	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
+
+	return &mnt->mnt;
+}
+
+int register_filesystem(struct file_system_type *fs)
+{
+	/* We don't need to register anything because we never
+	   really implement. any kind of filesystem.
+	   return 0 to signal success. */
+	return 0;
+}
+
+int alloc_fd(unsigned start, unsigned flags)
+{
+	lib_assert(false);
+	return 0;
+}
+void fd_install(unsigned int fd, struct file *file)
+{
+	lib_assert(false);
+}
+void put_unused_fd(unsigned int fd)
+{
+	lib_assert(false);
+}
+
+struct file *alloc_file(struct path *path, fmode_t mode,
+			const struct file_operations *fop)
+{
+	lib_assert(false);
+	return 0;
+}
+
+struct file *fget(unsigned int fd)
+{
+	lib_assert(false);
+	return 0;
+}
+struct file *fget_light(unsigned int fd, int *fput_needed)
+{
+	lib_assert(false);
+	return 0;
+}
+void fput(struct file *file)
+{
+}
+
+struct dentry *d_alloc(struct dentry *entry, const struct qstr *str)
+{
+	lib_assert(false);
+	return 0;
+}
+void d_instantiate(struct dentry *entry, struct inode *inode)
+{
+}
+char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
+		    const char *fmt, ...)
+{
+	lib_assert(false);
+	return 0;
+}
+
+struct dentry_stat_t dentry_stat;
+struct files_stat_struct files_stat;
+struct inodes_stat_t inodes_stat;
+
+pid_t f_getown(struct file *filp)
+{
+	lib_assert(false);
+	return 0;
+}
+
+void f_setown(struct file *filp, unsigned long arg, int force)
+{
+	lib_assert(false);
+}
+
+void kill_fasync(struct fasync_struct **fs, int a, int b)
+{
+	lib_assert(false);
+}
+int fasync_helper(int a, struct file *file, int b, struct fasync_struct **c)
+{
+	lib_assert(false);
+	return 0;
+}
+long sys_close(unsigned int fd)
+{
+	lib_assert(false);
+	return 0;
+}
+ssize_t splice_to_pipe(struct pipe_inode_info *info,
+		       struct splice_pipe_desc *desc)
+{
+	lib_assert(false);
+	return 0;
+}
+int splice_grow_spd(const struct pipe_inode_info *info,
+		    struct splice_pipe_desc *desc)
+{
+	lib_assert(false);
+	return 0;
+}
+void splice_shrink_spd(struct splice_pipe_desc *desc)
+{
+	lib_assert(false);
+}
+
+ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
+				struct file *out, loff_t *poff, size_t len,
+				unsigned int flags)
+{
+	lib_assert(false);
+	return 0;
+}
+void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
+			   struct pipe_buffer *buf, int atomic)
+{
+	lib_assert(false);
+	return 0;
+}
+
+void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
+			    struct pipe_buffer *buf, void *address)
+{
+	lib_assert(false);
+}
+
+int generic_pipe_buf_confirm(struct pipe_inode_info *pipe,
+			     struct pipe_buffer *buf)
+{
+	lib_assert(false);
+	return 0;
+}
+
+void generic_pipe_buf_release(struct pipe_inode_info *pipe,
+			      struct pipe_buffer *buf)
+{
+	lib_assert(false);
+}
+
+static int generic_pipe_buf_nosteal(struct pipe_inode_info *pipe,
+				    struct pipe_buffer *buf)
+{
+	return 1;
+}
+
+void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
+{
+	lib_assert(false);
+}
+int proc_nr_inodes(struct ctl_table *table, int write, void __user *buffer,
+		   size_t *lenp, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
+		   size_t *lenp, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+/*
+ * Handle writeback of dirty data for the device backed by this bdi. Also
+ * wakes up periodically and does kupdated style flushing.
+ */
+int bdi_writeback_thread(void *data)
+{
+	lib_assert(false);
+
+	return 0;
+}
+
+void get_filesystem(struct file_system_type *fs)
+{
+}
+/* #include <fs/proc/proc_sysctl.c> */
+unsigned int nr_free_buffer_pages(void)
+{
+	return 1024;
+}
+
+const struct pipe_buf_operations nosteal_pipe_buf_ops = {
+	.can_merge	= 0,
+	.confirm	= generic_pipe_buf_confirm,
+	.release	= generic_pipe_buf_release,
+	.steal		= generic_pipe_buf_nosteal,
+	.get		= generic_pipe_buf_get,
+};
+
+ssize_t
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+	return 0;
+}
+
+unsigned long get_max_files(void)
+{
+	return NR_FILE;
+}
diff --git a/arch/lib/glue.c b/arch/lib/glue.c
new file mode 100644
index 0000000..9208739
--- /dev/null
+++ b/arch/lib/glue.c
@@ -0,0 +1,336 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <linux/types.h>        /* loff_t */
+#include <linux/errno.h>        /* ESPIPE */
+#include <linux/pagemap.h>      /* PAGE_CACHE_SIZE */
+#include <linux/limits.h>       /* NAME_MAX */
+#include <linux/statfs.h>       /* struct kstatfs */
+#include <linux/bootmem.h>      /* HASHDIST_DEFAULT */
+#include <linux/utsname.h>
+#include <linux/binfmts.h>
+#include <linux/init_task.h>
+#include <linux/sched/rt.h>
+#include <stdarg.h>
+#include "sim-assert.h"
+#include "sim.h"
+#include "lib.h"
+
+
+struct pipe_buffer;
+struct file;
+struct pipe_inode_info;
+struct wait_queue_t;
+struct kernel_param;
+struct super_block;
+struct tvec_base {};
+
+/* defined in fs/exec.c */
+char core_pattern[CORENAME_MAX_SIZE] = "core";
+/* defined in sched.c, used in net/sched/em_meta.c */
+unsigned long avenrun[3];
+/* defined in mm/page_alloc.c, used in net/xfrm/xfrm_hash.c */
+int hashdist = HASHDIST_DEFAULT;
+/* defined in mm/page_alloc.c */
+struct pglist_data __refdata contig_page_data;
+/* defined in linux/mmzone.h mm/memory.c */
+struct page *mem_map = 0;
+/* used during boot. */
+struct tvec_base boot_tvec_bases;
+/* used by sysinfo in kernel/timer.c */
+int nr_threads = 0;
+/* not very useful in mm/vmstat.c */
+atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+
+/* XXX: used in network stack ! */
+unsigned long num_physpages = 0;
+unsigned long totalram_pages = 0;
+
+/* XXX figure out initial value */
+unsigned int interrupt_pending = 0;
+static unsigned long g_irqflags = 0;
+static unsigned long local_irqflags = 0;
+int overflowgid = 0;
+int overflowuid = 0;
+int fs_overflowgid = 0;
+int fs_overflowuid = 0;
+unsigned long sysctl_overcommit_kbytes __read_mostly;
+DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+
+/* from kobject_uevent.c */
+char uevent_helper[UEVENT_HELPER_PATH_LEN] = "dummy-uevent";
+/* from ksysfs.c */
+int rcu_expedited;
+/* from rt.c */
+int sched_rr_timeslice = RR_TIMESLICE;
+/* from main.c */
+bool initcall_debug;
+bool static_key_initialized __read_mostly = false;
+unsigned long __start_rodata, __end_rodata;
+
+unsigned long __raw_local_save_flags(void)
+{
+	return g_irqflags;
+}
+unsigned long arch_local_save_flags(void)
+{
+	return local_irqflags;
+}
+void arch_local_irq_restore(unsigned long flags)
+{
+	local_irqflags = flags;
+}
+
+int in_egroup_p(kgid_t grp)
+{
+	/* called from sysctl code. */
+	lib_assert(false);
+	return 0;
+}
+
+void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
+{
+}
+
+unsigned long long nr_context_switches(void)
+{
+	/* we just need to return >0 to avoid the warning
+	   in kernel/rcupdate.c */
+	return 1;
+}
+
+
+long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+		    unsigned long start, unsigned long nr_pages,
+		    int write, int force, struct page **pages,
+		    struct vm_area_struct **vmas)
+{
+	/* in practice, this function is never called. It's linked in because */
+	/* we link in get_user_pages_fast which is included only because it */
+	/* is located in mm/util.c */
+	lib_assert(false);
+	return 0;
+}
+
+
+unsigned long wrong_size_cmpxchg(volatile void *ptr)
+{
+	lib_assert(false);
+}
+
+void dump_stack(void)
+{
+	/* we assert to make sure that we catch whoever calls dump_stack */
+	lib_assert(false);
+}
+
+
+void lib_printf(const char *str, ...)
+{
+	va_list args;
+
+	va_start(args, str);
+	lib_vprintf(str, args);
+	va_end(args);
+}
+
+void atomic64_inc(atomic64_t *v)
+{
+	v->counter++;
+}
+
+#include <linux/vmalloc.h>
+#include <linux/kmemleak.h>
+
+static unsigned long __meminitdata nr_kernel_pages;
+static unsigned long __meminitdata nr_all_pages;
+/*
+ * allocate a large system hash table from bootmem
+ * - it is assumed that the hash table must contain an exact power-of-2
+ *   quantity of entries
+ * - limit is the number of hash buckets, not the total allocation size
+ */
+void *__init alloc_large_system_hash(const char *tablename,
+				     unsigned long bucketsize,
+				     unsigned long numentries,
+				     int scale,
+				     int flags,
+				     unsigned int *_hash_shift,
+				     unsigned int *_hash_mask,
+				     unsigned long low_limit,
+				     unsigned long high_limit)
+{
+	unsigned long long max = high_limit;
+	unsigned long log2qty, size;
+	void *table = NULL;
+
+	/* allow the kernel cmdline to have a say */
+	if (!numentries) {
+		/* round applicable memory size up to nearest megabyte */
+		numentries = nr_kernel_pages;
+		numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
+		numentries >>= 20 - PAGE_SHIFT;
+		numentries <<= 20 - PAGE_SHIFT;
+
+		/* limit to 1 bucket per 2^scale bytes of low memory */
+		if (scale > PAGE_SHIFT)
+			numentries >>= (scale - PAGE_SHIFT);
+		else
+			numentries <<= (PAGE_SHIFT - scale);
+
+		/* Make sure we've got at least a 0-order allocation.. */
+		if (unlikely(flags & HASH_SMALL)) {
+			/* Makes no sense without HASH_EARLY */
+			WARN_ON(!(flags & HASH_EARLY));
+			if (!(numentries >> *_hash_shift)) {
+				numentries = 1UL << *_hash_shift;
+				BUG_ON(!numentries);
+			}
+		} else if (unlikely((numentries * bucketsize) < PAGE_SIZE))
+			numentries = PAGE_SIZE / bucketsize;
+	}
+	numentries = roundup_pow_of_two(numentries);
+
+	/* limit allocation size to 1/16 total memory by default */
+	if (max == 0) {
+		max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
+		do_div(max, bucketsize);
+	}
+
+	if (numentries > max)
+		numentries = max;
+
+	log2qty = ilog2(numentries);
+
+	do {
+		size = bucketsize << log2qty;
+		if (flags & HASH_EARLY)
+			table = alloc_bootmem_nopanic(size);
+		else if (hashdist)
+			table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
+		else {
+			/*
+			 * If bucketsize is not a power-of-two, we may free
+			 * some pages at the end of hash table which
+			 * alloc_pages_exact() automatically does
+			 */
+			if (get_order(size) < MAX_ORDER) {
+				table = alloc_pages_exact(size, GFP_ATOMIC);
+				kmemleak_alloc(table, size, 1, GFP_ATOMIC);
+			}
+		}
+	} while (!table && size > PAGE_SIZE && --log2qty);
+
+	if (!table)
+		panic("Failed to allocate %s hash table\n", tablename);
+
+	pr_info("%s hash table entries: %d (order: %d, %lu bytes)\n",
+	       tablename,
+	       (1U << log2qty),
+	       ilog2(size) - PAGE_SHIFT,
+	       size);
+
+	if (_hash_shift)
+		*_hash_shift = log2qty;
+	if (_hash_mask)
+		*_hash_mask = (1 << log2qty) - 1;
+
+	return table;
+}
+
+int vm_insert_page(struct vm_area_struct *area, unsigned long addr,
+		   struct page *page)
+{
+	/* this function is called from af_packet.c to support mmap on packet
+	   sockets since we will never call mmap on them, this function
+	   should never be called. */
+	lib_assert(false);
+	return 0; /* quiet compiler */
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+	/* This function is called from the ip layer to get information about
+	   the amount of memory in the system and make some educated guesses
+	   about some default buffer sizes. We pick a value which ensures
+	   small buffers. */
+	val->totalram = 0;
+}
+int slab_is_available(void)
+{
+	/* called from kernel/param.c. */
+	return 1;
+}
+
+/* used from kern_ptr_validate from mm/util.c which is never called */
+void *high_memory = 0;
+
+
+
+char *get_options(const char *str, int nints, int *ints)
+{
+	/* called from net/core/dev.c */
+	/* we return 0 to indicate no options. */
+	return 0;
+}
+void __xchg_called_with_bad_pointer(void)
+{
+	/* never called theoretically. */
+	lib_assert(false);
+}
+
+void async_synchronize_full(void)
+{
+	/* called from drivers/base/ *.c */
+	/* there is nothing to do, really. */
+}
+int send_sigurg(struct fown_struct *fown)
+{
+	lib_assert(false);
+	return 0;
+}
+int send_sig(int signal, struct task_struct *task, int x)
+{
+	struct SimTask *lib_task = container_of(task, struct SimTask,
+						kernel_task);
+
+	lib_signal_raised((struct SimTask *)lib_task, signal);
+	/* lib_assert (false); */
+	return 0;
+}
+unsigned long get_taint(void)
+{
+	/* never tainted. */
+	return 0;
+}
+void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
+{
+}
+struct pid *cad_pid = 0;
+
+void add_device_randomness(const void *buf, unsigned int size)
+{
+}
+
+int kobject_uevent(struct kobject *kobj, enum kobject_action action)
+{
+	return 0;
+}
+
+int sched_rr_handler(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos)
+{
+	return 0;
+}
+
+void on_each_cpu_mask(const struct cpumask *mask,
+		      smp_call_func_t func, void *info, bool wait)
+{
+}
diff --git a/arch/lib/inode.c b/arch/lib/inode.c
new file mode 100644
index 0000000..ab3d2ec
--- /dev/null
+++ b/arch/lib/inode.c
@@ -0,0 +1,146 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/dcache.h>
+#include <linux/security.h>
+#include <linux/pagemap.h>
+#include <linux/backing-dev.h>
+
+
+static struct kmem_cache *inode_cachep __read_mostly;
+/*
+ * Empty aops. Can be used for the cases where the user does not
+ * define any of the address_space operations.
+ */
+const struct address_space_operations empty_aops = {
+};
+
+unsigned int get_next_ino(void)
+{
+	static unsigned int res = 0;
+
+	return ++res;
+}
+
+/**
+ * inode_init_always - perform inode structure intialisation
+ * @sb: superblock inode belongs to
+ * @inode: inode to initialise
+ *
+ * These are initializations that need to be done on every inode
+ * allocation as the fields are not initialised by slab allocation.
+ */
+int inode_init_always(struct super_block *sb, struct inode *inode)
+{
+	static const struct inode_operations empty_iops;
+	static const struct file_operations empty_fops;
+	struct address_space *const mapping = &inode->i_data;
+
+	inode->i_sb = sb;
+	inode->i_blkbits = sb->s_blocksize_bits;
+	inode->i_flags = 0;
+	atomic_set(&inode->i_count, 1);
+	inode->i_op = &empty_iops;
+	inode->__i_nlink = 1;
+	inode->i_opflags = 0;
+	i_uid_write(inode, 0);
+	i_gid_write(inode, 0);
+	atomic_set(&inode->i_writecount, 0);
+	inode->i_size = 0;
+	inode->i_blocks = 0;
+	inode->i_bytes = 0;
+	inode->i_generation = 0;
+	inode->i_pipe = NULL;
+	inode->i_bdev = NULL;
+	inode->i_cdev = NULL;
+	inode->i_rdev = 0;
+	inode->dirtied_when = 0;
+
+	if (security_inode_alloc(inode))
+		goto out;
+	spin_lock_init(&inode->i_lock);
+	lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
+
+	mutex_init(&inode->i_mutex);
+	lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key);
+
+	atomic_set(&inode->i_dio_count, 0);
+
+	mapping->a_ops = &empty_aops;
+	mapping->host = inode;
+	mapping->flags = 0;
+	atomic_set(&mapping->i_mmap_writable, 0);
+	mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE);
+	mapping->private_data = NULL;
+	mapping->writeback_index = 0;
+	inode->i_private = NULL;
+	inode->i_mapping = mapping;
+	INIT_HLIST_HEAD(&inode->i_dentry);	/* buggered by rcu freeing */
+#ifdef CONFIG_FS_POSIX_ACL
+	inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED;
+#endif
+
+#ifdef CONFIG_FSNOTIFY
+	inode->i_fsnotify_mask = 0;
+#endif
+	/* this_cpu_inc(nr_inodes); */
+
+	return 0;
+out:
+	return -ENOMEM;
+}
+
+
+static struct inode *alloc_inode(struct super_block *sb)
+{
+	struct inode *inode;
+
+	if (sb->s_op->alloc_inode)
+		inode = sb->s_op->alloc_inode(sb);
+	else
+		inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL);
+
+	if (!inode)
+		return NULL;
+
+	if (unlikely(inode_init_always(sb, inode))) {
+		if (inode->i_sb->s_op->destroy_inode)
+			inode->i_sb->s_op->destroy_inode(inode);
+		else
+			kmem_cache_free(inode_cachep, inode);
+		return NULL;
+	}
+
+	return inode;
+}
+
+/**
+ *	new_inode_pseudo        - obtain an inode
+ *	@sb: superblock
+ *
+ *	Allocates a new inode for given superblock.
+ *	Inode wont be chained in superblock s_inodes list
+ *	This means :
+ *	- fs can't be unmount
+ *	- quotas, fsnotify, writeback can't work
+ */
+struct inode *new_inode_pseudo(struct super_block *sb)
+{
+	struct inode *inode = alloc_inode(sb);
+
+	if (inode) {
+		spin_lock(&inode->i_lock);
+		inode->i_state = 0;
+		spin_unlock(&inode->i_lock);
+		INIT_LIST_HEAD(&inode->i_sb_list);
+	}
+	return inode;
+}
diff --git a/arch/lib/modules.c b/arch/lib/modules.c
new file mode 100644
index 0000000..ca43fdc
--- /dev/null
+++ b/arch/lib/modules.c
@@ -0,0 +1,36 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-assert.h"
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+
+int modules_disabled = 0;
+char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
+
+static struct module_version_attribute g_empty_attr_buffer;
+/* we make the array empty by default because, really, we don't need */
+/* to look at the builtin params */
+const struct kernel_param __start___param[] = {{0}} ;
+const struct kernel_param __stop___param[] = {{0}} ;
+const struct module_version_attribute *__start___modver[] = {
+	&g_empty_attr_buffer};
+const struct module_version_attribute *__stop___modver[] = {
+	&g_empty_attr_buffer};
+
+struct module_attribute module_uevent;
+struct ctl_table usermodehelper_table[] = {};
+
+int __request_module(bool wait, const char *fmt, ...)
+{
+	/* we really should never be trying to load modules that way. */
+	/*  lib_assert (false); */
+	return 0;
+}
diff --git a/arch/lib/pid.c b/arch/lib/pid.c
new file mode 100644
index 0000000..00cf7b6
--- /dev/null
+++ b/arch/lib/pid.c
@@ -0,0 +1,29 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/pid.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+void put_pid(struct pid *pid)
+{
+}
+pid_t pid_vnr(struct pid *pid)
+{
+	return pid_nr(pid);
+}
+struct task_struct *find_task_by_vpid(pid_t nr)
+{
+	lib_assert(false);
+	return 0;
+}
+struct pid *find_get_pid(int nr)
+{
+	lib_assert(false);
+	return 0;
+}
diff --git a/arch/lib/print.c b/arch/lib/print.c
new file mode 100644
index 0000000..09b1bb5
--- /dev/null
+++ b/arch/lib/print.c
@@ -0,0 +1,56 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <stdarg.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+int dmesg_restrict = 1;
+
+/* from lib/vsprintf.c */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
+int printk(const char *fmt, ...)
+{
+	va_list args;
+	static char buf[256];
+	int value;
+
+	va_start(args, fmt);
+	value = vsnprintf(buf, 256, printk_skip_level(fmt), args);
+	lib_printf("<%c>%s", printk_get_level(fmt), buf);
+	va_end(args);
+	return value;
+}
+void panic(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	lib_vprintf(fmt, args);
+	va_end(args);
+	lib_assert(false);
+}
+
+void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
+{
+	va_list args;
+
+	printk("%s:%d -- ", file, line);
+	va_start(args, fmt);
+	lib_vprintf(fmt, args);
+	va_end(args);
+}
+
+void warn_slowpath_null(const char *file, int line)
+{
+	printk("%s:%d -- ", file, line);
+}
+
diff --git a/arch/lib/proc.c b/arch/lib/proc.c
new file mode 100644
index 0000000..0a65d7b
--- /dev/null
+++ b/arch/lib/proc.c
@@ -0,0 +1,164 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2014 Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/fs.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <net/net_namespace.h>
+#include "sim-types.h"
+#include "sim-assert.h"
+#include "fs/proc/internal.h"           /* XXX */
+
+struct proc_dir_entry;
+static char proc_root_data[sizeof(struct proc_dir_entry) + 4];
+
+static struct proc_dir_entry *proc_root_sim  =
+	(struct proc_dir_entry *)proc_root_data;
+
+void lib_proc_net_initialize(void)
+{
+	proc_root_sim->parent = proc_root_sim;
+	strcpy(proc_root_sim->name, "net");
+	proc_root_sim->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+	proc_root_sim->subdir = RB_ROOT;
+	init_net.proc_net = proc_root_sim;
+	init_net.proc_net_stat = proc_mkdir("stat", proc_root_sim);
+}
+struct proc_dir_entry *
+proc_net_fops_create(struct net *net,
+		     const char *name,
+		     umode_t mode, const struct file_operations *fops)
+{
+	return proc_create_data(name, mode, net->proc_net, fops, 0);
+}
+
+static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
+					  const char *name,
+					  umode_t mode,
+					  nlink_t nlink)
+{
+	struct proc_dir_entry *ent = NULL;
+	const char *fn = name;
+	struct qstr qstr;
+
+	qstr.name = fn;
+	qstr.len = strlen(fn);
+	if (qstr.len == 0 || qstr.len >= 256) {
+		WARN(1, "name len %u\n", qstr.len);
+		return NULL;
+	}
+
+	ent = kzalloc(sizeof(struct proc_dir_entry) + qstr.len + 1, GFP_KERNEL);
+	if (!ent)
+		goto out;
+
+	memcpy(ent->name, fn, qstr.len + 1);
+	ent->namelen = qstr.len;
+	ent->mode = mode;
+	ent->nlink = nlink;
+	ent->subdir = RB_ROOT;
+	atomic_set(&ent->count, 1);
+	spin_lock_init(&ent->pde_unload_lock);
+	INIT_LIST_HEAD(&ent->pde_openers);
+out:
+	return ent;
+}
+struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
+					struct proc_dir_entry *parent,
+					const struct file_operations *proc_fops,
+					void *data)
+{
+	struct proc_dir_entry *de;
+
+	de = __proc_create(&parent, name, S_IFDIR | mode, 2);
+	de->proc_fops = proc_fops;
+	de->data = data;
+	return de;
+}
+static int proc_match(unsigned int len, const char *name,
+		      struct proc_dir_entry *de)
+{
+	if (len < de->namelen)
+		return -1;
+	if (len > de->namelen)
+		return 1;
+
+	return memcmp(name, de->name, len);
+}
+static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
+					      const char *name,
+					      unsigned int len)
+{
+	struct rb_node *node = dir->subdir.rb_node;
+
+	while (node) {
+		struct proc_dir_entry *de = container_of(node,
+							 struct proc_dir_entry,
+							 subdir_node);
+		int result = proc_match(len, name, de);
+
+		if (result < 0)
+			node = node->rb_left;
+		else if (result > 0)
+			node = node->rb_right;
+		else
+			return de;
+	}
+	return NULL;
+}
+
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry *de, **prev;
+
+	de = pde_subdir_find(parent, name, strlen(name));
+	if (de) {
+		rb_erase(&de->subdir_node, &parent->subdir);
+		kfree(de->name);
+		kfree(de);
+	}
+}
+void proc_net_remove(struct net *net, const char *name)
+{
+	remove_proc_entry(name, net->proc_net);
+}
+void proc_remove(struct proc_dir_entry *de)
+{
+	/* XXX */
+}
+int proc_nr_files(struct ctl_table *table, int write,
+		  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return -ENOSYS;
+}
+
+struct proc_dir_entry *proc_mkdir(const char *name,
+				  struct proc_dir_entry *parent)
+{
+	return __proc_create(&parent, name, S_IFDIR | S_IRUGO, 2);
+}
+
+struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
+				       struct proc_dir_entry *parent,
+				       void *data)
+{
+	struct proc_dir_entry *de;
+
+	de = __proc_create(&parent, name,
+			S_IFDIR | S_IRUGO | S_IXUGO | mode, 2);
+	de->data = data;
+	return de;
+}
+
+int proc_alloc_inum(unsigned int *inum)
+{
+	*inum = 1;
+	return 0;
+}
diff --git a/arch/lib/random.c b/arch/lib/random.c
new file mode 100644
index 0000000..9fbb8bf
--- /dev/null
+++ b/arch/lib/random.c
@@ -0,0 +1,53 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include <linux/random.h>
+
+u32 random32(void)
+{
+	return lib_random();
+}
+
+void get_random_bytes(void *buf, int nbytes)
+{
+	char *p = (char *)buf;
+	int i;
+
+	for (i = 0; i < nbytes; i++)
+		p[i] = lib_random();
+}
+void srandom32(u32 entropy)
+{
+}
+
+u32 prandom_u32(void)
+{
+	return lib_random();
+}
+void prandom_seed(u32 entropy)
+{
+}
+
+void prandom_bytes(void *buf, size_t bytes)
+{
+	return get_random_bytes(buf, bytes);
+}
+
+#include <linux/sysctl.h>
+
+static int nothing;
+struct ctl_table random_table[] = {
+	{
+		.procname       = "nothing",
+		.data           = &nothing,
+		.maxlen         = sizeof(int),
+		.mode           = 0444,
+		.proc_handler   = proc_dointvec,
+	}
+};
diff --git a/arch/lib/security.c b/arch/lib/security.c
new file mode 100644
index 0000000..0367189
--- /dev/null
+++ b/arch/lib/security.c
@@ -0,0 +1,45 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "linux/capability.h"
+
+struct sock;
+struct sk_buff;
+
+bool capable(int cap)
+{
+	switch (cap) {
+	case CAP_NET_RAW:
+	case CAP_NET_BIND_SERVICE:
+	case CAP_NET_ADMIN:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int cap_netlink_recv(struct sk_buff *skb, int cap)
+{
+	return 0;
+}
+
+int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	return 0;
+}
+bool ns_capable(struct user_namespace *ns, int cap)
+{
+	return true;
+}
+bool file_ns_capable(const struct file *file, struct user_namespace *ns,
+		     int cap)
+{
+	return true;
+}
diff --git a/arch/lib/seq.c b/arch/lib/seq.c
new file mode 100644
index 0000000..72c2f5d
--- /dev/null
+++ b/arch/lib/seq.c
@@ -0,0 +1,122 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/seq_file.h>
+
+struct hlist_node *seq_hlist_next_rcu(void *v,
+				      struct hlist_head *head,
+				      loff_t *ppos)
+{
+	return 0;
+}
+struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head,
+					    loff_t pos)
+{
+	return 0;
+}
+struct list_head *seq_list_start(struct list_head *head,
+				 loff_t pos)
+{
+	return 0;
+}
+struct list_head *seq_list_start_head(struct list_head *head,
+				      loff_t pos)
+{
+	return 0;
+}
+
+struct list_head *seq_list_next(void *v, struct list_head *head,
+				loff_t *ppos)
+{
+	return 0;
+}
+
+void *__seq_open_private(struct file *file, const struct seq_operations *ops,
+			 int psize)
+{
+	return 0;
+}
+
+int seq_open_private(struct file *file, const struct seq_operations *ops,
+		     int psize)
+{
+	return 0;
+}
+
+int seq_release_private(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+loff_t seq_lseek(struct file *file, loff_t offset, int origin)
+{
+	return 0;
+}
+int seq_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+int seq_putc(struct seq_file *m, char c)
+{
+	return 0;
+}
+int seq_puts(struct seq_file *m, const char *s)
+{
+	return 0;
+}
+ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+	return 0;
+}
+int seq_open(struct file *file, const struct seq_operations *ops)
+{
+	return 0;
+}
+int seq_printf(struct seq_file *seq, const char *fmt, ...)
+{
+	return 0;
+}
+
+int seq_write(struct seq_file *seq, const void *data, size_t len)
+{
+	return 0;
+}
+
+int seq_open_net(struct inode *inode, struct file *file,
+		 const struct seq_operations *ops, int size)
+{
+	return 0;
+}
+
+int seq_release_net(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+
+int single_open(struct file *file, int (*cb)(struct seq_file *,
+					     void *), void *data)
+{
+	return 0;
+}
+
+int single_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+int single_open_net(struct inode *inode, struct file *file,
+		    int (*show)(struct seq_file *, void *))
+{
+	return 0;
+}
+
+int single_release_net(struct inode *inode, struct file *file)
+{
+	return 0;
+}
diff --git a/arch/lib/splice.c b/arch/lib/splice.c
new file mode 100644
index 0000000..9ecd9e5
--- /dev/null
+++ b/arch/lib/splice.c
@@ -0,0 +1,20 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/fs.h>
+
+ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
+				 struct pipe_inode_info *pipe, size_t len,
+				 unsigned int flags)
+{
+	lib_assert(false);
+
+	return 0;
+}
diff --git a/arch/lib/super.c b/arch/lib/super.c
new file mode 100644
index 0000000..45a653f
--- /dev/null
+++ b/arch/lib/super.c
@@ -0,0 +1,210 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/acct.h>
+#include <linux/blkdev.h>
+#include <linux/mount.h>
+#include <linux/security.h>
+#include <linux/writeback.h>            /* for the emergency remount stuff */
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/backing-dev.h>
+#include <linux/rculist_bl.h>
+#include <linux/cleancache.h>
+#include <linux/fsnotify.h>
+#include <linux/fs.h>
+#include <sim-assert.h>
+
+
+void put_super(struct super_block *sb)
+{
+}
+
+int grab_super(struct super_block *s)
+{
+	return 0;
+}
+void destroy_super(struct super_block *s)
+{
+}
+
+int set_anon_super(struct super_block *s, void *data)
+{
+	return 0;
+}
+
+struct super_block;
+LIST_HEAD(super_blocks);
+
+/**
+ *	alloc_super	-	create new superblock
+ *	@type:	filesystem type superblock should belong to
+ *
+ *	Allocates and initializes a new &struct super_block.  alloc_super()
+ *	returns a pointer new superblock or %NULL if allocation had failed.
+ */
+static struct super_block *alloc_super(struct file_system_type *type)
+{
+	struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);
+	static const struct super_operations default_op;
+
+	if (s) {
+		if (security_sb_alloc(s)) {
+			kfree(s);
+			s = NULL;
+			goto fail;
+		}
+		INIT_HLIST_NODE(&s->s_instances);
+		INIT_HLIST_BL_HEAD(&s->s_anon);
+		INIT_LIST_HEAD(&s->s_inodes);
+		if (list_lru_init(&s->s_dentry_lru))
+			goto fail;
+		if (list_lru_init(&s->s_inode_lru))
+			goto fail;
+		INIT_LIST_HEAD(&s->s_mounts);
+		init_rwsem(&s->s_umount);
+		/*
+		 * sget() can have s_umount recursion.
+		 *
+		 * When it cannot find a suitable sb, it allocates a new
+		 * one (this one), and tries again to find a suitable old
+		 * one.
+		 *
+		 * In case that succeeds, it will acquire the s_umount
+		 * lock of the old one. Since these are clearly distrinct
+		 * locks, and this object isn't exposed yet, there's no
+		 * risk of deadlocks.
+		 *
+		 * Annotate this by putting this lock in a different
+		 * subclass.
+		 */
+		down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
+		s->s_count = 1;
+		atomic_set(&s->s_active, 1);
+		mutex_init(&s->s_vfs_rename_mutex);
+		lockdep_set_class(&s->s_vfs_rename_mutex,
+				  &type->s_vfs_rename_key);
+		mutex_init(&s->s_dquot.dqio_mutex);
+		mutex_init(&s->s_dquot.dqonoff_mutex);
+		s->s_maxbytes = MAX_NON_LFS;
+		s->s_op = &default_op;
+		s->s_time_gran = 1000000000;
+		s->cleancache_poolid = -1;
+
+		s->s_shrink.seeks = DEFAULT_SEEKS;
+		s->s_shrink.batch = 1024;
+		return s;
+	}
+fail:
+	destroy_super(s);
+	return NULL;
+}
+
+/**
+ *	deactivate_locked_super	-	drop an active reference to superblock
+ *	@s: superblock to deactivate
+ *
+ *	Drops an active reference to superblock, converting it into a temprory
+ *	one if there is no other active references left.  In that case we
+ *	tell fs driver to shut it down and drop the temporary reference we
+ *	had just acquired.
+ *
+ *	Caller holds exclusive lock on superblock; that lock is released.
+ */
+void deactivate_locked_super(struct super_block *s)
+{
+	struct file_system_type *fs = s->s_type;
+
+	if (atomic_dec_and_test(&s->s_active)) {
+		cleancache_invalidate_fs(s);
+		fs->kill_sb(s);
+
+		/* caches are now gone, we can safely kill the shrinker now */
+		unregister_shrinker(&s->s_shrink);
+
+		/*
+		 * We need to call rcu_barrier so all the delayed rcu free
+		 * inodes are flushed before we release the fs module.
+		 */
+		rcu_barrier();
+		put_filesystem(fs);
+		put_super(s);
+	} else
+		up_write(&s->s_umount);
+}
+
+/* from fs/super.c */
+DEFINE_SPINLOCK(sb_lock);
+/**
+ *	sget	-	find or create a superblock
+ *	@type:	filesystem type superblock should belong to
+ *	@test:	comparison callback
+ *	@set:	setup callback
+ *	@data:	argument to each of them
+ */
+struct super_block *sget(struct file_system_type *type,
+			 int (*test)(struct super_block *, void *),
+			 int (*set)(struct super_block *, void *),
+			 int flags, void *data)
+{
+	struct super_block *s = NULL;
+	struct super_block *old;
+	int err;
+
+retry:
+	spin_lock(&sb_lock);
+	if (test) {
+		hlist_for_each_entry(old, &type->fs_supers, s_instances) {
+			if (!test(old, data))
+				continue;
+			if (!grab_super(old))
+				goto retry;
+			if (s) {
+				up_write(&s->s_umount);
+				destroy_super(s);
+				s = NULL;
+			}
+			down_write(&old->s_umount);
+			if (unlikely(!(old->s_flags & MS_BORN))) {
+				deactivate_locked_super(old);
+				goto retry;
+			}
+			return old;
+		}
+	}
+	if (!s) {
+		spin_unlock(&sb_lock);
+		s = alloc_super(type);
+		if (!s)
+			return ERR_PTR(-ENOMEM);
+		goto retry;
+	}
+
+	err = set(s, data);
+	if (err) {
+		spin_unlock(&sb_lock);
+		up_write(&s->s_umount);
+		destroy_super(s);
+		return ERR_PTR(err);
+	}
+	s->s_type = type;
+	strlcpy(s->s_id, type->name, sizeof(s->s_id));
+	list_add_tail(&s->s_list, &super_blocks);
+	hlist_add_head(&s->s_instances, &type->fs_supers);
+	spin_unlock(&sb_lock);
+/*	get_filesystem(type); */
+/*	register_shrinker(&s->s_shrink); */
+	return s;
+}
+
+void kill_anon_super(struct super_block *sb)
+{
+
+}
diff --git a/arch/lib/sysfs.c b/arch/lib/sysfs.c
new file mode 100644
index 0000000..2def2ca
--- /dev/null
+++ b/arch/lib/sysfs.c
@@ -0,0 +1,83 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+int sysfs_create_bin_file(struct kobject *kobj,
+			  const struct bin_attribute *attr)
+{
+	return 0;
+}
+void sysfs_remove_bin_file(struct kobject *kobj,
+			   const struct bin_attribute *attr)
+{
+}
+int sysfs_create_dir(struct kobject *kobj)
+{
+	return 0;
+}
+int sysfs_create_link(struct kobject *kobj, struct kobject *target,
+		      const char *name)
+{
+	return 0;
+}
+int sysfs_move_dir(struct kobject *kobj,
+		   struct kobject *new_parent_kobj)
+{
+	return 0;
+}
+void sysfs_remove_dir(struct kobject *kobj)
+{
+}
+void sysfs_remove_group(struct kobject *kobj,
+			const struct attribute_group *grp)
+{
+}
+int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+{
+	return 0;
+}
+int __must_check sysfs_create_group(struct kobject *kobj,
+				    const struct attribute_group *grp)
+{
+	return 0;
+}
+int sysfs_create_groups(struct kobject *kobj,
+			const struct attribute_group **groups)
+{
+	return 0;
+}
+int sysfs_schedule_callback(struct kobject *kobj,
+			    void (*func)(
+				    void *), void *data, struct module *owner)
+{
+	return 0;
+}
+void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
+		       const char *name)
+{
+}
+void sysfs_exit_ns(enum kobj_ns_type type, const void *tag)
+{
+}
+void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
+{
+}
+int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
+{
+	kobj->sd = lib_malloc(sizeof(struct kernfs_node));
+	return 0;
+}
+int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
+			 const void *ns)
+{
+	return 0;
+}
diff --git a/arch/lib/vmscan.c b/arch/lib/vmscan.c
new file mode 100644
index 0000000..3132f66
--- /dev/null
+++ b/arch/lib/vmscan.c
@@ -0,0 +1,26 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/mm.h>
+#include <linux/shrinker.h>
+
+/*
+ * Add a shrinker callback to be called from the vm
+ */
+int register_shrinker(struct shrinker *shrinker)
+{
+	return 0;
+}
+
+/*
+ * Remove one
+ */
+void unregister_shrinker(struct shrinker *shrinker)
+{
+}
+
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 09/11] lib: asm-generic files
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (7 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 08/11] lib: other kernel glue layer code Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 10/11] lib: libos build scripts and documentation Hajime Tazaki
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/include/asm/Kbuild           | 55 +++++++++++++++++++++++++++++++++++
 arch/lib/include/asm/atomic.h         | 47 ++++++++++++++++++++++++++++++
 arch/lib/include/asm/barrier.h        |  8 +++++
 arch/lib/include/asm/bitsperlong.h    | 12 ++++++++
 arch/lib/include/asm/current.h        |  7 +++++
 arch/lib/include/asm/elf.h            | 10 +++++++
 arch/lib/include/asm/hardirq.h        |  8 +++++
 arch/lib/include/asm/page.h           | 14 +++++++++
 arch/lib/include/asm/pgtable.h        | 30 +++++++++++++++++++
 arch/lib/include/asm/processor.h      | 19 ++++++++++++
 arch/lib/include/asm/ptrace.h         |  4 +++
 arch/lib/include/asm/segment.h        |  6 ++++
 arch/lib/include/asm/sembuf.h         |  4 +++
 arch/lib/include/asm/shmbuf.h         |  4 +++
 arch/lib/include/asm/shmparam.h       |  4 +++
 arch/lib/include/asm/sigcontext.h     |  6 ++++
 arch/lib/include/asm/slab.h           | 21 +++++++++++++
 arch/lib/include/asm/stat.h           |  4 +++
 arch/lib/include/asm/statfs.h         |  4 +++
 arch/lib/include/asm/swab.h           |  7 +++++
 arch/lib/include/asm/thread_info.h    | 35 ++++++++++++++++++++++
 arch/lib/include/asm/uaccess.h        | 14 +++++++++
 arch/lib/include/asm/unistd.h         |  4 +++
 arch/lib/include/uapi/asm/byteorder.h |  6 ++++
 24 files changed, 333 insertions(+)
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/slab.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h

diff --git a/arch/lib/include/asm/Kbuild b/arch/lib/include/asm/Kbuild
new file mode 100644
index 0000000..9649a11
--- /dev/null
+++ b/arch/lib/include/asm/Kbuild
@@ -0,0 +1,55 @@
+generic-y += auxvec.h
+generic-y += bitops.h
+generic-y += bug.h
+generic-y += cache.h
+generic-y += cacheflush.h
+generic-y += checksum.h
+generic-y += cputime.h
+generic-y += cmpxchg.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += exec.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += io.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq.h
+generic-y += irqflags.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += linkage.h
+generic-y += local.h
+generic-y += mcs_spinlock.h
+generic-y += mman.h
+generic-y += mmu.h
+generic-y += module.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += preempt.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += setup.h
+generic-y += signal.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += string.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += timex.h
+generic-y += types.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += unaligned.h
diff --git a/arch/lib/include/asm/atomic.h b/arch/lib/include/asm/atomic.h
new file mode 100644
index 0000000..d98ae3f
--- /dev/null
+++ b/arch/lib/include/asm/atomic.h
@@ -0,0 +1,47 @@
+#ifndef _ASM_SIM_ATOMIC_H
+#define _ASM_SIM_ATOMIC_H
+
+#include <linux/types.h>
+
+#if !defined(CONFIG_64BIT)
+typedef struct {
+	volatile long long counter;
+} atomic64_t;
+#endif
+
+#define ATOMIC64_INIT(i) { (i) }
+
+#define atomic64_read(v)        (*(volatile long *)&(v)->counter)
+void atomic64_add(long i, atomic64_t *v);
+static inline void atomic64_sub(long i, atomic64_t *v)
+{
+	v->counter -= i;
+}
+int atomic64_sub_and_test(long i, atomic64_t *v);
+void atomic64_inc(atomic64_t *v);
+#define atomic64_dec(v)			atomic64_sub(1LL, (v))
+int atomic64_dec_and_test(atomic64_t *v);
+int atomic64_inc_and_test(atomic64_t *v);
+int atomic64_add_negative(long i, atomic64_t *v);
+/* long atomic64_add_return(long i, atomic64_t *v); */
+static inline long atomic64_add_return(long i, atomic64_t *v)
+{
+	v->counter += i;
+	return v->counter;
+}
+static inline void atomic64_set(atomic64_t *v, long i)
+{
+	v->counter = i;
+}
+long atomic64_sub_return(long i, atomic64_t *v);
+long atomic64_inc_return(atomic64_t *v);
+long atomic64_dec_return(atomic64_t *v);
+long atomic64_cmpxchg(atomic64_t *v, long old, long new);
+long atomic64_xchg(atomic64_t *v, long new);
+int atomic64_add_unless(atomic64_t *v, long a, long u);
+int atomic64_inc_is_not_zero(atomic64_t *v);
+#define atomic64_inc_not_zero(v) 	atomic64_add_unless((v), 1LL, 0LL)
+
+#include <asm-generic/atomic.h>
+
+#endif /* _ASM_SIM_ATOMIC_H */
diff --git a/arch/lib/include/asm/barrier.h b/arch/lib/include/asm/barrier.h
new file mode 100644
index 0000000..47adcc6
--- /dev/null
+++ b/arch/lib/include/asm/barrier.h
@@ -0,0 +1,8 @@
+#include <asm-generic/barrier.h>
+
+#undef smp_store_release
+#define smp_store_release(p, v)						\
+	do {								\
+		smp_mb();						\
+		ACCESS_ONCE(*p) = (v);					\
+	} while (0)
diff --git a/arch/lib/include/asm/bitsperlong.h b/arch/lib/include/asm/bitsperlong.h
new file mode 100644
index 0000000..c7592f9
--- /dev/null
+++ b/arch/lib/include/asm/bitsperlong.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_SIM_BITSPERLONG_H
+#define _ASM_SIM_BITSPERLONG_H
+
+#ifdef CONFIG_64BIT
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif /* CONFIG_64BIT */
+
+#define __BITS_PER_LONG BITS_PER_LONG
+
+#endif /* _ASM_SIM_BITSPERLONG_H */
diff --git a/arch/lib/include/asm/current.h b/arch/lib/include/asm/current.h
new file mode 100644
index 0000000..62489cd
--- /dev/null
+++ b/arch/lib/include/asm/current.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SIM_CURRENT_H
+#define _ASM_SIM_CURRENT_H
+
+struct task_struct *get_current(void);
+#define current get_current()
+
+#endif /* _ASM_SIM_CURRENT_H */
diff --git a/arch/lib/include/asm/elf.h b/arch/lib/include/asm/elf.h
new file mode 100644
index 0000000..a7396c9
--- /dev/null
+++ b/arch/lib/include/asm/elf.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_SIM_ELF_H
+#define _ASM_SIM_ELF_H
+
+#if defined(CONFIG_64BIT)
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
+#endif /* _ASM_SIM_ELF_H */
diff --git a/arch/lib/include/asm/hardirq.h b/arch/lib/include/asm/hardirq.h
new file mode 100644
index 0000000..47d47f9
--- /dev/null
+++ b/arch/lib/include/asm/hardirq.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_SIM_HARDIRQ_H
+#define _ASM_SIM_HARDIRQ_H
+
+extern unsigned int interrupt_pending;
+
+#define local_softirq_pending() (interrupt_pending)
+
+#endif /* _ASM_SIM_HARDIRQ_H */
diff --git a/arch/lib/include/asm/page.h b/arch/lib/include/asm/page.h
new file mode 100644
index 0000000..8c0aa74
--- /dev/null
+++ b/arch/lib/include/asm/page.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_SIM_PAGE_H
+#define _ASM_SIM_PAGE_H
+
+typedef struct {} pud_t;
+
+#define THREAD_ORDER    1
+#define THREAD_SIZE  (PAGE_SIZE << THREAD_ORDER)
+
+#define WANT_PAGE_VIRTUAL 1
+
+#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
+
+#endif /* _ASM_SIM_PAGE_H */
diff --git a/arch/lib/include/asm/pgtable.h b/arch/lib/include/asm/pgtable.h
new file mode 100644
index 0000000..ce599c8
--- /dev/null
+++ b/arch/lib/include/asm/pgtable.h
@@ -0,0 +1,30 @@
+#ifndef _ASM_SIM_PGTABLE_H
+#define _ASM_SIM_PGTABLE_H
+
+#define PAGE_KERNEL ((pgprot_t) {0 })
+
+#define arch_start_context_switch(prev) do {} while (0)
+
+#define kern_addr_valid(addr)(1)
+#define pte_file(pte)(1)
+/* Encode and de-code a swap entry */
+#define __swp_type(x)                   (((x).val >> 5) & 0x1f)
+#define __swp_offset(x)                 ((x).val >> 11)
+#define __swp_entry(type, offset) \
+	((swp_entry_t) {((type) << 5) | ((offset) << 11) })
+#define __pte_to_swp_entry(pte)         ((swp_entry_t) {pte_val((pte)) })
+#define __swp_entry_to_pte(x)           ((pte_t) {(x).val })
+#define pmd_page(pmd) (struct page *)(pmd_val(pmd) & PAGE_MASK)
+#define pgtable_cache_init()   do { } while (0)
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+	return 0;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+	return pte;
+}
+
+#endif /* _ASM_SIM_PGTABLE_H */
diff --git a/arch/lib/include/asm/processor.h b/arch/lib/include/asm/processor.h
new file mode 100644
index 0000000..b673ee0
--- /dev/null
+++ b/arch/lib/include/asm/processor.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_SIM_PROCESSOR_H
+#define _ASM_SIM_PROCESSOR_H
+
+struct thread_struct {};
+
+#define cpu_relax()
+#define cpu_relax_lowlatency() cpu_relax()
+#define KSTK_ESP(tsk)	(0)
+
+void *current_text_addr(void);
+
+#define TASK_SIZE ((~(long)0))
+
+#define thread_saved_pc(x) (unsigned long)0
+#define task_pt_regs(t) NULL
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+#endif /* _ASM_SIM_PROCESSOR_H */
diff --git a/arch/lib/include/asm/ptrace.h b/arch/lib/include/asm/ptrace.h
new file mode 100644
index 0000000..ddd9708
--- /dev/null
+++ b/arch/lib/include/asm/ptrace.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_PTRACE_H
+#define _ASM_SIM_PTRACE_H
+
+#endif /* _ASM_SIM_PTRACE_H */
diff --git a/arch/lib/include/asm/segment.h b/arch/lib/include/asm/segment.h
new file mode 100644
index 0000000..e056922
--- /dev/null
+++ b/arch/lib/include/asm/segment.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SIM_SEGMENT_H
+#define _ASM_SIM_SEGMENT_H
+
+typedef struct { int seg; } mm_segment_t;
+
+#endif /* _ASM_SIM_SEGMENT_H */
diff --git a/arch/lib/include/asm/sembuf.h b/arch/lib/include/asm/sembuf.h
new file mode 100644
index 0000000..d64927b
--- /dev/null
+++ b/arch/lib/include/asm/sembuf.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SEMBUF_H
+#define _ASM_SIM_SEMBUF_H
+
+#endif /* _ASM_SIM_SEMBUF_H */
diff --git a/arch/lib/include/asm/shmbuf.h b/arch/lib/include/asm/shmbuf.h
new file mode 100644
index 0000000..42d0a71
--- /dev/null
+++ b/arch/lib/include/asm/shmbuf.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SHMBUF_H
+#define _ASM_SIM_SHMBUF_H
+
+#endif /* _ASM_SIM_SHMBUF_H */
diff --git a/arch/lib/include/asm/shmparam.h b/arch/lib/include/asm/shmparam.h
new file mode 100644
index 0000000..3410f1b
--- /dev/null
+++ b/arch/lib/include/asm/shmparam.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SHMPARAM_H
+#define _ASM_SIM_SHMPARAM_H
+
+#endif /* _ASM_SIM_SHMPARAM_H */
diff --git a/arch/lib/include/asm/sigcontext.h b/arch/lib/include/asm/sigcontext.h
new file mode 100644
index 0000000..230b4b5
--- /dev/null
+++ b/arch/lib/include/asm/sigcontext.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SIM_SIGCONTEXT_H
+#define _ASM_SIM_SIGCONTEXT_H
+
+struct sigcontext {};
+
+#endif /* _ASM_SIM_SIGCONTEXT_H */
diff --git a/arch/lib/include/asm/slab.h b/arch/lib/include/asm/slab.h
new file mode 100644
index 0000000..a3f5d19
--- /dev/null
+++ b/arch/lib/include/asm/slab.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SIM_SLAB_H
+#define _ASM_SIM_SLAB_H
+
+
+struct kmem_cache {
+	unsigned int object_size;
+	const char *name;
+	size_t size;
+	size_t align;
+	unsigned long flags;
+	void (*ctor)(void *);
+};
+
+void *__kmalloc(size_t size, gfp_t flags);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+static __always_inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc(size, flags);
+}
+
+#endif /* _ASM_SIM_SLAB_H */
diff --git a/arch/lib/include/asm/stat.h b/arch/lib/include/asm/stat.h
new file mode 100644
index 0000000..80fa2cb
--- /dev/null
+++ b/arch/lib/include/asm/stat.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_STAT_H
+#define _ASM_SIM_STAT_H
+
+#endif /* _ASM_SIM_STAT_H */
diff --git a/arch/lib/include/asm/statfs.h b/arch/lib/include/asm/statfs.h
new file mode 100644
index 0000000..881ce51
--- /dev/null
+++ b/arch/lib/include/asm/statfs.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_STATFS_H
+#define _ASM_SIM_STATFS_H
+
+#endif /* _ASM_SIM_STATFS_H */
diff --git a/arch/lib/include/asm/swab.h b/arch/lib/include/asm/swab.h
new file mode 100644
index 0000000..d81376a
--- /dev/null
+++ b/arch/lib/include/asm/swab.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SIM_SWAB_H
+#define _ASM_SIM_SWAB_H
+
+#include <linux/types.h>
+
+
+#endif /* _ASM_SIM_SWAB_H */
diff --git a/arch/lib/include/asm/thread_info.h b/arch/lib/include/asm/thread_info.h
new file mode 100644
index 0000000..a9a26d9
--- /dev/null
+++ b/arch/lib/include/asm/thread_info.h
@@ -0,0 +1,35 @@
+#ifndef _ASM_SIM_THREAD_INFO_H
+#define _ASM_SIM_THREAD_INFO_H
+
+#define TIF_NEED_RESCHED 1
+#define TIF_SIGPENDING 2
+
+struct thread_info {
+	__u32 flags;
+	int preempt_count;
+	struct task_struct *task;
+	struct restart_block restart_block;
+};
+
+struct thread_info *current_thread_info(void);
+struct thread_info *alloc_thread_info(struct task_struct *task);
+void free_thread_info(struct thread_info *ti);
+
+#define TS_RESTORE_SIGMASK      0x0008  /* restore signal mask in do_signal() */
+#define HAVE_SET_RESTORE_SIGMASK        1
+static inline void set_restore_sigmask(void)
+{
+}
+static inline void clear_restore_sigmask(void)
+{
+}
+static inline bool test_restore_sigmask(void)
+{
+	return true;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+	return true;
+}
+
+#endif /* _ASM_SIM_THREAD_INFO_H */
diff --git a/arch/lib/include/asm/uaccess.h b/arch/lib/include/asm/uaccess.h
new file mode 100644
index 0000000..74f973b
--- /dev/null
+++ b/arch/lib/include/asm/uaccess.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_SIM_UACCESS_H
+#define _ASM_SIM_UACCESS_H
+
+#define KERNEL_DS ((mm_segment_t) {0 })
+#define USER_DS ((mm_segment_t) {0 })
+#define get_fs() KERNEL_DS
+#define get_ds() USER_DS
+#define set_fs(x) do {} while ((x.seg) != (x.seg))
+
+#define __access_ok(addr, size) (1)
+
+#include <asm-generic/uaccess.h>
+
+#endif /* _ASM_SIM_UACCESS_H */
diff --git a/arch/lib/include/asm/unistd.h b/arch/lib/include/asm/unistd.h
new file mode 100644
index 0000000..6b482b4
--- /dev/null
+++ b/arch/lib/include/asm/unistd.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_UNISTD_H
+#define _ASM_SIM_UNISTD_H
+
+#endif /* _ASM_SIM_UNISTD_H */
diff --git a/arch/lib/include/uapi/asm/byteorder.h b/arch/lib/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..b13a7a8
--- /dev/null
+++ b/arch/lib/include/uapi/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_BYTEORDER_H
+#define _ASM_X86_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_X86_BYTEORDER_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 10/11] lib: libos build scripts and documentation
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (8 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 09/11] lib: asm-generic files Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:10 ` [RFC PATCH 11/11] lib: tools used for test scripts Hajime Tazaki
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage, Ryo Nakamura

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 Documentation/virtual/libos-howto.txt | 143 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   8 +
 arch/lib/Kconfig                      | 121 +++++++
 arch/lib/Makefile                     | 248 +++++++++++++
 arch/lib/Makefile.print               |  44 +++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/processor.mk                 |   7 +
 9 files changed, 1283 insertions(+)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/defconfig
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/processor.mk

diff --git a/Documentation/virtual/libos-howto.txt b/Documentation/virtual/libos-howto.txt
new file mode 100644
index 0000000..18cb443
--- /dev/null
+++ b/Documentation/virtual/libos-howto.txt
@@ -0,0 +1,143 @@
+Library operating system (libos) version of Linux
+=================================================
+
+* Overview
+
+New hardware independent architecture 'arch/lib', configured by
+CONFIG_LIB gives you two features.
+
+- network stack in userspace (NUSE)
+  NUSE will give you a personalized network stack for each application
+  without replacing host operating system.
+
+- network simulator integration, which is called Direct Code Execution (DCE)
+  DCE will give us a network simulation environment with Linux network stack
+  to investigate the detail behavior protocol implementation with a flexible
+  network configuration. This is also useful for the testing environment.
+
+(- more abstracted implementation of underlying platform will be a future
+   direction (e.g., rump hypercall))
+
+In both features, Linux kernel network stack is running on top of
+userspace application with a linked or dynamically loaded library.
+
+They have their own, isolated network stack from host operating system
+so they are configured different IP addresses as other virtualization
+methods do.
+
+
+* How different with others ?
+
+- User-mode Linux (UML)
+
+UML is a way to execute Linux kernel code as a userspace
+application. It is completely isolated from host kernel but can host
+arbitrary userspace applications on top of UML.
+
+- namespace / container
+
+Container technologies with namespace brings a process-level isolation
+to host multiple network entities but shares the kernel among
+processes, which prevents to introduce new features implemented in
+kernel space.
+
+
+* How to build it ?
+
+configuration of arch/lib follows a standard configuration of kernel.
+
+ make defconfig ARCH=lib
+
+or
+
+ make menuconfig ARCH=lib
+
+then you can build a set of libraries for libos.
+
+ make library ARCH=lib
+
+This will give you a shared library file liblinux-$(KERNELVERSION).so
+in the top directory.
+
+* Hello world
+
+you may first need to configure a configuration file, named
+'nuse.conf' so that the library version of network stack can know what
+kind of IP configuration should be used. There is an example file
+at arch/lib/nuse.conf.sample: you may copy and modify it for your purpose.
+
+ sudo NUSECONF=nuse.conf ./nuse ping www.google.com
+
+
+
+* Example use cases
+- regression test with Direct Code Execution (DCE)
+
+'make test' by DCE gives a test platform for networking code, with the
+help of network simulator facilities like link delay/bandwidth/drop
+configurations, large network topology with userspace routing protocol
+daemons, etc.
+
+An interesting feature is the determinism of any test executions. A
+test script always gives same results in every execution if there is
+no modification on test target code.
+
+For the first step, you need to obtain network simulator
+environment. 'make testbin' does all the stuff for the preparation.
+
+% make testbin -C tools/testing/libos
+
+Then, you can 'make test' for your code.
+
+% make test ARCH=lib
+
+ PASS: TestSuite netlink-socket
+ PASS: TestSuite process-manager
+ PASS: TestSuite dce-cradle
+ PASS: TestSuite dce-mptcp
+ PASS: TestSuite dce-umip
+ PASS: TestSuite dce-quagga
+ PASS: Example dce-tcp-simple
+ PASS: Example dce-udp-simple
+
+
+- userspace network stack (NUSE)
+
+an application can use its own network stack, distinct from host network stack
+in order to personalize any network feature to the application specific one.
+The 'nuse' wrapper script, based on LD_PRELOAD technique, carefully replaces
+socket API and redirects system calls to the network stack library, provided by
+this framework.
+
+the network stack can be used with any kind of raw-socket like
+technologies such as Intel DPDK, netmap, etc.
+
+
+
+* Files / External Repository
+
+The kernel source tree (i.e., arch/lib) only contains a shared part of
+applications (NUSE/DCE). Pure userspace part is managed at a different
+repository, called Linux-libos-tools: it is automatically downloaded
+during make library.
+
+ https://github.com/libos-nuse/linux-libos-tools
+
+
+* More information
+- ns-3-users@googlegroups.com (ns-3 related questions)
+- articles, slides
+ Experimentation Tools for Networking Research (Lacage, 2010)
+   http://cutebugs.net/files/thesis.pdf
+ Direct code execution: revisiting library OS architecture for reproducible
+  network experiments (Tazaki et al., 2013)
+   http://dx.doi.org/10.1145/2535372.2535374
+ Library Operating System with Mainline Linux Network Stack (Tazaki et al., 2015)
+   https://www.netdev01.org/docs/netdev01-tazaki-libos.pdf (slides)
+
+
+* Authors
+ Mathieu Lacage <mathieu.lacage@gmail.com>
+ Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ Frederic Urbani <frederic.urbani@gmail.com>
+ Ryo Nakamura <upa@haeena.net>
diff --git a/MAINTAINERS b/MAINTAINERS
index 3589d67..637d853 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5699,6 +5699,15 @@ M:	Sasha Levin <sasha.levin@oracle.com>
 S:	Maintained
 F:	tools/lib/lockdep/
 
+LIBRARY OS (LIBOS)
+M:	Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+L:	(TBD)
+W:	http://libos-nuse.github.io/
+S:	Maintained
+F:	Documentation/virtual/libos-howto.txt
+F:	arch/lib/
+F:	tools/testing/libos/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:	Paul Mackerras <paulus@au.ibm.com>
 W:	http://www.ibm.com/linux/ltc/projects/ppc
diff --git a/arch/lib/.gitignore b/arch/lib/.gitignore
new file mode 100644
index 0000000..9f48573
--- /dev/null
+++ b/arch/lib/.gitignore
@@ -0,0 +1,8 @@
+linker.lds
+autoconf.h
+objs.mk
+timeconst.h
+hz.bc
+crc32table.h
+*.d
+tools
diff --git a/arch/lib/Kconfig b/arch/lib/Kconfig
new file mode 100644
index 0000000..eb7dede
--- /dev/null
+++ b/arch/lib/Kconfig
@@ -0,0 +1,121 @@
+menuconfig LIB
+       bool "LibOS-specific options"
+       def_bool n
+       select PROC_FS
+       select PROC_SYSCTL
+       select SYSCTL
+       select SYSFS
+       help
+          The 'lib' architecture is a library (user-mode) version of
+          the linux kernel that includes only its network stack and is
+	  used within the userspace application, and ns-3 simulator.
+	  For more information, about ns-3, see http://www.nsnam.org.
+
+config EXPERIMENTAL
+	def_bool y
+
+config MMU
+        def_bool n
+config FPU
+        def_bool n
+config SMP
+        def_bool n
+
+config ARCH
+	string
+	option env="ARCH"
+
+config KTIME_SCALAR
+       def_bool y
+
+config MODULES
+       def_bool y
+       option modules
+
+config GENERIC_CSUM
+	def_bool y
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+config PRINTK
+       def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+config GENERIC_HWEIGHT
+       def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config NO_HZ
+	def_bool y
+
+config BASE_FULL
+       def_bool n
+
+config SELECT_MEMORY_MODEL
+       def_bool n
+
+config FLAT_NODE_MEM_MAP
+       def_bool n
+
+config PAGEFLAGS_EXTENDED
+       def_bool n
+
+config VIRT_TO_BUS
+       def_bool n
+
+config HAS_DMA
+       def_bool n
+
+config HZ
+        int
+        default 250
+
+config TINY_RCU
+       def_bool y
+
+config HZ_250
+       def_bool y
+
+config BASE_SMALL
+       int
+       default 1
+
+config SPLIT_PTLOCK_CPUS
+       int
+       default 1
+
+config FLATMEM
+       def_bool y
+
+config SYSCTL
+       def_bool y
+
+config PROC_FS
+       def_bool y
+
+config SYSFS
+       def_bool y
+
+config PROC_SYSCTL
+       def_bool y
+
+config NETDEVICES
+       def_bool y
+
+source "net/Kconfig"
+
+source "drivers/base/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+
diff --git a/arch/lib/Makefile b/arch/lib/Makefile
new file mode 100644
index 0000000..6fe7c10
--- /dev/null
+++ b/arch/lib/Makefile
@@ -0,0 +1,248 @@
+ARCH_DIR := arch/lib
+SRCDIR=$(dir $(firstword $(MAKEFILE_LIST)))
+DCE_TESTDIR=$(srctree)/tools/testing/libos/
+KBUILD_KCONFIG := arch/$(ARCH)/Kconfig
+
+CC = gcc
+GCCVERSIONGTEQ48 := $(shell expr `gcc -dumpversion` \>= 4.8)
+ifeq "$(GCCVERSIONGTEQ48)" "1"
+   NO_TREE_LOOP_OPT += -fno-tree-loop-distribute-patterns
+endif
+
+
+-include $(ARCH_DIR)/objs.mk
+-include $(srctree)/.config
+include $(ARCH_DIR)/processor.mk
+
+# targets
+LIBOS_TOOLS=$(ARCH_DIR)/tools
+LIBOS_GIT_REPO=git://github.com/libos-nuse/linux-libos-tools
+KERNEL_LIB=liblinux-$(KERNELVERSION).so
+
+ALL_OBJS=$(OBJS) $(KERNEL_LIB) $(modules) $(all-obj-for-clean)
+
+# auto generated files
+AUTOGENS=$(CRC32TABLE) $(COMPILE_H) $(BOUNDS_H) $(ARCH_DIR)/timeconst.h $(ARCH_DIR)/linker.lds
+COMPILE_H=$(srctree)/include/generated/compile.h
+BOUNDS_H=$(srctree)/include/generated/bounds.h
+
+# from lib/Makefile
+CRC32TABLE = $(ARCH_DIR)/crc32table.h
+hostprogs-y	:= $(srctree)/lib/gen_crc32table
+clean-files	:= crc32table.h
+
+# sources and objects
+LIB_SRC=\
+lib.c lib-device.c lib-socket.c random.c softirq.c time.c \
+glue.c fs.c sysctl.c timer.c \
+hrtimer.c sched.c sysfs.c workqueue.c \
+print.c security.c slab.c tasklet.c \
+proc.c seq.c tasklet-hrtimer.c \
+cred.c pid.c modules.c filemap.c splice.c vmscan.c \
+dcache.c super.c inode.c
+
+LIB_OBJ=$(addprefix $(ARCH_DIR)/,$(addsuffix .o,$(basename $(LIB_SRC))))
+
+DEPENDS=$(addprefix $(ARCH_DIR)/.,\
+	$(addsuffix .d,$(basename $(LIB_SRC)))\
+	)
+
+# options
+COV?=no
+cov_yes=-fprofile-arcs -ftest-coverage
+cov_no=
+covl_yes=-fprofile-arcs
+covl_no=
+OPT?=yes
+opt_yes=-O3 -fomit-frame-pointer $(NO_TREE_LOOP_OPT)
+opt_no=-O0
+PIC?=yes
+pic_yes=-fpic -DPIC
+pic_no=-mcmodel=large
+PIC_CFLAGS=$(pic_$(PIC))
+
+# flags
+CFLAGS_USPACE= \
+ $(opt_$(OPT)) -g3 -Wall -Wstrict-prototypes -Wno-trigraphs \
+ -fno-inline -fno-strict-aliasing -fno-common \
+ -fno-delete-null-pointer-checks -fno-builtin \
+ -fno-stack-protector -Wno-unused -Wno-pointer-sign \
+ $(PIC_CFLAGS) -D_DEBUG $(cov_$(COV)) -I$(ARCH_DIR)/include
+
+CFLAGS+= \
+ $(CFLAGS_USPACE) -nostdinc -D__KERNEL__ -iwithprefix $(srctree)/include \
+ -DKBUILD_BASENAME=\"clnt\" -DKBUILD_MODNAME=\"nsc\" -DMODVERSIONS \
+ -DEXPORT_SYMTAB \
+ -U__FreeBSD__ -D__linux__=1 -Dlinux=1 -D__linux=1 \
+ -DCONFIG_DEFAULT_HOSTNAME=\"lib\" \
+ -I$(ARCH_DIR)/include/generated/uapi \
+ -I$(ARCH_DIR)/include/generated \
+ -I$(srctree)/include -I$(ARCH_DIR)/include/uapi \
+ -I$(srctree)/include/uapi -I$(srctree)/include/generated/uapi \
+ -include $(srctree)/include/linux/kconfig.h \
+ -I$(ARCH_DIR) -I.
+
+ifeq ($(PROCESSOR_SIZE),64)
+CFLAGS+= -DCONFIG_64BIT
+endif
+
+LDFLAGS += -shared -nodefaultlibs -g3 -Wl,-O1 -Wl,-T$(ARCH_DIR)/linker.lds $(covl_$(COV))
+
+# targets
+
+modules:=
+all-obj-for-clean:=
+
+all: library modules
+
+# note: the directory order below matters to ensure that we match the kernel order
+dirs=kernel/ kernel/time/ kernel/rcu/ kernel/locking/ kernel/bpf/ mm/ fs/ fs/proc/ crypto/ lib/ drivers/base/ drivers/net/ net/ init/
+empty:=
+space:= $(empty) $(empty)
+colon:= :
+comma= ,
+kernel/_to_keep=notifier.o params.o sysctl.o \
+rwsem.o semaphore.o kfifo.o
+kernel/time/_to_keep=time.o
+kernel/rcu_to_keep=rcu/srcu.o rcu/pdate.o rcu/tiny.o
+kernel/locking_to_keep=locking/mutex.o
+kernel/bpf_to_keep=bpf/core.o
+mm/_to_keep=util.o list_lru.o iov_iter.o
+crypto/_to_keep=aead.o ahash.o shash.o api.o algapi.o cipher.o compress.o proc.o \
+crc32c_generic.o
+drivers/base/_to_keep=class.o core.o bus.o dd.o driver.o devres.o module.o
+drivers/net/_to_keep=loopback.o
+lib/_to_keep=klist.o kobject.o kref.o hweight.o int_sqrt.o checksum.o \
+find_last_bit.o find_next_bit.o bitmap.o nlattr.o idr.o libcrc32c.o \
+ctype.o string.o kasprintf.o rbtree.o sha1.o textsearch.o vsprintf.o \
+rwsem-spinlock.o scatterlist.o ratelimit.o hexdump.o dec_and_lock.o \
+div64.o dynamic_queue_limits.o md5.o kstrtox.o iovec.o lockref.o crc32.o \
+rhashtable.o
+fs/_to_keep=read_write.o libfs.o namei.o
+fs/proc/_to_keep=proc_sysctl.o
+init/_to_keep=version.o
+
+quiet_cmd_objsmk = OBJS-MK   $@
+      cmd_objsmk = \
+	for i in 1; do \
+	$(foreach d,$(dirs), \
+           $(MAKE) -i -s -f $< srcdir=$(srctree)/$(d) \
+	    objdir=$(srctree)/$(d) \
+            config=$(srctree)/.config \
+	    to_keep=$(subst $(space),$(colon),$($(d)_to_keep)) print;) \
+	done > $@
+
+$(ARCH_DIR)/objs.mk: $(ARCH_DIR)/Makefile.print $(srctree)/.config $(ARCH_DIR)/Makefile
+	$(call if_changed,objsmk)
+
+quiet_cmd_timeconst = GEN     $@
+      cmd_timeconst = echo "hz=$(CONFIG_HZ)" > $(ARCH_DIR)/hz.bc ; \
+                      bc $(ARCH_DIR)/hz.bc kernel/time/timeconst.bc > $@
+$(ARCH_DIR)/timeconst.h: $(srctree)/.config
+	$(call if_changed,timeconst)
+
+quiet_cmd_linker = GEN     $@
+      cmd_linker = ld -shared --verbose | ./$^ > $@
+$(ARCH_DIR)/linker.lds: $(ARCH_DIR)/generate-linker-script.py
+	$(call if_changed,linker)
+
+quiet_cmd_crc32src = GEN     $@
+      cmd_crc32src = $(MAKE) -f $(srctree)/Makefile silentoldconfig ; \
+                     cc $^ -o $@
+$(srctree)/lib/gen_crc32table: $(srctree)/lib/gen_crc32table.c
+	$(call if_changed,crc32src)
+
+quiet_cmd_crc32 = GEN     $@
+      cmd_crc32 = $< > $@
+
+$(CRC32TABLE): $(srctree)/lib/gen_crc32table
+	$(call if_changed,crc32)
+
+# copied from init/Makefile
+       chk_compile.h = :
+ quiet_chk_compile.h = echo '  CHK     $@'
+silent_chk_compile.h = :
+$(COMPILE_H): include/generated/utsrelease.h asm-generic $(version_h)
+	@$($(quiet)chk_compile.h)
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
+	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
+
+# crafted from $(srctree)/Kbuild
+quiet_cmd_lib_bounds = GEN     $@
+define cmd_lib_bounds
+	(set -e; \
+	 echo "#ifndef GENERATED_BOUNDS_H"; \
+	 echo "#define GENERATED_BOUNDS_H"; \
+	 echo ""; \
+	 echo "#define NR_PAGEFLAGS (__NR_PAGEFLAGS)"; \
+	 echo "#define MAX_NR_ZONES (__MAX_NR_ZONES)"; \
+	 echo ""; \
+	 echo "#endif /* GENERATED_BOUNDS_H */") > $@
+endef
+
+$(BOUNDS_H): FORCE
+	$(Q)mkdir -p $(dir $@)
+	$(call cmd,lib_bounds)
+
+
+KERNEL_BUILTIN=$(addprefix $(srctree)/,$(addsuffix builtin.o,$(dirs)))
+OBJS=$(LIB_OBJ) $(foreach builtin,$(KERNEL_BUILTIN),$(if $($(builtin)),$($(builtin))))
+export OBJS KERNEL_LIB
+
+quiet_cmd_cc = CC   $@
+      cmd_cc = 	mkdir -p $(dir $@);	\
+		$(CC) $(CFLAGS) -c $< -o $@
+quiet_cmd_linkko = KO   $@
+      cmd_linkko = $(CC) -shared -o $@ -nostdlib $^
+quiet_cmd_builtin = BUILTIN   $@
+      cmd_builtin = mkdir -p $(dir $(srctree)/$@); rm -f $(srctree)/$@; \
+		    if test -n "$($(srctree)/$@)"; then for f in $($(srctree)/$@); \
+		    do $(AR) Tcru $@ $$f; done; else $(AR) Tcru $@; fi
+
+%/builtin.o:
+	$(call if_changed,builtin)
+%.ko:%.o
+	$(call if_changed,linkko)
+%.o:%.c
+	$(call if_changed,cc)
+
+library: $(KERNEL_LIB) $(LIBOS_TOOLS)
+modules: $(modules)
+
+$(LIBOS_TOOLS): $(KERNEL_LIB) Makefile FORCE
+	$(Q) if [ ! -d "$@" ]; then \
+		git clone $(LIBOS_GIT_REPO) $@ ;\
+	fi
+	$(Q) $(MAKE) -C $(LIBOS_TOOLS)
+
+install: modules library
+
+install-dir:
+
+$(KERNEL_LIB): $(ARCH_DIR)/objs.mk $(AUTOGENS) $(OBJS)
+	$(call if_changed,linklib)
+
+quiet_cmd_linklib = LIB		$@
+      cmd_linklib = $(CC) -Wl,--whole-archive $(OBJS) $(LDFLAGS) -o $@; \
+		    ln -s -f $(KERNEL_LIB) liblinux.so
+
+quiet_cmd_clean = CLEAN   $@
+      cmd_clean = for f in $(foreach m,$(modules),$($(m))) ; do rm -f $$f 2>/dev/null; done ; \
+		  for f in $(ALL_OBJS); do rm -f $$f; done 2>/dev/null ;\
+		  rm -rf $(AUTOGENS) $(ARCH_DIR)/objs.mk 2>/dev/null ;\
+		  if [ -d $(LIBOS_TOOLS) ]; then $(MAKE) -C $(LIBOS_TOOLS) clean ; fi
+
+archclean:
+	$(call if_changed,clean)
+
+.%.d:%.c $(srctree)/.config
+	$(Q) set -e; $(CC) -MM -MT $(<:.c=.o) $(CFLAGS) $< > $@
+
+deplib: $(DEPENDS)
+	-include $(DEPENDS)
+
+test:
+	$(Q) $(MAKE) -C $(DCE_TESTDIR)/
+
+.PHONY : clean deplib
+
diff --git a/arch/lib/Makefile.print b/arch/lib/Makefile.print
new file mode 100644
index 0000000..56b68b6
--- /dev/null
+++ b/arch/lib/Makefile.print
@@ -0,0 +1,44 @@
+# inherit $(objdir) $(config) $(srcdir) $(to_keep) from command-line
+
+include $(config)
+include $(srcdir)Makefile
+
+# fix minor nits for make version dependencies
+ifeq (3.82,$(firstword $(sort $(MAKE_VERSION) 3.82)))
+  SEPARATOR=
+else
+  SEPARATOR=/
+endif
+
+to_keep_list=$(subst :, ,$(to_keep))
+obj-y += $(lib-y)
+obj-m += $(lib-m)
+subdirs := $(filter %/, $(obj-y) $(obj-m))
+subdirs-y := $(filter %/, $(obj-y))
+subdirs-m := $(filter %/, $(obj-m))
+tmp1-obj-y=$(patsubst %/,%/builtin.o,$(obj-y))
+tmp1-obj-m=$(filter-out $(subdirs-m),$(obj-m))
+tmp2-obj-y=$(foreach m,$(tmp1-obj-y), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
+tmp2-obj-m=$(foreach m,$(tmp1-obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
+tmp3-obj-y=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-y)),$(tmp2-obj-y))
+tmp3-obj-m=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-m)),$(tmp2-obj-m))
+final-obj-y=$(tmp3-obj-y)
+final-obj-m=$(tmp3-obj-m)
+
+print: $(final-obj-m) $(subdirs)
+	@if test $(if $(final-obj-y),1); then \
+	  echo -n $(objdir)builtin.o; echo -n "="; echo $(addprefix $(objdir),$(final-obj-y)); \
+	  echo -n $(objdir)builtin.o; echo -n ": "; echo $(addprefix $(objdir),$(final-obj-y)); \
+	  echo -n "all-obj-for-clean+="; echo $(addprefix $(objdir),$(final-obj-y)) $(objdir)builtin.o; \
+	fi
+$(final-obj-m):
+	@echo -n "modules+="; echo $(addprefix $(objdir),$(@:.o=.ko))
+	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n ": "
+	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
+	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n "="
+	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
+$(subdirs):
+	@$(MAKE) -s -f $(firstword $(MAKEFILE_LIST)) objdir=$(objdir)$@$(SEPARATOR) config=$(config) srcdir=$(srcdir)$@$(SEPARATOR) to_keep=$(to_keep) print 2>/dev/null
+
+.PHONY : core
+.NOTPARALLEL :
diff --git a/arch/lib/defconfig b/arch/lib/defconfig
new file mode 100644
index 0000000..9307e6f
--- /dev/null
+++ b/arch/lib/defconfig
@@ -0,0 +1,653 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux Kernel Configuration
+#
+CONFIG_LIB=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+# CONFIG_SMP is not set
+CONFIG_KTIME_SCALAR=y
+CONFIG_MODULES=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_PRINTK=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_NO_HZ=y
+# CONFIG_BASE_FULL is not set
+# CONFIG_SELECT_MEMORY_MODEL is not set
+# CONFIG_FLAT_NODE_MEM_MAP is not set
+# CONFIG_PAGEFLAGS_EXTENDED is not set
+# CONFIG_VIRT_TO_BUS is not set
+# CONFIG_HAS_DMA is not set
+CONFIG_HZ=250
+CONFIG_TINY_RCU=y
+CONFIG_HZ_250=y
+CONFIG_BASE_SMALL=1
+CONFIG_SPLIT_PTLOCK_CPUS=1
+CONFIG_FLATMEM=y
+CONFIG_SYSCTL=y
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=y
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_NET_UDP_TUNNEL=m
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_GENEVE is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=y
+CONFIG_TCP_CONG_HSTCP=y
+CONFIG_TCP_CONG_HYBLA=y
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=y
+CONFIG_TCP_CONG_LP=y
+CONFIG_TCP_CONG_VENO=y
+CONFIG_TCP_CONG_YEAH=y
+CONFIG_TCP_CONG_ILLINOIS=y
+CONFIG_TCP_CONG_DCTCP=y
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_HYBLA is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_VENO is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_DCTCP is not set
+CONFIG_DEFAULT_RENO=y
+CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=y
+# CONFIG_IPV6_GRE is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=m
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_ACCT=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_LOG_COMMON=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_DCCP=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+CONFIG_NF_NAT_PROTO_SCTP=y
+CONFIG_NF_NAT_AMANDA=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_NF_NAT_TFTP is not set
+CONFIG_NF_NAT_REDIRECT=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_EXTHDR=y
+CONFIG_NFT_META=y
+CONFIG_NFT_CT=y
+CONFIG_NFT_RBTREE=y
+CONFIG_NFT_HASH=y
+CONFIG_NFT_COUNTER=y
+CONFIG_NFT_LOG=y
+CONFIG_NFT_LIMIT=y
+CONFIG_NFT_MASQ=y
+# CONFIG_NFT_REDIR is not set
+CONFIG_NFT_NAT=y
+# CONFIG_NFT_QUEUE is not set
+# CONFIG_NFT_REJECT is not set
+# CONFIG_NFT_REJECT_INET is not set
+# CONFIG_NFT_COMPAT is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+# CONFIG_NETFILTER_XT_SET is not set
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_NETMAP=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_RATEEST=y
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=y
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_L2TP=m
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+CONFIG_IP_SET=y
+CONFIG_IP_SET_MAX=256
+# CONFIG_IP_SET_BITMAP_IP is not set
+# CONFIG_IP_SET_BITMAP_IPMAC is not set
+# CONFIG_IP_SET_BITMAP_PORT is not set
+# CONFIG_IP_SET_HASH_IP is not set
+# CONFIG_IP_SET_HASH_IPMARK is not set
+# CONFIG_IP_SET_HASH_IPPORT is not set
+# CONFIG_IP_SET_HASH_IPPORTIP is not set
+# CONFIG_IP_SET_HASH_IPPORTNET is not set
+# CONFIG_IP_SET_HASH_MAC is not set
+# CONFIG_IP_SET_HASH_NETPORTNET is not set
+# CONFIG_IP_SET_HASH_NET is not set
+# CONFIG_IP_SET_HASH_NETNET is not set
+# CONFIG_IP_SET_HASH_NETPORT is not set
+# CONFIG_IP_SET_HASH_NETIFACE is not set
+# CONFIG_IP_SET_LIST_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_LOG_ARP is not set
+CONFIG_NF_LOG_IPV4=y
+CONFIG_NF_TABLES_IPV4=y
+CONFIG_NFT_CHAIN_ROUTE_IPV4=y
+# CONFIG_NF_REJECT_IPV4 is not set
+# CONFIG_NFT_REJECT_IPV4 is not set
+# CONFIG_NF_TABLES_ARP is not set
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_FILTER is not set
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_TABLES_IPV6=y
+# CONFIG_NFT_CHAIN_ROUTE_IPV6 is not set
+# CONFIG_NF_REJECT_IPV6 is not set
+# CONFIG_NFT_REJECT_IPV6 is not set
+CONFIG_NF_LOG_IPV6=y
+# CONFIG_NF_NAT_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+# CONFIG_NF_TABLES_BRIDGE is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=y
+CONFIG_INET_DCCP_DIAG=y
+
+#
+# DCCP CCIDs Configuration
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=y
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE=y
+# CONFIG_SCTP_COOKIE_HMAC_MD5 is not set
+# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_L2TP=m
+# CONFIG_L2TP_V3 is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_VLAN_8021Q_MVRP is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+CONFIG_IPX_INTERN=y
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_PHONET=m
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_SJA1000=m
+# CONFIG_CAN_SJA1000_ISA is not set
+CONFIG_CAN_SJA1000_PLATFORM=m
+# CONFIG_CAN_C_CAN is not set
+# CONFIG_CAN_M_CAN is not set
+# CONFIG_CAN_CC770 is not set
+# CONFIG_CAN_SOFTING is not set
+CONFIG_CAN_DEBUG_DEVICES=y
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+
+#
+# Dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_BT=m
+CONFIG_BT_BREDR=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_LE=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+# CONFIG_NET_9P is not set
+CONFIG_CAIF=m
+CONFIG_CAIF_DEBUG=y
+CONFIG_CAIF_NETDEV=m
+# CONFIG_CAIF_USB is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_MCRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST_COMMON=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_DRBG_MENU is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
diff --git a/arch/lib/generate-linker-script.py b/arch/lib/generate-linker-script.py
new file mode 100755
index 0000000..db3d7f8
--- /dev/null
+++ b/arch/lib/generate-linker-script.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+import re
+
+def linker_script(reading, writing):
+    delim = re.compile('^==')
+    end_of_ro = re.compile('^ *.gcc_except_table[^:]*:[ ]*ONLY_IF_RW')
+    skipping = True
+    for line in reading.readlines():
+        if delim.search (line) is not None:
+            if skipping:
+                skipping = False
+                continue
+            else:
+                skipping = True
+        if skipping:
+            continue
+        m = end_of_ro.search(line)
+        if m is not None:
+            skipping = False
+            initcall = """
+  /* taken from kernel script*/
+    . = ALIGN (CONSTANT (MAXPAGESIZE));
+    .initcall.init : AT(ADDR(.initcall.init)) {
+     __initcall_start = .;
+     *(.initcallearly.init)
+     *(.initcall0.init)
+     *(.initcall0s.init)
+     *(.initcall1.init)
+     *(.initcall1s.init)
+     *(.initcall2.init)
+     *(.initcall2s.init)
+     *(.initcall3.init)
+     *(.initcall3s.init)
+     *(.initcall4.init)
+     *(.initcall4s.init)
+     *(.initcall5.init)
+     *(.initcall5s.init)
+     *(.initcall6.init)
+     *(.initcall6s.init)
+     *(.initcall7.init)
+     *(.initcall7s.init)
+     __initcall_end = .;
+    }
+"""
+            writing.write (initcall)
+        writing.write(line)
+
+import sys
+linker_script (sys.stdin, sys.stdout)
diff --git a/arch/lib/processor.mk b/arch/lib/processor.mk
new file mode 100644
index 0000000..7331528
--- /dev/null
+++ b/arch/lib/processor.mk
@@ -0,0 +1,7 @@
+PROCESSOR=$(shell uname -m)
+PROCESSOR_x86_64=64
+PROCESSOR_i686=32
+PROCESSOR_i586=32
+PROCESSOR_i386=32
+PROCESSOR_i486=32
+PROCESSOR_SIZE=$(PROCESSOR_$(PROCESSOR))
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH 11/11] lib: tools used for test scripts
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (9 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 10/11] lib: libos build scripts and documentation Hajime Tazaki
@ 2015-03-24 13:10 ` Hajime Tazaki
  2015-03-24 13:21 ` [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Richard Weinberger
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
  12 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 13:10 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

These auxiliary files are used for make test ARCH=lib.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 tools/testing/libos/.gitignore   |  6 +++++
 tools/testing/libos/Makefile     | 38 +++++++++++++++++++++++++++
 tools/testing/libos/README       | 15 +++++++++++
 tools/testing/libos/bisect.sh    | 10 +++++++
 tools/testing/libos/dce-test.sh  | 23 ++++++++++++++++
 tools/testing/libos/nuse-test.sh | 57 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 149 insertions(+)
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

diff --git a/tools/testing/libos/.gitignore b/tools/testing/libos/.gitignore
new file mode 100644
index 0000000..57a74a0
--- /dev/null
+++ b/tools/testing/libos/.gitignore
@@ -0,0 +1,6 @@
+*.pcap
+files-*
+bake
+buildtop
+core
+exitprocs
diff --git a/tools/testing/libos/Makefile b/tools/testing/libos/Makefile
new file mode 100644
index 0000000..3da25429
--- /dev/null
+++ b/tools/testing/libos/Makefile
@@ -0,0 +1,38 @@
+ADD_PARAM?=
+
+all: test
+
+bake:
+	hg clone http://code.nsnam.org/bake
+
+check_pkgs:
+	@./bake/bake.py check | grep Bazaar | grep OK || (echo "bzr is missing" && ./bake/bake.py check)
+	@./bake/bake.py check | grep autoreconf | grep OK || (echo "autotools is missing" && ./bake/bake.py check && exit 1)
+
+testbin: bake check_pkgs
+	@cp ../../../arch/lib/tools/bakeconf-linux.xml bake/bakeconf.xml
+	@mkdir -p buildtop/build/bin_dce
+	cd buildtop ; \
+	../bake/bake.py configure -e dce-linux-inkernel $(BAKECONF_PARAMS)
+	cd buildtop ; \
+	../bake/bake.py show --enabledTree | grep -v  -E "pygoocanvas|graphviz|python-dev" | grep Missing && (echo "required packages are missing") || echo ""
+	cd buildtop ; \
+	../bake/bake.py download ; \
+	../bake/bake.py update ; \
+	../bake/bake.py build
+
+test:
+	@./dce-test.sh ADD_PARAM=$(ADD_PARAM)
+
+test-valgrind:
+	@./dce-test.sh -g ADD_PARAM=$(ADD_PARAM)
+
+test-fault-injection:
+	@./dce-test.sh -f ADD_PARAM=$(ADD_PARAM)
+
+clean:
+#	@rm -rf buildtop
+	@rm -f *.pcap
+	@rm -rf files-*
+	@rm -f exitprocs
+	@rm -f core
diff --git a/tools/testing/libos/README b/tools/testing/libos/README
new file mode 100644
index 0000000..51ac5a5
--- /dev/null
+++ b/tools/testing/libos/README
@@ -0,0 +1,15 @@
+
+- bisect.sh
+a sample script to bisect an issue of network stack code with the help
+of LibOS (and ns-3 network simulator). This was used to detect the issue
+for the following patch.
+
+http://patchwork.ozlabs.org/patch/436351/
+
+- dce-test.sh
+a test script invoked by 'make test ARCH=lib'. The contents of test
+scenario are implemented as test suites of ns-3 network simulator.
+
+- nuse-test.sh
+a simple test script for Network Stack in Userspace (NUSE).
+
diff --git a/tools/testing/libos/bisect.sh b/tools/testing/libos/bisect.sh
new file mode 100755
index 0000000..9377ac3
--- /dev/null
+++ b/tools/testing/libos/bisect.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+git merge origin/nuse --no-commit
+make clean ARCH=lib
+make library ARCH=lib OPT=no
+make test ARCH=lib ADD_PARAM=" -s dce-umip"
+RET=$?
+git reset --hard
+
+exit $RET
diff --git a/tools/testing/libos/dce-test.sh b/tools/testing/libos/dce-test.sh
new file mode 100755
index 0000000..e81e2d8
--- /dev/null
+++ b/tools/testing/libos/dce-test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+#set -x
+export LD_LOG=symbol-fail
+#VERBOSE="-v"
+VALGRIND=""
+FAULT_INJECTION=""
+
+if [ "$1" = "-g" ] ; then
+ VALGRIND="-g"
+# Not implemneted yet.
+#elif [ "$1" = "-f" ] ; then
+# FAULT_INJECTION="-f"
+fi
+
+# FIXME
+#export NS_ATTRIBUTE_DEFAULT='ns3::DceManagerHelper::LoaderFactory=ns3::\
+#DlmLoaderFactory[];ns3::TaskManager::FiberManagerType=UcontextFiberManager'
+
+cd buildtop/source/ns-3-dce
+LD_LIBRARY_PATH=${srctree} ./test.py -n ${VALGRIND} ${FAULT_INJECTION}\
+	   ${VERBOSE} ${ADD_PARAM}
diff --git a/tools/testing/libos/nuse-test.sh b/tools/testing/libos/nuse-test.sh
new file mode 100755
index 0000000..198e7e4
--- /dev/null
+++ b/tools/testing/libos/nuse-test.sh
@@ -0,0 +1,57 @@
+#!/bin/bash -e
+
+LIBOS_TOOLS=arch/lib/tools
+
+IFNAME=`ip route |grep default | awk '{print $5}'`
+GW=`ip route |grep default | awk '{print $3}'`
+#XXX
+IPADDR=`echo $GW | sed -r "s/([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)$/\1\`expr \2 + 10\`/"`
+
+# ip route
+# ip address
+# ip link
+
+NUSE_CONF=/tmp/nuse.conf
+
+cat > ${NUSE_CONF} << ENDCONF
+
+interface ${IFNAME}
+	address ${IPADDR}
+	netmask 255.255.255.0
+	macaddr 00:01:01:01:01:02
+	viftype RAW
+
+route
+	network 0.0.0.0
+	netmask 0.0.0.0
+	gateway ${GW}
+
+ENDCONF
+
+cd ${LIBOS_TOOLS}
+sudo NUSECONF=${NUSE_CONF} ./nuse ping 127.0.0.1 -c 2
+
+# rump test
+sudo NUSECONF=${NUSE_CONF} ./nuse sleep 5 &
+
+sleep 2
+PID_SLEEP=`/bin/ls -ltr /tmp/rump-server-nuse.* | tail -1 | awk '{print $9}' | sed -e "s/.*rump-server-nuse\.//g" | sed "s/=//"`
+RUMP_URL=unix:///tmp/rump-server-nuse.$PID_SLEEP
+# ls -ltr /tmp/*
+
+sudo chmod 777 /tmp/rump-server-nuse.$PID_SLEEP
+LD_PRELOAD=./libnuse-hijack.so  RUMPHIJACK=socket=all \
+    RUMP_SERVER=$RUMP_URL ip addr show
+
+wait %1
+
+if [ "$1" == "--extended" ] ; then
+sudo NUSECONF=${NUSE_CONF} ./nuse ping ${GW} -c 2
+sudo NUSECONF=${NUSE_CONF} ./nuse iperf -c ${GW} -p 2000 -t 3
+sudo NUSECONF=${NUSE_CONF} ./nuse iperf -c ${GW} -p 8 -u -t 3
+sudo NUSECONF=${NUSE_CONF} ./nuse dig www.google.com
+sudo NUSECONF=${NUSE_CONF} ./nuse host www.google.com
+sudo NUSECONF=${NUSE_CONF} ./nuse nslookup www.google.com
+#sudo NUSECONF=${NUSE_CONF} ./nuse nc www.google.com 80
+sudo NUSECONF=${NUSE_CONF} ./nuse wget www.google.com -O -
+fi
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (10 preceding siblings ...)
  2015-03-24 13:10 ` [RFC PATCH 11/11] lib: tools used for test scripts Hajime Tazaki
@ 2015-03-24 13:21 ` Richard Weinberger
  2015-03-24 14:25   ` Hajime Tazaki
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
  12 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-03-24 13:21 UTC (permalink / raw)
  To: Hajime Tazaki, linux-arch
  Cc: Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter, Jekka Enberg,
	Javid Rientjes, Joonsoo Kim, Jndrew Morton, linux-kernel,
	linux-doc, netdev, linux-mm, Jeff Dike, Rusty Russell,
	Mathieu Lacage

Am 24.03.2015 um 14:10 schrieb Hajime Tazaki:
 > == More information ==
> 
> The crucial difference between UML (user-mode linux) and this approach
> is that we allow multiple network stack instances to co-exist within a
> single process with dlmopen(3) like linking for easy debugging.

Is this the only difference?
We already have arch/um, why do you need arch/lib/ then?
My point is, can't you merge your arch/lib into the existing arch/um stuff?
>From a very rough look your arch/lib seems like a micro UML.

BTW: There was already an idea for having UML as regular library.
See: http://user-mode-linux.sourceforge.net/old/projects.html
"UML as a normal userspace library"

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 13:21 ` [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Richard Weinberger
@ 2015-03-24 14:25   ` Hajime Tazaki
  2015-03-24 14:32     ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 14:25 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


Hi,

thanks for your comment.

At Tue, 24 Mar 2015 14:21:49 +0100,
Richard Weinberger wrote:
> 
> Am 24.03.2015 um 14:10 schrieb Hajime Tazaki:
>  > == More information ==
> > 
> > The crucial difference between UML (user-mode linux) and this approach
> > is that we allow multiple network stack instances to co-exist within a
> > single process with dlmopen(3) like linking for easy debugging.
> 
> Is this the only difference?
> We already have arch/um, why do you need arch/lib/ then?
> My point is, can't you merge your arch/lib into the existing arch/um stuff?
> From a very rough look your arch/lib seems like a micro UML.

I understand your point.
but ptrace(2) based system call interception used by UML
makes it depend on the host OS (i.e., linux kernel), while
LibOS uses symbol hijacking with weak alias and LD_PRELOAD.

we're really thinking to run this library on other
POSIX-like hosts (e.g., osx) though it's not coming yet.

> BTW: There was already an idea for having UML as regular library.
> See: http://user-mode-linux.sourceforge.net/old/projects.html
> "UML as a normal userspace library"

thanks, it's new information for me.
were there any trial on this idea ?

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 14:25   ` Hajime Tazaki
@ 2015-03-24 14:32     ` Richard Weinberger
  2015-03-24 15:24       ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-03-24 14:32 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Am 24.03.2015 um 15:25 schrieb Hajime Tazaki:
> At Tue, 24 Mar 2015 14:21:49 +0100,
> Richard Weinberger wrote:
>>
>> Am 24.03.2015 um 14:10 schrieb Hajime Tazaki:
>>  > == More information ==
>>>
>>> The crucial difference between UML (user-mode linux) and this approach
>>> is that we allow multiple network stack instances to co-exist within a
>>> single process with dlmopen(3) like linking for easy debugging.
>>
>> Is this the only difference?
>> We already have arch/um, why do you need arch/lib/ then?
>> My point is, can't you merge your arch/lib into the existing arch/um stuff?
>> From a very rough look your arch/lib seems like a micro UML.
> 
> I understand your point.
> but ptrace(2) based system call interception used by UML
> makes it depend on the host OS (i.e., linux kernel), while
> LibOS uses symbol hijacking with weak alias and LD_PRELOAD.
> 
> we're really thinking to run this library on other
> POSIX-like hosts (e.g., osx) though it's not coming yet.

Yeah, but this does not mean that arch/um and arch/lib can't coexist in arch/um.
Maybe you can add a "library operation mode" to UML.
I'll happily help you in that area.

>> BTW: There was already an idea for having UML as regular library.
>> See: http://user-mode-linux.sourceforge.net/old/projects.html
>> "UML as a normal userspace library"
> 
> thanks, it's new information for me.
> were there any trial on this idea ?

IIRC Jeff (the original author of UML) wanted to create a special linker script
such that you can build UML as shared object.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 14:32     ` Richard Weinberger
@ 2015-03-24 15:24       ` Hajime Tazaki
  2015-03-24 15:27         ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-24 15:24 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


At Tue, 24 Mar 2015 15:32:05 +0100,
Richard Weinberger wrote:
> 
> Am 24.03.2015 um 15:25 schrieb Hajime Tazaki:
> > At Tue, 24 Mar 2015 14:21:49 +0100,
> > Richard Weinberger wrote:
> >>
> >> Am 24.03.2015 um 14:10 schrieb Hajime Tazaki:
> >>  > == More information ==
> >>>
> >>> The crucial difference between UML (user-mode linux) and this approach
> >>> is that we allow multiple network stack instances to co-exist within a
> >>> single process with dlmopen(3) like linking for easy debugging.
> >>
> >> Is this the only difference?
> >> We already have arch/um, why do you need arch/lib/ then?
> >> My point is, can't you merge your arch/lib into the existing arch/um stuff?
> >> From a very rough look your arch/lib seems like a micro UML.
> > 
> > I understand your point.
> > but ptrace(2) based system call interception used by UML
> > makes it depend on the host OS (i.e., linux kernel), while
> > LibOS uses symbol hijacking with weak alias and LD_PRELOAD.
> > 
> > we're really thinking to run this library on other
> > POSIX-like hosts (e.g., osx) though it's not coming yet.
> 
> Yeah, but this does not mean that arch/um and arch/lib can't coexist in arch/um.
> Maybe you can add a "library operation mode" to UML.
> I'll happily help you in that area.

I was thinking that such 'architectural' differences in core
idea (like system call handling, execution model, process
context design, etc) is better to have a different architecture
even if some part of the code is similar.

Isn't it also the same to the other 'hardware-dependent'
architectures' case like between arm and arm64 ?

of course I'm also happy to share the code between us,
especially _pure_ userspace part like (virtual) NIC with
tap or pcap because we also need that part, but we kept such
code at an external codebase (i.e., linux-libos-tools).

> >> BTW: There was already an idea for having UML as regular library.
> >> See: http://user-mode-linux.sourceforge.net/old/projects.html
> >> "UML as a normal userspace library"
> > 
> > thanks, it's new information for me.
> > were there any trial on this idea ?
> 
> IIRC Jeff (the original author of UML) wanted to create a special linker script
> such that you can build UML as shared object.

okay.

thanks.
-- Hajime


^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 15:24       ` Hajime Tazaki
@ 2015-03-24 15:27         ` Richard Weinberger
  2015-03-25 14:48           ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-03-24 15:27 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Am 24.03.2015 um 16:24 schrieb Hajime Tazaki:
> I was thinking that such 'architectural' differences in core
> idea (like system call handling, execution model, process
> context design, etc) is better to have a different architecture
> even if some part of the code is similar.
> 
> Isn't it also the same to the other 'hardware-dependent'
> architectures' case like between arm and arm64 ?
> 
> of course I'm also happy to share the code between us,
> especially _pure_ userspace part like (virtual) NIC with
> tap or pcap because we also need that part, but we kept such
> code at an external codebase (i.e., linux-libos-tools).

I'd say you should try hard to re-use/integrate your work in arch/um.
With um we already have an architecture which targets userspace,
having two needs a very good justification.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib
  2015-03-24 13:10 ` [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
@ 2015-03-24 16:13   ` Joe Perches
  2015-03-25 15:31     ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Joe Perches @ 2015-03-24 16:13 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Mathieu Lacage

On Tue, 2015-03-24 at 22:10 +0900, Hajime Tazaki wrote:
> libos (arch/lib) emulates a sysctl-like interface by a function call of
> userspace by enumerating sysctl tree from sysctl_table_root. It requires
> to be publicly accessible to this symbol and related functions.
[]
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
[]
> @@ -77,7 +77,7 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
>  }
>  
>  /* Called under sysctl_lock */
> -static struct ctl_table *find_entry(struct ctl_table_header **phead,
> +struct ctl_table *find_entry(struct ctl_table_header **phead,

find_entry and all of the <foo>_entry functions below it
are overly generic names.  Maybe prefix with ctl_table_



^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 15:27         ` Richard Weinberger
@ 2015-03-25 14:48           ` Hajime Tazaki
  2015-03-25 22:50             ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-25 14:48 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


At Tue, 24 Mar 2015 16:27:51 +0100,
Richard Weinberger wrote:
> 
> I'd say you should try hard to re-use/integrate your work in arch/um.
> With um we already have an architecture which targets userspace,
> having two needs a very good justification.

in addition to the case of my previous email, libos is not
limited to run on user-mode: it is just a library which can
be used with various programs. thus it has a potential (not
implemented yet) to run on a hypervisor like OSv or MirageOS
does for application containment, or run on a bare-metal
machine as rumpkernel does. We already have a clear
interface for the underlying layer to be able to add such
backend.

again, it's not only for user-mode.

mixing all the stuff in a single architecture may not only
mislead to users, but also introduce conceptual-disagreements
during code sharing of essential parts. 

I don't see any benefits to have a name 'um' with this idea.

# I'm not saying sharing a part of code is bad idea at all, btw.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib
  2015-03-24 16:13   ` Joe Perches
@ 2015-03-25 15:31     ` Hajime Tazaki
  0 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-25 15:31 UTC (permalink / raw)
  To: joe
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, richard,
	rusty, mathieu.lacage


At Tue, 24 Mar 2015 09:13:39 -0700,
Joe Perches wrote:
> 
> On Tue, 2015-03-24 at 22:10 +0900, Hajime Tazaki wrote:
> > libos (arch/lib) emulates a sysctl-like interface by a function call of
> > userspace by enumerating sysctl tree from sysctl_table_root. It requires
> > to be publicly accessible to this symbol and related functions.
> []
> > diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> []
> > @@ -77,7 +77,7 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
> >  }
> >  
> >  /* Called under sysctl_lock */
> > -static struct ctl_table *find_entry(struct ctl_table_header **phead,
> > +struct ctl_table *find_entry(struct ctl_table_header **phead,
> 
> find_entry and all of the <foo>_entry functions below it
> are overly generic names.  Maybe prefix with ctl_table_

agree.
I will address this in the next version of the patch.

thanks.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-25 14:48           ` Hajime Tazaki
@ 2015-03-25 22:50             ` Richard Weinberger
  2015-03-26 16:24               ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-03-25 22:50 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Hi!

Am 25.03.2015 um 15:48 schrieb Hajime Tazaki:
> 
> At Tue, 24 Mar 2015 16:27:51 +0100,
> Richard Weinberger wrote:
>>
>> I'd say you should try hard to re-use/integrate your work in arch/um.
>> With um we already have an architecture which targets userspace,
>> having two needs a very good justification.
> 
> in addition to the case of my previous email, libos is not
> limited to run on user-mode: it is just a library which can
> be used with various programs. thus it has a potential (not
> implemented yet) to run on a hypervisor like OSv or MirageOS
> does for application containment, or run on a bare-metal
> machine as rumpkernel does. We already have a clear
> interface for the underlying layer to be able to add such
> backend.
> 
> again, it's not only for user-mode.
> 
> mixing all the stuff in a single architecture may not only
> mislead to users, but also introduce conceptual-disagreements
> during code sharing of essential parts. 
> 
> I don't see any benefits to have a name 'um' with this idea.
> 
> # I'm not saying sharing a part of code is bad idea at all, btw.

After digging into the source I know what you mean and I have the
feeling that "lib" is the wrong name.
It has not much do to with an architecture.
Apart from that, I really like your idea!

You don't implement an architecture, you take some part of Linux
(the networking stack) and create stubs around it to make it work.
That means that we'd also have to duplicate kernel functions into
arch/lib to keep it running.

BTW: It does not build here:
---cut---
  LIB           liblinux-4.0.0-rc5.so
Cloning into 'arch/lib/tools'...
remote: Counting objects: 93, done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 93 (delta 9), reused 0 (delta 0), pack-reused 74
Receiving objects: 100% (93/93), 59.77 KiB | 0 bytes/s, done.
Resolving deltas: 100% (43/43), done.
Checking connectivity... done
  CC       nuse-fiber.o
  CC       nuse-vif.o
  CC       nuse-hostcalls.o
  CC       nuse-config.o
  CC       nuse-vif-rawsock.o
  CC       nuse-vif-tap.o
  CC       nuse-glue.o
  CC       nuse-vif-pipe.o
  CC       nuse.o
make[2]: *** No rule to make target `rump/lib/librumpuser/rumpuser_sp.c', needed by `rump/lib/librumpuser/rumpuser_sp.o'.  Stop.
make[2]: *** Waiting for unfinished jobs....
  CC       sim.o
  GEN      git-sparse
make[2]: *** No rule to make target `rump/lib/librumpclient/rumpclient.c', needed by `rump/lib/librumpclient/rumpclient.o'.  Stop.
make[1]: *** [librumpclient.so] Error 2
make[1]: *** Waiting for unfinished jobs....
nuse.c: In function 'nuse_dev_rx':
nuse.c:279:5: warning: unused variable 'hdr' [-Wunused-variable]
  } *hdr = (struct ethhdr *)buf;
     ^
make[1]: *** [librumpserver.so] Error 2
make: *** [arch/lib/tools] Error 2
---cut---

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-25 22:50             ` Richard Weinberger
@ 2015-03-26 16:24               ` Hajime Tazaki
  2015-03-26 18:55                 ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-26 16:24 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


Hi Richard,

At Wed, 25 Mar 2015 23:50:23 +0100,
Richard Weinberger wrote:
> 
> Hi!
> 
> Am 25.03.2015 um 15:48 schrieb Hajime Tazaki:
> > 
> > At Tue, 24 Mar 2015 16:27:51 +0100,
> > Richard Weinberger wrote:
> >>
> >> I'd say you should try hard to re-use/integrate your work in arch/um.
> >> With um we already have an architecture which targets userspace,
> >> having two needs a very good justification.
> > 
> > in addition to the case of my previous email, libos is not
> > limited to run on user-mode: it is just a library which can
> > be used with various programs. thus it has a potential (not
> > implemented yet) to run on a hypervisor like OSv or MirageOS
> > does for application containment, or run on a bare-metal
> > machine as rumpkernel does. We already have a clear
> > interface for the underlying layer to be able to add such
> > backend.
> > 
> > again, it's not only for user-mode.
> > 
> > mixing all the stuff in a single architecture may not only
> > mislead to users, but also introduce conceptual-disagreements
> > during code sharing of essential parts. 
> > 
> > I don't see any benefits to have a name 'um' with this idea.
> > 
> > # I'm not saying sharing a part of code is bad idea at all, btw.
> 
> After digging into the source I know what you mean and I have the

thank you for your deep review on the source code !

> feeling that "lib" is the wrong name.
> It has not much do to with an architecture.

could you care to elaborate your feeling more explicitly ?

what is an architecture here and what is _not_ an
architecture ? 
is UML an architecture in your sense (probably yes, but why)?

and what is arch/lib missing for an architecture ?

> Apart from that, I really like your idea!

great to hear that ;)

> You don't implement an architecture, you take some part of Linux
> (the networking stack) and create stubs around it to make it work.
> That means that we'd also have to duplicate kernel functions into
> arch/lib to keep it running.

again, the above same questions.

it (arch/lib) is a hardware-independent architecture which
provides necessary features to the remainder of kernel code,
isn't it ?

answers to those questions are really helpful for a feedback
on this RFC patches.

> BTW: It does not build here:
> ---cut---
>   LIB           liblinux-4.0.0-rc5.so

fixed, thanks: though the issue was in the external code
base (i.e., linux-libos-tools). there was a parallel build
(make -jX) problem.

# you may need to git pull at arch/lib/tools to reflect the updates.

thanks.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-26 16:24               ` Hajime Tazaki
@ 2015-03-26 18:55                 ` Richard Weinberger
  2015-03-27  3:31                   ` Rusty Russell
  2015-03-27  6:34                   ` Hajime Tazaki
  0 siblings, 2 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-03-26 18:55 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Hi!

Am 26.03.2015 um 17:24 schrieb Hajime Tazaki:
> thank you for your deep review on the source code !
> 
>> feeling that "lib" is the wrong name.
>> It has not much do to with an architecture.
> 
> could you care to elaborate your feeling more explicitly ?
> 
> what is an architecture here and what is _not_ an
> architecture ? 
> is UML an architecture in your sense (probably yes, but why)?

UML is an architecture as it binds the whole kernel to a computer
interface. Linux userspace in that case.

> and what is arch/lib missing for an architecture ?

Your arch/lib does not bind the Linux kernel to an interface.
It takes some part of Linux and duplicates kernel core subsystems
to make that part work on its own.
For example arch/lib contains a stub implementation of core VFS
functions like register_filesystem().
Also it does not seem to use the kernel scheduler, you have your own.

This also infers that arch/lib will be broken most of the time as
every time the networking stack references a new symbol it
has to be duplicated into arch/lib.

But this does not mean that your idea is bad, all I want to say that
I'm not sure whether arch/lib is the right approach.
Maybe Arnd has a better idea.

>> Apart from that, I really like your idea!
> 
> great to hear that ;)
> 
>> You don't implement an architecture, you take some part of Linux
>> (the networking stack) and create stubs around it to make it work.
>> That means that we'd also have to duplicate kernel functions into
>> arch/lib to keep it running.
> 
> again, the above same questions.
> 
> it (arch/lib) is a hardware-independent architecture which
> provides necessary features to the remainder of kernel code,
> isn't it ?

The stuff in arch/ is the code to glue the kernel to
a specific piece of hardware.
Your code does something between. You duplicate kernel core features
to make a specific piece of code work in userland.

> answers to those questions are really helpful for a feedback
> on this RFC patches.
> 
>> BTW: It does not build here:
>> ---cut---
>>   LIB           liblinux-4.0.0-rc5.so
> 
> fixed, thanks: though the issue was in the external code
> base (i.e., linux-libos-tools). there was a parallel build
> (make -jX) problem.
> 
> # you may need to git pull at arch/lib/tools to reflect the updates.

Will retry later.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-26 18:55                 ` Richard Weinberger
@ 2015-03-27  3:31                   ` Rusty Russell
  2015-03-27  3:49                     ` Geert Uytterhoeven
  2015-03-27  6:05                     ` Hajime Tazaki
  2015-03-27  6:34                   ` Hajime Tazaki
  1 sibling, 2 replies; 117+ messages in thread
From: Rusty Russell @ 2015-03-27  3:31 UTC (permalink / raw)
  To: Richard Weinberger, Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike,
	mathieu.lacage

Richard Weinberger <richard@nod.at> writes:
> This also infers that arch/lib will be broken most of the time as
> every time the networking stack references a new symbol it
> has to be duplicated into arch/lib.
>
> But this does not mean that your idea is bad, all I want to say that
> I'm not sure whether arch/lib is the right approach.
> Maybe Arnd has a better idea.

Exactly why I look forward to getting this in-tree.  Jeremy Kerr and I
wrote nfsim back in 2005(!) which stubbed around the netfilter
infrastructure; with failtest and valgrind it found some nasty bugs.  It
was too much hassle to maintain out-of-tree though :(

I look forward to a flood of great bugfixes from this work :)

Cheers,
Rusty.

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27  3:31                   ` Rusty Russell
@ 2015-03-27  3:49                     ` Geert Uytterhoeven
  2015-03-27  5:52                       ` Richard Weinberger
  2015-03-27  6:05                     ` Hajime Tazaki
  1 sibling, 1 reply; 117+ messages in thread
From: Geert Uytterhoeven @ 2015-03-27  3:49 UTC (permalink / raw)
  To: Rusty Russell
  Cc: Richard Weinberger, Hajime Tazaki, Linux-Arch, Arnd Bergmann,
	Jonathan Corbet, Christoph Lameter, Pekka Enberg, David Rientjes,
	Joonsoo Kim, Andrew Morton, linux-kernel, linux-doc, netdev,
	Linux MM, Jeff Dike, mathieu.lacage

On Fri, Mar 27, 2015 at 4:31 AM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> Richard Weinberger <richard@nod.at> writes:
>> This also infers that arch/lib will be broken most of the time as
>> every time the networking stack references a new symbol it
>> has to be duplicated into arch/lib.
>>
>> But this does not mean that your idea is bad, all I want to say that
>> I'm not sure whether arch/lib is the right approach.
>> Maybe Arnd has a better idea.
>
> Exactly why I look forward to getting this in-tree.  Jeremy Kerr and I
> wrote nfsim back in 2005(!) which stubbed around the netfilter
> infrastructure; with failtest and valgrind it found some nasty bugs.  It
> was too much hassle to maintain out-of-tree though :(
>
> I look forward to a flood of great bugfixes from this work :)

IIRC, the ability to run UML under valgrind was also one of its key features?
And that's not limited to networking.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27  3:49                     ` Geert Uytterhoeven
@ 2015-03-27  5:52                       ` Richard Weinberger
  0 siblings, 0 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-03-27  5:52 UTC (permalink / raw)
  To: Geert Uytterhoeven, Rusty Russell
  Cc: Hajime Tazaki, Linux-Arch, Arnd Bergmann, Jonathan Corbet,
	Christoph Lameter, Pekka Enberg, David Rientjes, Joonsoo Kim,
	Andrew Morton, linux-kernel, linux-doc, netdev, Linux MM,
	Jeff Dike, mathieu.lacage

Am 27.03.2015 um 04:49 schrieb Geert Uytterhoeven:
> On Fri, Mar 27, 2015 at 4:31 AM, Rusty Russell <rusty@rustcorp.com.au> wrote:
>> Richard Weinberger <richard@nod.at> writes:
>>> This also infers that arch/lib will be broken most of the time as
>>> every time the networking stack references a new symbol it
>>> has to be duplicated into arch/lib.
>>>
>>> But this does not mean that your idea is bad, all I want to say that
>>> I'm not sure whether arch/lib is the right approach.
>>> Maybe Arnd has a better idea.
>>
>> Exactly why I look forward to getting this in-tree.  Jeremy Kerr and I
>> wrote nfsim back in 2005(!) which stubbed around the netfilter
>> infrastructure; with failtest and valgrind it found some nasty bugs.  It
>> was too much hassle to maintain out-of-tree though :(
>>
>> I look forward to a flood of great bugfixes from this work :)
> 
> IIRC, the ability to run UML under valgrind was also one of its key features?
> And that's not limited to networking.

Sadly this feature went never mainline. You needed a rather invading patch
for both Linux and valgrind.

But now with KASan we have a much more powerful feature to find issues.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27  3:31                   ` Rusty Russell
  2015-03-27  3:49                     ` Geert Uytterhoeven
@ 2015-03-27  6:05                     ` Hajime Tazaki
  1 sibling, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-27  6:05 UTC (permalink / raw)
  To: rusty
  Cc: richard, linux-arch, arnd, corbet, cl, penberg, rientjes,
	iamjoonsoo.kim, akpm, linux-kernel, linux-doc, netdev, linux-mm,
	jdike, mathieu.lacage


Hi Rusty,

At Fri, 27 Mar 2015 14:01:22 +1030,
Rusty Russell wrote:
> 
> Richard Weinberger <richard@nod.at> writes:
> > This also infers that arch/lib will be broken most of the time as
> > every time the networking stack references a new symbol it
> > has to be duplicated into arch/lib.
> >
> > But this does not mean that your idea is bad, all I want to say that
> > I'm not sure whether arch/lib is the right approach.
> > Maybe Arnd has a better idea.
> 
> Exactly why I look forward to getting this in-tree.  Jeremy Kerr and I
> wrote nfsim back in 2005(!) which stubbed around the netfilter
> infrastructure; with failtest and valgrind it found some nasty bugs.  It
> was too much hassle to maintain out-of-tree though :(

we're aware of (and respected ;)) nfsim, and expanded the
idea with DCE: make test ARCH=lib gives a broad testsuite
for network stack. 

# we also have
  make {test-valgrind, test-fault-injection} ARCH=lib
 but not well tested (of the options themselves) yet.

there are the overview of test facility in my slides (the
link is in my original cover letter email)

> I look forward to a flood of great bugfixes from this work :)

it has not been so much, but the following fix for xfrm
regression was detected by this framework (through jenkins
CI). git bisect is also easy (see tools/testing/libos/bisect.sh).

http://patchwork.ozlabs.org/patch/436351/

thanks for the comment.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-26 18:55                 ` Richard Weinberger
  2015-03-27  3:31                   ` Rusty Russell
@ 2015-03-27  6:34                   ` Hajime Tazaki
  2015-03-27  9:21                     ` Richard Weinberger
  1 sibling, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-27  6:34 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


Hi Richard,

At Thu, 26 Mar 2015 19:55:06 +0100,
Richard Weinberger wrote:

> >> feeling that "lib" is the wrong name.
> >> It has not much do to with an architecture.
> > 
> > could you care to elaborate your feeling more explicitly ?
> > 
> > what is an architecture here and what is _not_ an
> > architecture ? 
> > is UML an architecture in your sense (probably yes, but why)?
> 
> UML is an architecture as it binds the whole kernel to a computer
> interface. Linux userspace in that case.
> 
> > and what is arch/lib missing for an architecture ?
> 
> Your arch/lib does not bind the Linux kernel to an interface.
> It takes some part of Linux and duplicates kernel core subsystems
> to make that part work on its own.
> For example arch/lib contains a stub implementation of core VFS
> functions like register_filesystem().
> Also it does not seem to use the kernel scheduler, you have your own.

the scheduler is the part of which a library user (NUSE or
DCE) should implement.

> This also infers that arch/lib will be broken most of the time as
> every time the networking stack references a new symbol it
> has to be duplicated into arch/lib.
> 
> But this does not mean that your idea is bad, all I want to say that
> I'm not sure whether arch/lib is the right approach.
> Maybe Arnd has a better idea.

one way to avoid the duplication is: to put our
libos-specific implementation to the kernel core
subsystem. Maybe this will introduce a bunch of #ifdefs
(ifdef CONFIG_LIB) into cores, which I don't know it's okay
or not.

for example, add_timer() is implemented in arch/lib/timer.c
while in kernel/time/timer.c in kernel core.

# [04/11] to [08/11] of my RFC patches are these parts.

We've been implemented these stubs (we call 'kernel glue
code') into arch/lib because 1) we were in out-of-tree and
2) this won't disturb kernel core.


OTOH, [03/11] (and [09/11] and [10/11]) is an original part
of libos, which probably have no conflict (in terms of the
concept) to the others. I'm still thinking arch/lib is an
appropriate place.


> >> You don't implement an architecture, you take some part of Linux
> >> (the networking stack) and create stubs around it to make it work.
> >> That means that we'd also have to duplicate kernel functions into
> >> arch/lib to keep it running.
> > 
> > again, the above same questions.
> > 
> > it (arch/lib) is a hardware-independent architecture which
> > provides necessary features to the remainder of kernel code,
> > isn't it ?
> 
> The stuff in arch/ is the code to glue the kernel to
> a specific piece of hardware.
> Your code does something between. You duplicate kernel core features
> to make a specific piece of code work in userland.

indeed, 'something between' would be an appropriate word.

thank you for your comment.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27  6:34                   ` Hajime Tazaki
@ 2015-03-27  9:21                     ` Richard Weinberger
  2015-03-27 15:17                       ` Antti Kantee
  2015-03-29 15:06                       ` Hajime Tazaki
  0 siblings, 2 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-03-27  9:21 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Am 27.03.2015 um 07:34 schrieb Hajime Tazaki:
>>> it (arch/lib) is a hardware-independent architecture which
>>> provides necessary features to the remainder of kernel code,
>>> isn't it ?
>>
>> The stuff in arch/ is the code to glue the kernel to
>> a specific piece of hardware.
>> Your code does something between. You duplicate kernel core features
>> to make a specific piece of code work in userland.
> 
> indeed, 'something between' would be an appropriate word.

Just an idea popping out of my head...

What about putting libos into tools/testing/ and make it much more generic and framework alike.
With more generic I mean that libos could be a stubbing framework for the kernel.
i.e. you specify the subsystem you want to test/stub and the framework helps you doing so.
A lot of the stubs you're placing in arch/lib could be auto-generated as the
vast majority of all kernel methods you stub are no-ops which call only lib_assert(false).

Using that approach only very few kernel core components have to be duplicated and
actually implemented by hand.
Hence, less maintenance overhead and libos is not broken all the time.

What do you think?

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27  9:21                     ` Richard Weinberger
@ 2015-03-27 15:17                       ` Antti Kantee
  2015-03-28 21:17                         ` Richard Weinberger
  2015-03-29 15:06                       ` Hajime Tazaki
  1 sibling, 1 reply; 117+ messages in thread
From: Antti Kantee @ 2015-03-27 15:17 UTC (permalink / raw)
  To: Richard Weinberger, Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev

On 27/03/15 09:21, Richard Weinberger wrote:
> Am 27.03.2015 um 07:34 schrieb Hajime Tazaki:
>>>> it (arch/lib) is a hardware-independent architecture which
>>>> provides necessary features to the remainder of kernel code,
>>>> isn't it ?
>>>
>>> The stuff in arch/ is the code to glue the kernel to
>>> a specific piece of hardware.
>>> Your code does something between. You duplicate kernel core features
>>> to make a specific piece of code work in userland.
>>
>> indeed, 'something between' would be an appropriate word.
>
> Just an idea popping out of my head...

Let me try to offer some insight.  I've been working on something 
similar in mainline NetBSD for almost 8 years now, so in addition to 
ideas popping into my head I've also tested them out in the real world. 
  I do think that all operating systems should be structured to support 
a lib mode, and hopefully integrating Hajime's work into Linux will get 
on the right track.

> What about putting libos into tools/testing/ and make it much more generic and framework alike.
> With more generic I mean that libos could be a stubbing framework for the kernel.
> i.e. you specify the subsystem you want to test/stub and the framework helps you doing so.
> A lot of the stubs you're placing in arch/lib could be auto-generated as the
> vast majority of all kernel methods you stub are no-ops which call only lib_assert(false).
>
> Using that approach only very few kernel core components have to be duplicated and
> actually implemented by hand.
> Hence, less maintenance overhead and libos is not broken all the time.

Stubbing things might be the way to get things initially rolling, but 
you don't want to aim for that or spend energy on fancy ways to do it. 
Autogenerating stubs only means that the libos will build, not that it 
won't be broken.  Figuring out how to make the libos as close to 
zero-maintenance as possible is indeed the trick.

What I ended up doing is coining the term "anykernel architecture", 
which simply means that in addition to the monolithic architecture, the 
kernel can now be used as in exokernel, microkernel, multikernel, etc. 
(which are really just different frontends for the lib mode).  I'd 
recommend diving head-first into the issue and thinking "how can we 
adjust the kernel architecture to support the libos mode" instead of 
"how can we tip-toe around the kernel and invent clever ways to stub 
things".  The anykernel is not really that different from a monolithic 
kernel once you figure out which bits are important, and support will 
not require a whole lot of "duplicated" code.  There are practically no 
stubs in the NetBSD implementation; somewhere between 0 and 20 depending 
on what you count as a stub.  There is a few thousand lines of 
"duplicated" code, the majority of which is a direct result of the rump 
kernel (which is the name of the libos mode) running on top of an 
external thread scheduler, so that code from the monolithic kernel 
doesn't apply.

Continuous testing is paramount.  Running the kernel as a lib provides 
an unparalleled method for testing most of the kernel.  It will improve 
testing capabilities dramatically, and on the flipside it will keep the 
libos working.  Everyone wins.

   - antti

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27 15:17                       ` Antti Kantee
@ 2015-03-28 21:17                         ` Richard Weinberger
  2015-03-29 15:36                           ` Hajime Tazaki
  2015-03-29 16:59                           ` Antti Kantee
  0 siblings, 2 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-03-28 21:17 UTC (permalink / raw)
  To: Antti Kantee, Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev

Am 27.03.2015 um 16:17 schrieb Antti Kantee:
> Let me try to offer some insight.  I've been working on something similar in mainline NetBSD for almost 8 years now, so in addition to ideas popping into my head I've also tested
> them out in the real world.  I do think that all operating systems should be structured to support a lib mode, and hopefully integrating Hajime's work into Linux will get on the
> right track.

IMHO it depends on the maintenance burden.
Linux source changes magnitudes faster than NetBSD's.

>> What about putting libos into tools/testing/ and make it much more generic and framework alike.
>> With more generic I mean that libos could be a stubbing framework for the kernel.
>> i.e. you specify the subsystem you want to test/stub and the framework helps you doing so.
>> A lot of the stubs you're placing in arch/lib could be auto-generated as the
>> vast majority of all kernel methods you stub are no-ops which call only lib_assert(false).
>>
>> Using that approach only very few kernel core components have to be duplicated and
>> actually implemented by hand.
>> Hence, less maintenance overhead and libos is not broken all the time.
> 
> Stubbing things might be the way to get things initially rolling, but you don't want to aim for that or spend energy on fancy ways to do it. Autogenerating stubs only means that
> the libos will build, not that it won't be broken.  Figuring out how to make the libos as close to zero-maintenance as possible is indeed the trick.
> 
> What I ended up doing is coining the term "anykernel architecture", which simply means that in addition to the monolithic architecture, the kernel can now be used as in exokernel,
> microkernel, multikernel, etc. (which are really just different frontends for the lib mode).  I'd recommend diving head-first into the issue and thinking "how can we adjust the
> kernel architecture to support the libos mode" instead of "how can we tip-toe around the kernel and invent clever ways to stub things".  The anykernel is not really that different
> from a monolithic kernel once you figure out which bits are important, and support will not require a whole lot of "duplicated" code.  There are practically no stubs in the NetBSD
> implementation; somewhere between 0 and 20 depending on what you count as a stub.  There is a few thousand lines of "duplicated" code, the majority of which is a direct result of
> the rump kernel (which is the name of the libos mode) running on top of an external thread scheduler, so that code from the monolithic kernel doesn't apply.

I agree that this would be nice but without actual patches I'm very doubtful.

> Continuous testing is paramount.  Running the kernel as a lib provides an unparalleled method for testing most of the kernel.  It will improve testing capabilities dramatically,
> and on the flipside it will keep the libos working.  Everyone wins.

If it can be done cheap, yes. But our in-kernel tests improved over the years a lot.
Now have lockdep, KASan, kmemleak, etc. to find *real-world* issues and the need for stubbed testing
decreases.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-27  9:21                     ` Richard Weinberger
  2015-03-27 15:17                       ` Antti Kantee
@ 2015-03-29 15:06                       ` Hajime Tazaki
  2015-03-30  6:41                         ` Richard Weinberger
  2015-04-01  1:29                         ` Rusty Russell
  1 sibling, 2 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-29 15:06 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


Hi Richard,

At Fri, 27 Mar 2015 10:21:59 +0100,
Richard Weinberger wrote:

> Just an idea popping out of my head...
> 
> What about putting libos into tools/testing/ and make it much more generic and framework alike.

it's trivial though, libos is not only for the testing (i.e., NUSE).
# of course tools/libos or something can be the place.

> With more generic I mean that libos could be a stubbing framework for the kernel.
> i.e. you specify the subsystem you want to test/stub and the framework helps you doing so.
> A lot of the stubs you're placing in arch/lib could be auto-generated as the
> vast majority of all kernel methods you stub are no-ops which call only lib_assert(false).

the issue here is the decision between 'no-ops' and
'assert(false)' depends on the context. an auto-generated
mechanism needs some hand-written parameters I think.

one more concern on the out-of-arch-tree design is that how
to handle our asm-generic-based header files
(arch/lib/include/asm). we have been heavily used
'generic-y' in the Kbuild file to reuse header files.

OTOH, I agree with you on the point of auto-generated glues
(stubs), or trying to avoid glues (reuse the originals as
much as possible) as Antti mentioned. that will definitely
be reduce the amount of maintenance effort.


-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-28 21:17                         ` Richard Weinberger
@ 2015-03-29 15:36                           ` Hajime Tazaki
  2015-03-29 16:47                             ` Richard Weinberger
  2015-03-29 16:59                           ` Antti Kantee
  1 sibling, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-29 15:36 UTC (permalink / raw)
  To: richard
  Cc: pooka, linux-arch, arnd, corbet, cl, penberg, rientjes,
	iamjoonsoo.kim, akpm, linux-kernel, linux-doc, netdev



At Sat, 28 Mar 2015 22:17:40 +0100,
Richard Weinberger wrote:

> > Continuous testing is paramount.  Running the kernel as
> > a lib provides an unparalleled method for testing most of
> > the kernel.  It will improve testing capabilities
> > dramatically,
> > and on the flipside it will keep the libos working.
> > Everyone wins.
> 
> If it can be done cheap, yes. But our in-kernel tests improved over the years a lot.
> Now have lockdep, KASan, kmemleak, etc. to find *real-world* issues and the need for stubbed testing
> decreases.

let me take the same example I raised.

- Patchwork [net-next] xfrm6: Fix a offset value for network header in _decode_session6
http://patchwork.ozlabs.org/patch/436351/

without stubbed testing (I didn't know this term btw), we
can't decrease untested paths of the code.

the above bug is for Mobile IPv6, which not so many people
are using though, but it's certainly a regression for a
person.

testing framework with libos is based on a network
simulator, with a slight decreased realism (but it can
detect a real bug !), but provides a lightweight multi-node
testing framework with a single test scenario script to
control over the nodes.

it doesn't require heavyweight machines nor complex cabling
for a bunch of tests.

even a framework is not cheap, I would use such a testing
tool IF we can improve the code. plus (as you may know), it
certainly reduces the maintenance effort once it's automated.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-29 15:36                           ` Hajime Tazaki
@ 2015-03-29 16:47                             ` Richard Weinberger
  0 siblings, 0 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-03-29 16:47 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: pooka, linux-arch, arnd, corbet, cl, penberg, rientjes,
	iamjoonsoo.kim, akpm, linux-kernel, linux-doc, netdev

Am 29.03.2015 um 17:36 schrieb Hajime Tazaki:
> 
> 
> At Sat, 28 Mar 2015 22:17:40 +0100,
> Richard Weinberger wrote:
> 
>>> Continuous testing is paramount.  Running the kernel as
>>> a lib provides an unparalleled method for testing most of
>>> the kernel.  It will improve testing capabilities
>>> dramatically,
>>> and on the flipside it will keep the libos working.
>>> Everyone wins.
>>
>> If it can be done cheap, yes. But our in-kernel tests improved over the years a lot.
>> Now have lockdep, KASan, kmemleak, etc. to find *real-world* issues and the need for stubbed testing
>> decreases.
> 
> let me take the same example I raised.
> 
> - Patchwork [net-next] xfrm6: Fix a offset value for network header in _decode_session6
> http://patchwork.ozlabs.org/patch/436351/
> 
> without stubbed testing (I didn't know this term btw), we
> can't decrease untested paths of the code.
> 
> the above bug is for Mobile IPv6, which not so many people
> are using though, but it's certainly a regression for a
> person.
> 
> testing framework with libos is based on a network
> simulator, with a slight decreased realism (but it can
> detect a real bug !), but provides a lightweight multi-node
> testing framework with a single test scenario script to
> control over the nodes.
> 
> it doesn't require heavyweight machines nor complex cabling
> for a bunch of tests.
> 
> even a framework is not cheap, I would use such a testing
> tool IF we can improve the code. plus (as you may know), it
> certainly reduces the maintenance effort once it's automated.

Don't get me wrong, I totally agree that this kind of testing is good.
But as I said before we have to keep the maintenance burden in mind.

Let's wait a bit what Arnd says. He is the Linux arch maintainer.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-28 21:17                         ` Richard Weinberger
  2015-03-29 15:36                           ` Hajime Tazaki
@ 2015-03-29 16:59                           ` Antti Kantee
  2015-03-29 18:05                             ` Richard Weinberger
  1 sibling, 1 reply; 117+ messages in thread
From: Antti Kantee @ 2015-03-29 16:59 UTC (permalink / raw)
  To: Richard Weinberger, Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev

On 28/03/15 21:17, Richard Weinberger wrote:
> Am 27.03.2015 um 16:17 schrieb Antti Kantee:
>> Let me try to offer some insight.  I've been working on something similar in mainline NetBSD for almost 8 years now, so in addition to ideas popping into my head I've also tested
>> them out in the real world.  I do think that all operating systems should be structured to support a lib mode, and hopefully integrating Hajime's work into Linux will get on the
>> right track.
>
> IMHO it depends on the maintenance burden.
> Linux source changes magnitudes faster than NetBSD's.

I can understand why you're worried about maintenance burden -- believe 
me, I've heard all the excuses before, starting all the way back from 
"it's impossible".  Let's dissect your concern.

There's a reason I wrote in my original mail: "Figuring out how to make 
the libos as close to zero-maintenance as possible is indeed the trick". 
  It took me a few weeks to make things work in my version, but it took 
four years to figure out how to make things as maintainable as I could 
figure out how to make them.  The good news is that the results of those 
four years are more or less generic and independent of OS.

The source may change an order of magnitude faster in Linux, but Linux 
also has several orders of magnitude more resources.  Even if you do not 
believe that available resources are relevant in the equation, you can 
still take the data from NetBSD, multiply the maintenance burden with 
any Stetson-Harrison constant you see fit, and have your expected Linux 
maintenance burden value.

Mind game: what if I were to assert that the maintenance burden of 
application compatibility is too high on Linux compared to NetBSD due to 
the high rate of change?  I think everyone would rush to tell me that 
I'm wrong...

So why not just evaluate Hajime et al's work for its functional merits 
and immediate benefits, and see how maintenance burden plays out by 
collecting actual data on it.

   - antti

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-29 16:59                           ` Antti Kantee
@ 2015-03-29 18:05                             ` Richard Weinberger
  0 siblings, 0 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-03-29 18:05 UTC (permalink / raw)
  To: Antti Kantee, Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev

Am 29.03.2015 um 18:59 schrieb Antti Kantee:
> On 28/03/15 21:17, Richard Weinberger wrote:
>> Am 27.03.2015 um 16:17 schrieb Antti Kantee:
>>> Let me try to offer some insight.  I've been working on something similar in mainline NetBSD for almost 8 years now, so in addition to ideas popping into my head I've also tested
>>> them out in the real world.  I do think that all operating systems should be structured to support a lib mode, and hopefully integrating Hajime's work into Linux will get on the
>>> right track.
>>
>> IMHO it depends on the maintenance burden.
>> Linux source changes magnitudes faster than NetBSD's.
> 
> I can understand why you're worried about maintenance burden -- believe me, I've heard all the excuses before, starting all the way back from "it's impossible".  Let's dissect your
> concern.
> 
> There's a reason I wrote in my original mail: "Figuring out how to make the libos as close to zero-maintenance as possible is indeed the trick".  It took me a few weeks to make
> things work in my version, but it took four years to figure out how to make things as maintainable as I could figure out how to make them.  The good news is that the results of
> those four years are more or less generic and independent of OS.
> 
> The source may change an order of magnitude faster in Linux, but Linux also has several orders of magnitude more resources.  Even if you do not believe that available resources are
> relevant in the equation, you can still take the data from NetBSD, multiply the maintenance burden with any Stetson-Harrison constant you see fit, and have your expected Linux
> maintenance burden value.
> 
> Mind game: what if I were to assert that the maintenance burden of application compatibility is too high on Linux compared to NetBSD due to the high rate of change?  I think
> everyone would rush to tell me that I'm wrong...

There is no need for mind games. Patches talk. :)

> So why not just evaluate Hajime et al's work for its functional merits and immediate benefits, and see how maintenance burden plays out by collecting actual data on it.

Hajime's work is currently under evaluation. Guess what we're doing right now?

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 08/11] lib: other kernel glue layer code
  2015-03-24 13:10 ` [RFC PATCH 08/11] lib: other kernel glue layer code Hajime Tazaki
@ 2015-03-29 18:17   ` Richard Weinberger
  2015-03-31  7:36     ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-03-29 18:17 UTC (permalink / raw)
  To: Hajime Tazaki, linux-arch
  Cc: Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter, Jekka Enberg,
	Javid Rientjes, Joonsoo Kim, Jndrew Morton, linux-kernel,
	linux-doc, netdev, linux-mm, Jeff Dike, Rusty Russell,
	Mathieu Lacage, Christoph Paasch

Am 24.03.2015 um 14:10 schrieb Hajime Tazaki:
> These files are used to provide the same function calls so that other
> network stack code keeps untouched.
> 
> Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
> Signed-off-by: Christoph Paasch <christoph.paasch@gmail.com>
> ---
>  arch/lib/cred.c     |  16 +++
>  arch/lib/dcache.c   |  93 +++++++++++++++
>  arch/lib/filemap.c  |  27 +++++
>  arch/lib/fs.c       | 287 ++++++++++++++++++++++++++++++++++++++++++++
>  arch/lib/glue.c     | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  arch/lib/inode.c    | 146 +++++++++++++++++++++++
>  arch/lib/modules.c  |  36 ++++++
>  arch/lib/pid.c      |  29 +++++
>  arch/lib/print.c    |  56 +++++++++
>  arch/lib/proc.c     | 164 +++++++++++++++++++++++++
>  arch/lib/random.c   |  53 +++++++++
>  arch/lib/security.c |  45 +++++++
>  arch/lib/seq.c      | 122 +++++++++++++++++++
>  arch/lib/splice.c   |  20 ++++
>  arch/lib/super.c    | 210 ++++++++++++++++++++++++++++++++
>  arch/lib/sysfs.c    |  83 +++++++++++++
>  arch/lib/vmscan.c   |  26 ++++
>  17 files changed, 1749 insertions(+)

BTW: Why do you need these stub implementations at all?
If I read your code correctly it is because you're linking against the whole net/ directory.
Let's take register_filesystem() again as example. net/socket.c references it in sock_init().
Maybe it would make sense to split socket.c into two files, net/socket.c and net/sockfs.c.
Such that you could link only net/socket.o.
Of course you'd have to convince networking folks first. :D

By linking selectively objects files from net/ you could get rid of a lot unneeded stubs.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-29 15:06                       ` Hajime Tazaki
@ 2015-03-30  6:41                         ` Richard Weinberger
  2015-03-31  7:47                           ` Hajime Tazaki
  2015-04-01  1:29                         ` Rusty Russell
  1 sibling, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-03-30  6:41 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Am 29.03.2015 um 17:06 schrieb Hajime Tazaki:
>> What about putting libos into tools/testing/ and make it much more generic and framework alike.
> 
> it's trivial though, libos is not only for the testing (i.e., NUSE).
> # of course tools/libos or something can be the place.

Yep, tool/libos is also perfectly fine.

>> With more generic I mean that libos could be a stubbing framework for the kernel.
>> i.e. you specify the subsystem you want to test/stub and the framework helps you doing so.
>> A lot of the stubs you're placing in arch/lib could be auto-generated as the
>> vast majority of all kernel methods you stub are no-ops which call only lib_assert(false).
> 
> the issue here is the decision between 'no-ops' and
> 'assert(false)' depends on the context. an auto-generated
> mechanism needs some hand-written parameters I think.

The questions is, why do you need stubs which are a no-op but not a
lib_assert(false).
Sounds more like these dependencies shouldn't be linked at all.
Same applies to lib_assert(false) stubs. If they must not get
called from libos better try hard to avoid these dependencies at all.

> one more concern on the out-of-arch-tree design is that how
> to handle our asm-generic-based header files
> (arch/lib/include/asm). we have been heavily used
> 'generic-y' in the Kbuild file to reuse header files.

As noted before, libos is something in between. Maybe the asm-generic
stuff needs some modifications to make it work for libos.

> OTOH, I agree with you on the point of auto-generated glues
> (stubs), or trying to avoid glues (reuse the originals as
> much as possible) as Antti mentioned. that will definitely
> be reduce the amount of maintenance effort.

BTW: There is something really fishy wrt to your build process.
I did a ARCH=i386 build due to my regular kernel work and later a ARCH=lib build.
It seems to pickup old/unrelated object files.
After a make clean ARCH=i386 it build fine.

---cut---
  LIB           liblinux-4.0.0-rc5.so
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: Warning: size of symbol `skb_copy_bits' changed from 10 in ./kernel/bpf/core.o to 441 in ./net/core/skbuff.o
./net/ipv6/fib6_rules.o: In function `fib6_rule_lookup':
/home/rw/linux/net/ipv6/fib6_rules.c:34: multiple definition of `fib6_rule_lookup'
./net/ipv6/ip6_fib.o:ip6_fib.c:(.text+0xd50): first defined here
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/sysctl.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/params.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/notifier.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/time/time.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/rcu/update.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/locking/mutex.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/locking/semaphore.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/locking/rwsem.o' is incompatible with i386:x86-64 output
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: i386 architecture of input file `./kernel/bpf/core.o' is incompatible with i386:x86-64 output
[...]
./kernel/rcu/update.o:(.ref.data+0x20): undefined reference to `trace_event_raw_init'
collect2: error: ld returned 1 exit status
arch/lib/Makefile:223: recipe for target 'liblinux-4.0.0-rc5.so' failed
make: *** [liblinux-4.0.0-rc5.so] Error 1
---cut---

While we're talking about the build process, how can I cross build libos?
Say a i386 libos on x86_64. For UML we have use SUBARCH.
i.e. make linux ARCH=um SUBARCH=i386

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 08/11] lib: other kernel glue layer code
  2015-03-29 18:17   ` Richard Weinberger
@ 2015-03-31  7:36     ` Hajime Tazaki
  2015-04-03  1:24       ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-31  7:36 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage, christoph.paasch


Hi Richard,

thanks again.

At Sun, 29 Mar 2015 20:17:02 +0200,
Richard Weinberger wrote:
> 
> Am 24.03.2015 um 14:10 schrieb Hajime Tazaki:
> > These files are used to provide the same function calls so that other
> > network stack code keeps untouched.
> > 
> > Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
> > Signed-off-by: Christoph Paasch <christoph.paasch@gmail.com>
> > ---
> >  arch/lib/cred.c     |  16 +++
> >  arch/lib/dcache.c   |  93 +++++++++++++++
> >  arch/lib/filemap.c  |  27 +++++
> >  arch/lib/fs.c       | 287 ++++++++++++++++++++++++++++++++++++++++++++
> >  arch/lib/glue.c     | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  arch/lib/inode.c    | 146 +++++++++++++++++++++++
> >  arch/lib/modules.c  |  36 ++++++
> >  arch/lib/pid.c      |  29 +++++
> >  arch/lib/print.c    |  56 +++++++++
> >  arch/lib/proc.c     | 164 +++++++++++++++++++++++++
> >  arch/lib/random.c   |  53 +++++++++
> >  arch/lib/security.c |  45 +++++++
> >  arch/lib/seq.c      | 122 +++++++++++++++++++
> >  arch/lib/splice.c   |  20 ++++
> >  arch/lib/super.c    | 210 ++++++++++++++++++++++++++++++++
> >  arch/lib/sysfs.c    |  83 +++++++++++++
> >  arch/lib/vmscan.c   |  26 ++++
> >  17 files changed, 1749 insertions(+)
> 
> BTW: Why do you need these stub implementations at all?
> If I read your code correctly it is because you're linking against the whole net/ directory.
> Let's take register_filesystem() again as example. net/socket.c references it in sock_init().
> Maybe it would make sense to split socket.c into two files, net/socket.c and net/sockfs.c.
> Such that you could link only net/socket.o.
> Of course you'd have to convince networking folks first. :D

this is something that we've been avoided: we weren't able
to estimate how much such splits will expand.

> By linking selectively objects files from net/ you could get rid of a lot unneeded stubs.

now I'm trying to minimize those stubs by reusing the original
codes (i.e., fs/filesystems.c for register_filesystem()). I
will let you know once I've done (maybe v2 RFC if you think
it's better ?)

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-30  6:41                         ` Richard Weinberger
@ 2015-03-31  7:47                           ` Hajime Tazaki
  2015-04-09  8:36                             ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-03-31  7:47 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


At Mon, 30 Mar 2015 08:41:52 +0200,
Richard Weinberger wrote:

> > one more concern on the out-of-arch-tree design is that how
> > to handle our asm-generic-based header files
> > (arch/lib/include/asm). we have been heavily used
> > 'generic-y' in the Kbuild file to reuse header files.
> 
> As noted before, libos is something in between. Maybe the asm-generic
> stuff needs some modifications to make it work for libos.

okay.

> BTW: There is something really fishy wrt to your build process.
> I did a ARCH=i386 build due to my regular kernel work and later a ARCH=lib build.
> It seems to pickup old/unrelated object files.
> After a make clean ARCH=i386 it build fine.
> 
> ---cut---
>   LIB           liblinux-4.0.0-rc5.so
> /usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: Warning: size of symbol `skb_copy_bits' changed from 10 in ./kernel/bpf/core.o to 441 in ./net/core/skbuff.o
> ./net/ipv6/fib6_rules.o: In function `fib6_rule_lookup':
> /home/rw/linux/net/ipv6/fib6_rules.c:34: multiple definition of `fib6_rule_lookup'
(snip)

right now arch/lib/Makefile isn't fully on the Kbuild
system: build file dependency is not tracked at all.

while I should learn more about Kbuild, I'd be happy if you
would suggest how the Makefile should be.

> ---cut---
> 
> While we're talking about the build process, how can I cross build libos?
> Say a i386 libos on x86_64. For UML we have use SUBARCH.
> i.e. make linux ARCH=um SUBARCH=i386

the cross build is not either implemented. if libos needs it,
I'd start to think about the design: maybe SUBARCH-like
mechanism is required.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-29 15:06                       ` Hajime Tazaki
  2015-03-30  6:41                         ` Richard Weinberger
@ 2015-04-01  1:29                         ` Rusty Russell
  2015-04-03  1:43                           ` Hajime Tazaki
  1 sibling, 1 reply; 117+ messages in thread
From: Rusty Russell @ 2015-04-01  1:29 UTC (permalink / raw)
  To: Hajime Tazaki, richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike,
	mathieu.lacage

Hajime Tazaki <tazaki@sfc.wide.ad.jp> writes:
> the issue here is the decision between 'no-ops' and
> 'assert(false)' depends on the context. an auto-generated
> mechanism needs some hand-written parameters I think.

Yes, I used auto-generated (fprintf, abort) stubs for similar testing in
pettycoin, where if it failed to link it would generate such stubs
for undefined symbols.

It's not a panacea, but it helps speed up rejiggin after code changes.
Generating noop stubs can actually make that process slower, as you can
get failures because you now need to do something in that stub.

> one more concern on the out-of-arch-tree design is that how
> to handle our asm-generic-based header files
> (arch/lib/include/asm). we have been heavily used
> 'generic-y' in the Kbuild file to reuse header files.

Yeah, the arch trick is clever.

Cheers,
Rusty.

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 08/11] lib: other kernel glue layer code
  2015-03-31  7:36     ` Hajime Tazaki
@ 2015-04-03  1:24       ` Hajime Tazaki
  0 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-03  1:24 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage, christoph.paasch


Hi Richard,

At Tue, 31 Mar 2015 16:36:55 +0900,
Hajime Tazaki wrote:

> now I'm trying to minimize those stubs by reusing the original
> codes (i.e., fs/filesystems.c for register_filesystem()). I
> will let you know once I've done (maybe v2 RFC if you think
> it's better ?)

I've extensively removed about 1K LoC of stubs (glues)
including e.g., register_filesystem(). There are still stubs
need to be tracked, like file mount code, memory management,
but it can be improved later I think.

commit edc9109d6d1a36f691872549762f954783a9a628
Author: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Date:   Tue Mar 31 22:32:21 2015 +0900

    lib: reduce glue codes (stubs)
    
 arch/lib/Makefile                  |  22 ++--
 arch/lib/capability.c              |  47 +++++++
 arch/lib/cred.c                    |  16 ---
 arch/lib/dcache.c                  |  93 --------------
 arch/lib/filemap.c                 |   5 +
 arch/lib/fs.c                      | 239 ++----------------------------------
 arch/lib/glue.c                    |  75 ++---------
 arch/lib/include/asm/Kbuild        |   2 +
 arch/lib/include/asm/atomic.h      |   5 +-
 arch/lib/include/asm/thread_info.h |   1 +
 arch/lib/inode.c                   | 146 ----------------------
 arch/lib/lib.c                     |   5 +
 arch/lib/proc.c                    | 130 --------------------
 arch/lib/sched.c                   |  41 +++++++
 arch/lib/security.c                |  45 -------
 arch/lib/seq.c                     | 122 ------------------
 arch/lib/slab.c                    |   3 +
 arch/lib/softirq.c                 |   4 +
 arch/lib/splice.c                  |  20 ---
 arch/lib/super.c                   | 210 -------------------------------
 arch/lib/sysctl.c                  |  15 ---
 arch/lib/time.c                    |   5 -
 22 files changed, 142 insertions(+), 1109 deletions(-)

(full modification on this commit)
https://github.com/libos-nuse/net-next-nuse/commit/edc9109d6d1a36f691872549762f954783a9a628

I still have a couple of comments, which I haven't addressed
with the code (below). will work on too.

* build system (Makefile)
- parallel build issue
- cross-build issue
- missing dependency detection

* code location
- under arch/ or tools/

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-04-01  1:29                         ` Rusty Russell
@ 2015-04-03  1:43                           ` Hajime Tazaki
  2015-04-07  1:25                             ` Rusty Russell
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-03  1:43 UTC (permalink / raw)
  To: rusty
  Cc: richard, linux-arch, arnd, corbet, cl, penberg, rientjes,
	iamjoonsoo.kim, akpm, linux-kernel, linux-doc, netdev, linux-mm,
	jdike, mathieu.lacage


Thanks Rusty,

At Wed, 01 Apr 2015 11:59:39 +1030,
Rusty Russell wrote:
> 
> Hajime Tazaki <tazaki@sfc.wide.ad.jp> writes:
> > the issue here is the decision between 'no-ops' and
> > 'assert(false)' depends on the context. an auto-generated
> > mechanism needs some hand-written parameters I think.
> 
> Yes, I used auto-generated (fprintf, abort) stubs for similar testing in
> pettycoin, where if it failed to link it would generate such stubs
> for undefined symbols.
> 
> It's not a panacea, but it helps speed up rejiggin after code changes.
> Generating noop stubs can actually make that process slower, as you can
> get failures because you now need to do something in that stub.

is it the following ? it's really cool stuff !

https://github.com/rustyrussell/pettycoin/blob/master/test/mockup.sh
 
-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-04-03  1:43                           ` Hajime Tazaki
@ 2015-04-07  1:25                             ` Rusty Russell
  0 siblings, 0 replies; 117+ messages in thread
From: Rusty Russell @ 2015-04-07  1:25 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: richard, linux-arch, arnd, corbet, cl, penberg, rientjes,
	iamjoonsoo.kim, akpm, linux-kernel, linux-doc, netdev, linux-mm,
	jdike, mathieu.lacage

Hajime Tazaki <tazaki@wide.ad.jp> writes:
> is it the following ? it's really cool stuff !
>
> https://github.com/rustyrussell/pettycoin/blob/master/test/mockup.sh

Yep.  It's ugly, but it Works For Me(TM).

Cheers,
Rusty.

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-31  7:47                           ` Hajime Tazaki
@ 2015-04-09  8:36                             ` Richard Weinberger
  2015-04-14  3:20                               ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-04-09  8:36 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage

Am 31.03.2015 um 09:47 schrieb Hajime Tazaki:
> right now arch/lib/Makefile isn't fully on the Kbuild
> system: build file dependency is not tracked at all.
> 
> while I should learn more about Kbuild, I'd be happy if you
> would suggest how the Makefile should be.

You definitely have to use Kbuild.
Please bite the bullet and dig into it. Maybe we
need also new functions in Kbuild to support a library mode.
Who knows? ;)

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS)
  2015-04-09  8:36                             ` Richard Weinberger
@ 2015-04-14  3:20                               ` Hajime Tazaki
  0 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-14  3:20 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	mathieu.lacage


At Thu, 09 Apr 2015 10:36:23 +0200,
Richard Weinberger wrote:
> 
> Am 31.03.2015 um 09:47 schrieb Hajime Tazaki:
> > right now arch/lib/Makefile isn't fully on the Kbuild
> > system: build file dependency is not tracked at all.
> > 
> > while I should learn more about Kbuild, I'd be happy if you
> > would suggest how the Makefile should be.
> 
> You definitely have to use Kbuild.
> Please bite the bullet and dig into it. Maybe we
> need also new functions in Kbuild to support a library mode.
> Who knows? ;)

Thanks Richard for the comment: I've been struggling on this
and created a github issue to struggle more ;)

https://github.com/libos-nuse/net-next-nuse/issues/26

I'd be happy if any of you're interested to tackle
Kbuild-ish Makefile for LibOS.

I'll be back here once I come up with the nice one.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 00/11] an introduction of library operating system for Linux (LibOS)
  2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                   ` (11 preceding siblings ...)
  2015-03-24 13:21 ` [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Richard Weinberger
@ 2015-04-17  9:36 ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
                     ` (11 more replies)
  12 siblings, 12 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

changes from v1:
- Patch 01/11 ("sysctl: make some functions unstatic to access by arch/lib"):
* add prefix ctl_table_ to newly publiced functions (commented by Joe Perches)
- Patch 08/11 ("lib: other kernel glue layer code"):
* significantly reduce glue codes (stubs) (commented by Richard Weinberger)
- Others
* adapt to linux-4.0.0
* detect make dependency by Kbuild .cmd files

patchset history
-----------------
[v1] : https://lkml.org/lkml/2015/3/24/254

This is an introduction of library operating system (LibOS) for Linux.

Our objective is to build the kernel network stack as a shared library
that can be linked to by userspace programs to provide network stack
personalization and testing facilities, and allow researchers to more
easily simulate complex network topologies of linux routers/hosts.

Although the architecture itself can virtualize various things, the
current design only focuses on the network stack. You can benefit
network stack feature such as TCP, UDP, SCTP, DCCP (IPv4 and IPv6),
Mobie IPv6, Multipath TCP (IPv4/IPv6, out-of-tree at the present
moment), and netlink with various userspace applications (quagga,
iproute2, iperf, wget, and thttpd).

== What is LibOS ? ==

The library exposes an entry point as API, which is lib_init(), in
order to connect userspace applications to the (userspace-version)
kernel network stack. The clock source, virtual struct net_device, and
scheduler are provided by caller while kernel resource like system
calls is provided by callee.

Once the LibOS is initialized via the API, userspace applications with
POSIX socket can use the system calls defined in LibOS by replacing
from the original socket-related symbols to the LibOS-specific
one. Then application can benefit the network stack of LibOS without
involving the host network stack.

Currently, there are two users of LibOS: Network Stack in Userspace
(NUSE) and ns-3 network simulatior with Direct Code Execution
(DCE). These codes are managed at an external repository(*1).


== How to use it ? ==

to build the library,
% make {defconfig,menuconfig} ARCH=lib

then, build it.
% make library ARCH=lib

You will see liblinux-$(KERNELVERSION).so in the top directory.

== More information ==

The crucial difference between UML (user-mode linux) and this approach
is that we allow multiple network stack instances to co-exist within a
single process with dlmopen(3) like linking for easy debugging.


These patches are also available on this branch:

git://github.com/libos-nuse/net-next-nuse.git for-asm-upstream


For further information, here is a slideset presented at the last
netdev0.1 conference.

http://www.slideshare.net/hajimetazaki/library-operating-system-for-linux-netdev01

I would appreciate any kind of your feedback regarding to upstream
this feature.

*1 https://github.com/libos-nuse/linux-libos-tools

Hajime Tazaki (11):
  sysctl: make some functions unstatic to access by arch/lib
  slab: add private memory allocator header for arch/lib
  lib: public headers and API implementations for userspace programs
  lib: memory management (kernel glue code)
  lib: time handling (kernel glue code)
  lib: context and scheduling handling (kernel glue code)
  lib: sysctl handling (kernel glue code)
  lib: other kernel glue layer code
  lib: asm-generic files
  lib: libos build scripts and documentation
  lib: tools used for test scripts

 Documentation/virtual/libos-howto.txt | 144 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   8 +
 arch/lib/Kconfig                      | 121 +++++++
 arch/lib/Makefile                     | 251 +++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/capability.c                 |  47 +++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/filemap.c                    |  32 ++
 arch/lib/fs.c                         |  70 ++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/glue.c                       | 283 +++++++++++++++
 arch/lib/hrtimer.c                    | 122 +++++++
 arch/lib/include/asm/Kbuild           |  57 +++
 arch/lib/include/asm/atomic.h         |  50 +++
 arch/lib/include/asm/barrier.h        |   8 +
 arch/lib/include/asm/bitsperlong.h    |  12 +
 arch/lib/include/asm/current.h        |   7 +
 arch/lib/include/asm/elf.h            |  10 +
 arch/lib/include/asm/hardirq.h        |   8 +
 arch/lib/include/asm/page.h           |  14 +
 arch/lib/include/asm/pgtable.h        |  30 ++
 arch/lib/include/asm/processor.h      |  19 +
 arch/lib/include/asm/ptrace.h         |   4 +
 arch/lib/include/asm/segment.h        |   6 +
 arch/lib/include/asm/sembuf.h         |   4 +
 arch/lib/include/asm/shmbuf.h         |   4 +
 arch/lib/include/asm/shmparam.h       |   4 +
 arch/lib/include/asm/sigcontext.h     |   6 +
 arch/lib/include/asm/slab.h           |  21 ++
 arch/lib/include/asm/stat.h           |   4 +
 arch/lib/include/asm/statfs.h         |   4 +
 arch/lib/include/asm/swab.h           |   7 +
 arch/lib/include/asm/thread_info.h    |  36 ++
 arch/lib/include/asm/uaccess.h        |  14 +
 arch/lib/include/asm/unistd.h         |   4 +
 arch/lib/include/sim-assert.h         |  23 ++
 arch/lib/include/sim-init.h           | 134 +++++++
 arch/lib/include/sim-printf.h         |  13 +
 arch/lib/include/sim-types.h          |  53 +++
 arch/lib/include/sim.h                |  51 +++
 arch/lib/include/uapi/asm/byteorder.h |   6 +
 arch/lib/lib-device.c                 | 187 ++++++++++
 arch/lib/lib-socket.c                 | 410 +++++++++++++++++++++
 arch/lib/lib.c                        | 294 +++++++++++++++
 arch/lib/lib.h                        |  21 ++
 arch/lib/modules.c                    |  36 ++
 arch/lib/pid.c                        |  29 ++
 arch/lib/print.c                      |  56 +++
 arch/lib/proc.c                       |  34 ++
 arch/lib/processor.mk                 |   7 +
 arch/lib/random.c                     |  53 +++
 arch/lib/sched.c                      | 406 +++++++++++++++++++++
 arch/lib/slab.c                       | 203 +++++++++++
 arch/lib/softirq.c                    | 108 ++++++
 arch/lib/sysctl.c                     | 270 ++++++++++++++
 arch/lib/sysfs.c                      |  83 +++++
 arch/lib/tasklet-hrtimer.c            |  57 +++
 arch/lib/tasklet.c                    |  76 ++++
 arch/lib/time.c                       | 144 ++++++++
 arch/lib/timer.c                      | 238 +++++++++++++
 arch/lib/vmscan.c                     |  26 ++
 arch/lib/workqueue.c                  | 242 +++++++++++++
 fs/proc/proc_sysctl.c                 |  36 +-
 include/linux/slab.h                  |  12 +
 tools/testing/libos/.gitignore        |   6 +
 tools/testing/libos/Makefile          |  38 ++
 tools/testing/libos/README            |  15 +
 tools/testing/libos/bisect.sh         |  10 +
 tools/testing/libos/dce-test.sh       |  23 ++
 tools/testing/libos/nuse-test.sh      |  57 +++
 71 files changed, 5608 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/capability.c
 create mode 100644 arch/lib/defconfig
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/slab.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/processor.mk
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/slab.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/sysctl.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c
 create mode 100644 arch/lib/vmscan.c
 create mode 100644 arch/lib/workqueue.c
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 01/11] sysctl: make some functions unstatic to access by arch/lib
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

libos (arch/lib) emulates a sysctl-like interface by a function call of
userspace by enumerating sysctl tree from sysctl_table_root. It requires
to be publicly accessible to this symbol and related functions.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 fs/proc/proc_sysctl.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f92d5dd..56feec7 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -35,7 +35,7 @@ static struct ctl_table root_table[] = {
 	},
 	{ }
 };
-static struct ctl_table_root sysctl_table_root = {
+struct ctl_table_root sysctl_table_root = {
 	.default_set.dir.header = {
 		{{.count = 1,
 		  .nreg = 1,
@@ -77,8 +77,9 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
 }
 
 /* Called under sysctl_lock */
-static struct ctl_table *find_entry(struct ctl_table_header **phead,
-	struct ctl_dir *dir, const char *name, int namelen)
+struct ctl_table *ctl_table_find_entry(struct ctl_table_header **phead,
+				       struct ctl_dir *dir, const char *name,
+				       int namelen)
 {
 	struct ctl_table_header *head;
 	struct ctl_table *entry;
@@ -300,7 +301,7 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
 	struct ctl_table *entry;
 
 	spin_lock(&sysctl_lock);
-	entry = find_entry(&head, dir, name, namelen);
+	entry = ctl_table_find_entry(&head, dir, name, namelen);
 	if (entry && use_table(head))
 		*phead = head;
 	else
@@ -321,7 +322,7 @@ static struct ctl_node *first_usable_entry(struct rb_node *node)
 	return NULL;
 }
 
-static void first_entry(struct ctl_dir *dir,
+void ctl_table_first_entry(struct ctl_dir *dir,
 	struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = NULL;
@@ -339,7 +340,7 @@ static void first_entry(struct ctl_dir *dir,
 	*pentry = entry;
 }
 
-static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
+void ctl_table_next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = *phead;
 	struct ctl_table *entry = *pentry;
@@ -670,7 +671,8 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
 
 	pos = 2;
 
-	for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
+	for (ctl_table_first_entry(ctl_dir, &h, &entry); h;
+	     ctl_table_next_entry(&h, &entry)) {
 		if (!scan(h, entry, &pos, file, ctx)) {
 			sysctl_head_finish(h);
 			break;
@@ -828,7 +830,7 @@ static struct ctl_dir *find_subdir(struct ctl_dir *dir,
 	struct ctl_table_header *head;
 	struct ctl_table *entry;
 
-	entry = find_entry(&head, dir, name, namelen);
+	entry = ctl_table_find_entry(&head, dir, name, namelen);
 	if (!entry)
 		return ERR_PTR(-ENOENT);
 	if (!S_ISDIR(entry->mode))
@@ -924,13 +926,13 @@ failed:
 	return subdir;
 }
 
-static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
+struct ctl_dir *ctl_table_xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
 {
 	struct ctl_dir *parent;
 	const char *procname;
 	if (!dir->header.parent)
 		return &set->dir;
-	parent = xlate_dir(set, dir->header.parent);
+	parent = ctl_table_xlate_dir(set, dir->header.parent);
 	if (IS_ERR(parent))
 		return parent;
 	procname = dir->header.ctl_table[0].procname;
@@ -951,13 +953,13 @@ static int sysctl_follow_link(struct ctl_table_header **phead,
 	spin_lock(&sysctl_lock);
 	root = (*pentry)->data;
 	set = lookup_header_set(root, namespaces);
-	dir = xlate_dir(set, (*phead)->parent);
+	dir = ctl_table_xlate_dir(set, (*phead)->parent);
 	if (IS_ERR(dir))
 		ret = PTR_ERR(dir);
 	else {
 		const char *procname = (*pentry)->procname;
 		head = NULL;
-		entry = find_entry(&head, dir, procname, strlen(procname));
+		entry = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		ret = -ENOENT;
 		if (entry && use_table(head)) {
 			unuse_table(*phead);
@@ -1069,7 +1071,7 @@ static bool get_links(struct ctl_dir *dir,
 	/* Are there links available for every entry in table? */
 	for (entry = table; entry->procname; entry++) {
 		const char *procname = entry->procname;
-		link = find_entry(&head, dir, procname, strlen(procname));
+		link = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		if (!link)
 			return false;
 		if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
@@ -1082,7 +1084,7 @@ static bool get_links(struct ctl_dir *dir,
 	/* The checks passed.  Increase the registration count on the links */
 	for (entry = table; entry->procname; entry++) {
 		const char *procname = entry->procname;
-		link = find_entry(&head, dir, procname, strlen(procname));
+		link = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		head->nreg++;
 	}
 	return true;
@@ -1098,7 +1100,7 @@ static int insert_links(struct ctl_table_header *head)
 	if (head->set == root_set)
 		return 0;
 
-	core_parent = xlate_dir(root_set, head->parent);
+	core_parent = ctl_table_xlate_dir(root_set, head->parent);
 	if (IS_ERR(core_parent))
 		return 0;
 
@@ -1479,7 +1481,7 @@ static void put_links(struct ctl_table_header *header)
 	if (header->set == root_set)
 		return;
 
-	core_parent = xlate_dir(root_set, parent);
+	core_parent = ctl_table_xlate_dir(root_set, parent);
 	if (IS_ERR(core_parent))
 		return;
 
@@ -1488,7 +1490,7 @@ static void put_links(struct ctl_table_header *header)
 		struct ctl_table *link;
 		const char *name = entry->procname;
 
-		link = find_entry(&link_head, core_parent, name, strlen(name));
+		link = ctl_table_find_entry(&link_head, core_parent, name, strlen(name));
 		if (link &&
 		    ((S_ISDIR(link->mode) && S_ISDIR(entry->mode)) ||
 		     (S_ISLNK(link->mode) && (link->data == root)))) {
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17 12:17     ` Christoph Lameter
  2015-04-17  9:36   ` [RFC PATCH v2 03/11] lib: public headers and API implementations for userspace programs Hajime Tazaki
                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

add header includion for CONFIG_LIB to wrap kmalloc and co. This will
bring malloc(3) based allocator used by arch/lib.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 include/linux/slab.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 9a139b6..6914e1f 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -205,6 +205,14 @@ size_t ksize(const void *);
 #endif
 #endif
 
+#ifdef CONFIG_LIB
+#define KMALLOC_SHIFT_MAX	30
+#define KMALLOC_SHIFT_HIGH	PAGE_SHIFT
+#ifndef KMALLOC_SHIFT_LOW
+#define KMALLOC_SHIFT_LOW	3
+#endif
+#endif
+
 /* Maximum allocatable size */
 #define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_MAX)
 /* Maximum size for which we actually use a slab cache */
@@ -350,6 +358,9 @@ kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
 }
 #endif
 
+#ifdef CONFIG_LIB
+#include <asm/slab.h>
+#else
 static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 {
 	unsigned int order = get_order(size);
@@ -428,6 +439,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 	}
 	return __kmalloc(size, flags);
 }
+#endif
 
 /*
  * Determine size used for the nth kmalloc cache.
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 03/11] lib: public headers and API implementations for userspace programs
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 04/11] lib: memory management (kernel glue code) Hajime Tazaki
                     ` (8 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

userspace programs access via public API, lib_init(), with passed
arguments struct SimImported and struct SimExported.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 arch/lib/include/sim-assert.h |  23 +++
 arch/lib/include/sim-init.h   | 134 ++++++++++++++
 arch/lib/include/sim-printf.h |  13 ++
 arch/lib/include/sim-types.h  |  53 ++++++
 arch/lib/include/sim.h        |  51 ++++++
 arch/lib/lib-device.c         | 187 +++++++++++++++++++
 arch/lib/lib-socket.c         | 410 ++++++++++++++++++++++++++++++++++++++++++
 arch/lib/lib.c                | 294 ++++++++++++++++++++++++++++++
 arch/lib/lib.h                |  21 +++
 9 files changed, 1186 insertions(+)
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h

diff --git a/arch/lib/include/sim-assert.h b/arch/lib/include/sim-assert.h
new file mode 100644
index 0000000..974122c
--- /dev/null
+++ b/arch/lib/include/sim-assert.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_ASSERT_H
+#define SIM_ASSERT_H
+
+#include "sim-printf.h"
+
+#define lib_assert(v) {							\
+		while (!(v)) {						\
+			lib_printf("Assert failed %s:%u \"" #v "\"\n",	\
+				__FILE__, __LINE__);			\
+			char *p = 0;					\
+			*p = 1;						\
+		}							\
+	}
+
+
+#endif /* SIM_ASSERT_H */
diff --git a/arch/lib/include/sim-init.h b/arch/lib/include/sim-init.h
new file mode 100644
index 0000000..e871a59
--- /dev/null
+++ b/arch/lib/include/sim-init.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_INIT_H
+#define SIM_INIT_H
+
+#include <linux/socket.h>
+#include "sim-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
+
+struct SimExported {
+	struct SimTask *(*task_create)(void *priv, unsigned long pid);
+	void (*task_destroy)(struct SimTask *task);
+	void *(*task_get_private)(struct SimTask *task);
+
+	int (*sock_socket)(int domain, int type, int protocol,
+			struct SimSocket **socket);
+	int (*sock_close)(struct SimSocket *socket);
+	ssize_t (*sock_recvmsg)(struct SimSocket *socket, struct msghdr *msg,
+				int flags);
+	ssize_t (*sock_sendmsg)(struct SimSocket *socket,
+				const struct msghdr *msg, int flags);
+	int (*sock_getsockname)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_getpeername)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_bind)(struct SimSocket *socket, const struct sockaddr *name,
+			int namelen);
+	int (*sock_connect)(struct SimSocket *socket,
+			const struct sockaddr *name, int namelen,
+			int flags);
+	int (*sock_listen)(struct SimSocket *socket, int backlog);
+	int (*sock_shutdown)(struct SimSocket *socket, int how);
+	int (*sock_accept)(struct SimSocket *socket,
+			struct SimSocket **newSocket, int flags);
+	int (*sock_ioctl)(struct SimSocket *socket, int request, char *argp);
+	int (*sock_setsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			const void *optval, int optlen);
+	int (*sock_getsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			void *optval, int *optlen);
+
+	void (*sock_poll)(struct SimSocket *socket, void *ret);
+	void (*sock_pollfreewait)(void *polltable);
+
+	struct SimDevice *(*dev_create)(const char *ifname, void *priv,
+					enum SimDevFlags flags);
+	void (*dev_destroy)(struct SimDevice *dev);
+	void *(*dev_get_private)(struct SimDevice *task);
+	void (*dev_set_address)(struct SimDevice *dev,
+				unsigned char buffer[6]);
+	void (*dev_set_mtu)(struct SimDevice *dev, int mtu);
+	struct SimDevicePacket (*dev_create_packet)(struct SimDevice *dev,
+						int size);
+	void (*dev_rx)(struct SimDevice *dev, struct SimDevicePacket packet);
+
+	void (*sys_iterate_files)(const struct SimSysIterator *iter);
+	int (*sys_file_read)(const struct SimSysFile *file, char *buffer,
+			int size, int offset);
+	int (*sys_file_write)(const struct SimSysFile *file,
+			const char *buffer, int size, int offset);
+};
+
+struct SimImported {
+	int (*vprintf)(struct SimKernel *kernel, const char *str,
+		va_list args);
+	void *(*malloc)(struct SimKernel *kernel, unsigned long size);
+	void (*free)(struct SimKernel *kernel, void *buffer);
+	void *(*memcpy)(struct SimKernel *kernel, void *dst, const void *src,
+			unsigned long size);
+	void *(*memset)(struct SimKernel *kernel, void *dst, char value,
+			unsigned long size);
+	int (*atexit)(struct SimKernel *kernel, void (*function)(void));
+	int (*access)(struct SimKernel *kernel, const char *pathname,
+		int mode);
+	char *(*getenv)(struct SimKernel *kernel, const char *name);
+	int (*mkdir)(struct SimKernel *kernel, const char *pathname,
+		mode_t mode);
+	int (*open)(struct SimKernel *kernel, const char *pathname, int flags);
+	int (*__fxstat)(struct SimKernel *kernel, int ver, int fd, void *buf);
+	int (*fseek)(struct SimKernel *kernel, FILE *stream, long offset,
+		int whence);
+	void (*setbuf)(struct SimKernel *kernel, FILE *stream, char *buf);
+	FILE *(*fdopen)(struct SimKernel *kernel, int fd, const char *mode);
+	long (*ftell)(struct SimKernel *kernel, FILE *stream);
+	int (*fclose)(struct SimKernel *kernel, FILE *fp);
+	size_t (*fread)(struct SimKernel *kernel, void *ptr, size_t size,
+			size_t nmemb, FILE *stream);
+	size_t (*fwrite)(struct SimKernel *kernel, const void *ptr, size_t size,
+			 size_t nmemb, FILE *stream);
+
+	unsigned long (*random)(struct SimKernel *kernel);
+	void *(*event_schedule_ns)(struct SimKernel *kernel, __u64 ns,
+				void (*fn)(void *context), void *context,
+				void (*pre_fn)(void));
+	void (*event_cancel)(struct SimKernel *kernel, void *event);
+	__u64 (*current_ns)(struct SimKernel *kernel);
+
+	struct SimTask *(*task_start)(struct SimKernel *kernel,
+				void (*callback)(void *),
+				void *context);
+	void (*task_wait)(struct SimKernel *kernel);
+	struct SimTask *(*task_current)(struct SimKernel *kernel);
+	int (*task_wakeup)(struct SimKernel *kernel, struct SimTask *task);
+	void (*task_yield)(struct SimKernel *kernel);
+
+	void (*dev_xmit)(struct SimKernel *kernel, struct SimDevice *dev,
+			unsigned char *data, int len);
+	void (*signal_raised)(struct SimKernel *kernel, struct SimTask *task,
+			int sig);
+	void (*poll_event)(int flag, void *context);
+};
+
+typedef void (*SimInit)(struct SimExported *, const struct SimImported *,
+			struct SimKernel *kernel);
+void sim_init(struct SimExported *exported, const struct SimImported *imported,
+	struct SimKernel *kernel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_INIT_H */
diff --git a/arch/lib/include/sim-printf.h b/arch/lib/include/sim-printf.h
new file mode 100644
index 0000000..2bf8245
--- /dev/null
+++ b/arch/lib/include/sim-printf.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_PRINTF_H
+#define SIM_PRINTF_H
+
+void lib_printf(const char *str, ...);
+
+#endif /* SIM_PRINTF_H */
diff --git a/arch/lib/include/sim-types.h b/arch/lib/include/sim-types.h
new file mode 100644
index 0000000..d50b99b
--- /dev/null
+++ b/arch/lib/include/sim-types.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_TYPES_H
+#define SIM_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBOS_API_VERSION     2
+
+struct SimTask;
+struct SimDevice;
+struct SimSocket;
+struct SimKernel;
+struct SimSysFile;
+
+enum SimDevFlags {
+	SIM_DEV_NOARP         = (1 << 0),
+	SIM_DEV_POINTTOPOINT  = (1 << 1),
+	SIM_DEV_MULTICAST     = (1 << 2),
+	SIM_DEV_BROADCAST     = (1 << 3),
+};
+
+struct SimDevicePacket {
+	void *buffer;
+	void *token;
+};
+
+enum SimSysFileFlags {
+	SIM_SYS_FILE_READ  = 1 << 0,
+	SIM_SYS_FILE_WRITE = 1 << 1,
+};
+
+struct SimSysIterator {
+	void (*report_start_dir)(const struct SimSysIterator *iter,
+				const char *dirname);
+	void (*report_end_dir)(const struct SimSysIterator *iter);
+	void (*report_file)(const struct SimSysIterator *iter,
+			const char *filename,
+			int flags, struct SimSysFile *file);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_TYPES_H */
diff --git a/arch/lib/include/sim.h b/arch/lib/include/sim.h
new file mode 100644
index 0000000..b30d7e8
--- /dev/null
+++ b/arch/lib/include/sim.h
@@ -0,0 +1,51 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_H
+#define SIM_H
+
+#include <stdarg.h>
+#include <linux/types.h>
+
+#include "sim-types.h"
+
+/* API called from within linux kernel. Forwards to SimImported. */
+int lib_vprintf(const char *str, va_list args);
+void *lib_malloc(unsigned long size);
+void lib_free(void *buffer);
+void *lib_memcpy(void *dst, const void *src, unsigned long size);
+void *lib_memset(void *dst, char value, unsigned long size);
+unsigned long lib_random(void);
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context),
+			    void *context);
+void lib_event_cancel(void *event);
+__u64 lib_current_ns(void);
+
+struct SimTask *lib_task_start(void (*callback) (void *), void *context);
+void lib_task_wait(void);
+void lib_task_yield(void);
+struct SimTask *lib_task_current(void);
+/* returns 1 if task was woken up, 0 if it was already running. */
+int lib_task_wakeup(struct SimTask *task);
+struct SimTask *lib_task_create(void *priv, unsigned long pid);
+void lib_task_destroy(struct SimTask *task);
+void *lib_task_get_private(struct SimTask *task);
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len);
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size);
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet);
+
+void lib_signal_raised(struct SimTask *task, int sig);
+
+void lib_poll_event(int flag, void *context);
+void lib_softirq_wakeup(void);
+void lib_update_jiffies(void);
+void *lib_dev_get_private(struct SimDevice *);
+void lib_proc_net_initialize(void);
+
+#endif /* SIM_H */
diff --git a/arch/lib/lib-device.c b/arch/lib/lib-device.c
new file mode 100644
index 0000000..1efa6460
--- /dev/null
+++ b/arch/lib/lib-device.c
@@ -0,0 +1,187 @@
+/*
+ * virtual net_device feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ethtool.h>
+
+struct SimDevice {
+	struct net_device dev;
+	void *priv;
+};
+
+static netdev_tx_t
+kernel_dev_xmit(struct sk_buff *skb,
+		struct net_device *dev)
+{
+	int err;
+
+	netif_stop_queue(dev);
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		err = skb_checksum_help(skb);
+		if (unlikely(err)) {
+			pr_err("checksum error (%d)\n", err);
+			return 0;
+		}
+	}
+
+	lib_dev_xmit((struct SimDevice *)dev, skb->data, skb->len);
+	dev_kfree_skb(skb);
+	netif_wake_queue(dev);
+	return 0;
+}
+
+static u32 always_on(struct net_device *dev)
+{
+	return 1;
+}
+
+
+static const struct ethtool_ops lib_ethtool_ops = {
+	.get_link		= always_on,
+};
+
+static const struct net_device_ops lib_dev_ops = {
+	.ndo_start_xmit		= kernel_dev_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static void lib_dev_setup(struct net_device *dev)
+{
+	dev->mtu                = (16 * 1024) + 20 + 20 + 12;
+	dev->hard_header_len    = ETH_HLEN;     /* 14   */
+	dev->addr_len           = ETH_ALEN;     /* 6    */
+	dev->tx_queue_len       = 0;
+	dev->type               = ARPHRD_ETHER;
+	dev->flags              = 0;
+	/* dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE; */
+	dev->features           = 0
+				  | NETIF_F_HIGHDMA
+				  | NETIF_F_NETNS_LOCAL;
+	/* disabled  NETIF_F_TSO NETIF_F_SG  NETIF_F_FRAGLIST NETIF_F_LLTX */
+	dev->ethtool_ops        = &lib_ethtool_ops;
+	dev->header_ops         = &eth_header_ops;
+	dev->netdev_ops         = &lib_dev_ops;
+	dev->destructor         = &free_netdev;
+}
+
+
+struct SimDevice *lib_dev_create(const char *ifname, void *priv,
+				 enum SimDevFlags flags)
+{
+	int err;
+	struct SimDevice *dev =
+		(struct SimDevice *)alloc_netdev(sizeof(struct SimDevice),
+						 ifname, NET_NAME_UNKNOWN,
+						 &lib_dev_setup);
+	ether_setup((struct net_device *)dev);
+
+	if (flags & SIM_DEV_NOARP)
+		dev->dev.flags |= IFF_NOARP;
+	if (flags & SIM_DEV_POINTTOPOINT)
+		dev->dev.flags |= IFF_POINTOPOINT;
+	if (flags & SIM_DEV_MULTICAST)
+		dev->dev.flags |= IFF_MULTICAST;
+	if (flags & SIM_DEV_BROADCAST) {
+		dev->dev.flags |= IFF_BROADCAST;
+		memset(dev->dev.broadcast, 0xff, 6);
+	}
+	dev->priv = priv;
+	err = register_netdev(&dev->dev);
+	return dev;
+}
+void lib_dev_destroy(struct SimDevice *dev)
+{
+	unregister_netdev(&dev->dev);
+	/* XXX */
+	free_netdev(&dev->dev);
+}
+void *lib_dev_get_private(struct SimDevice *dev)
+{
+	return dev->priv;
+}
+
+void lib_dev_set_mtu(struct SimDevice *dev, int mtu)
+{
+	/* called by ns-3 to synchronize the kernel mtu with */
+	/* the simulation mtu */
+	dev->dev.mtu = mtu;
+}
+
+static int lib_ndo_change_mtu(struct net_device *dev,
+			      int new_mtu)
+{
+	/* called by kernel to change the mtu when the user */
+	/* asks for it. */
+	/* XXX should forward the set call to ns-3 and wait for */
+	/* ns-3 to notify of the change in the function above */
+	/* but I am way too tired to do this now. */
+	return 0;
+}
+
+void lib_dev_set_address(struct SimDevice *dev, unsigned char buffer[6])
+{
+	/* called by ns-3 to synchronize the kernel address with */
+	/* the simulation address. */
+	struct sockaddr sa;
+
+	sa.sa_family = dev->dev.type;
+	lib_memcpy(&sa.sa_data, buffer, 6);
+	dev->dev.netdev_ops->ndo_set_mac_address(&dev->dev, &sa);
+	/* Note that we don't call   dev_set_mac_address (&dev->dev, &sa); */
+	/* because this function expects to be called from within */
+	/* the netlink layer so, it expects to hold */
+	/* the netlink lock during the execution of the associated notifiers */
+}
+static int get_hack_size(int size)
+{
+	/* Note: this hack is coming from nsc */
+	/* Bit of a hack... */
+	/* Note that the size allocated here effects the offered window
+	   somewhat. I've got this heuristic here to try and match up with
+	   what we observe on the emulation network and by looking at the
+	   driver code of the eepro100. In both cases we allocate enough
+	   space for our packet, which  is the important thing. The amount
+	   of slack at the end can make linux decide the grow the window
+	   differently. This is quite subtle, but the code in question is
+	   in the tcp_grow_window function. It checks skb->truesize, which
+	   is the size of the skbuff allocated for the incoming data
+	   packet -- what we are allocating right now! */
+	if (size < 1200)
+		return size + 36;
+	else if (size <= 1500)
+		return 1536;
+	else
+		return size + 36;
+}
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size)
+{
+	struct SimDevicePacket packet;
+	int len = get_hack_size(size);
+	struct sk_buff *skb = __dev_alloc_skb(len, __GFP_WAIT);
+
+	packet.token = skb;
+	packet.buffer = skb_put(skb, len);
+	return packet;
+}
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet)
+{
+	struct sk_buff *skb = packet.token;
+	struct net_device *dev = &device->dev;
+
+	skb->protocol = eth_type_trans(skb, dev);
+	/* Do the TCP checksum (FIXME: should be configurable) */
+	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	netif_rx(skb);
+}
diff --git a/arch/lib/lib-socket.c b/arch/lib/lib-socket.c
new file mode 100644
index 0000000..d9be5fc
--- /dev/null
+++ b/arch/lib/lib-socket.c
@@ -0,0 +1,410 @@
+/*
+ * socket feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/net.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/inet_connection_sock.h>
+
+struct SimSocket {};
+
+static struct iovec *copy_iovec(const struct iovec *input, int len)
+{
+	int size = sizeof(struct iovec) * len;
+	struct iovec *output = lib_malloc(size);
+
+	if (!output)
+		return NULL;
+	lib_memcpy(output, input, size);
+	return output;
+}
+
+int lib_sock_socket(int domain, int type, int protocol,
+		    struct SimSocket **socket)
+{
+	struct socket **kernel_socket = (struct socket **)socket;
+	int flags;
+
+	/* from net/socket.c */
+	flags = type & ~SOCK_TYPE_MASK;
+	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+		return -EINVAL;
+	type &= SOCK_TYPE_MASK;
+
+	int retval = sock_create(domain, type, protocol, kernel_socket);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	struct file *fp = lib_malloc(sizeof(struct file));
+	(*kernel_socket)->file = fp;
+	fp->f_cred = lib_malloc(sizeof(struct cred));
+	return retval;
+}
+int lib_sock_close(struct SimSocket *socket)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+
+	sock_release(kernel_socket);
+	return 0;
+}
+static size_t iov_size(const struct user_msghdr *msg)
+{
+	size_t i;
+	size_t size = 0;
+
+	for (i = 0; i < msg->msg_iovlen; i++)
+		size += msg->msg_iov[i].iov_len;
+	return size;
+}
+ssize_t lib_sock_recvmsg(struct SimSocket *socket,
+			struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct msghdr msg_sys;
+	struct cmsghdr *user_cmsgh = msg->msg_control;
+	size_t user_cmsghlen = msg->msg_controllen;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, READ,
+		msg->msg_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_recvmsg(kernel_socket, &msg_sys, iov_size(msg), flags);
+
+	msg->msg_name = msg_sys.msg_name;
+	msg->msg_namelen = msg_sys.msg_namelen;
+	msg->msg_control = user_cmsgh;
+	msg->msg_controllen = user_cmsghlen - msg_sys.msg_controllen;
+	return retval;
+}
+ssize_t lib_sock_sendmsg(struct SimSocket *socket,
+			const struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct iovec *kernel_iov = copy_iovec(msg->msg_iov, msg->msg_iovlen);
+	struct msghdr msg_sys;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, WRITE,
+		kernel_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_sendmsg(kernel_socket, &msg_sys);
+	lib_free(kernel_iov);
+	return retval;
+}
+int lib_sock_getsockname(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 0);
+
+	return retval;
+}
+int lib_sock_getpeername(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 1);
+
+	return retval;
+}
+int lib_sock_bind(struct SimSocket *socket, const struct sockaddr *name,
+		  int namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	int retval =
+		sock->ops->bind(sock, (struct sockaddr *)&address, namelen);
+	return retval;
+}
+int lib_sock_connect(struct SimSocket *socket, const struct sockaddr *name,
+		     int namelen, int flags)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	sock->file->f_flags = flags;
+	int retval = sock->ops->connect(sock, (struct sockaddr *)&address,
+					namelen, flags);
+	return retval;
+}
+int lib_sock_listen(struct SimSocket *socket, int backlog)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->listen(sock, backlog);
+
+	return retval;
+}
+int lib_sock_shutdown(struct SimSocket *socket, int how)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->shutdown(sock, how);
+
+	return retval;
+}
+int lib_sock_accept(struct SimSocket *socket, struct SimSocket **new_socket,
+		    int flags)
+{
+	struct socket *sock, *newsock;
+	int err;
+
+	sock = (struct socket *)socket;
+
+	/* the fields do not matter here. If we could, */
+	/* we would call sock_alloc but it's not exported. */
+	err = sock_create_lite(0, 0, 0, &newsock);
+	if (err < 0)
+		return err;
+	newsock->type = sock->type;
+	newsock->ops = sock->ops;
+
+	err = sock->ops->accept(sock, newsock, flags);
+	if (err < 0) {
+		sock_release(newsock);
+		return err;
+	}
+	*new_socket = (struct SimSocket *)newsock;
+	return 0;
+}
+int lib_sock_ioctl(struct SimSocket *socket, int request, char *argp)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sock *sk;
+	struct net *net;
+	int err;
+
+	sk = sock->sk;
+	net = sock_net(sk);
+
+	err = sock->ops->ioctl(sock, request, (long)argp);
+
+	/*
+	 * If this ioctl is unknown try to hand it down
+	 * to the NIC driver.
+	 */
+	if (err == -ENOIOCTLCMD)
+		err = dev_ioctl(net, request, argp);
+	return err;
+}
+int lib_sock_setsockopt(struct SimSocket *socket, int level, int optname,
+			const void *optval, int optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	char *coptval = (char *)optval;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_setsockopt(sock, level, optname, coptval, optlen);
+	else
+		err = sock->ops->setsockopt(sock, level, optname, coptval,
+					    optlen);
+	return err;
+}
+int lib_sock_getsockopt(struct SimSocket *socket, int level, int optname,
+			void *optval, int *optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_getsockopt(sock, level, optname, optval, optlen);
+	else
+		err =
+			sock->ops->getsockopt(sock, level, optname, optval,
+					      optlen);
+	return err;
+}
+
+int lib_sock_canrecv(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct inet_connection_sock *icsk;
+
+	switch (sock->sk->sk_state) {
+	case TCP_CLOSE:
+		if (SOCK_STREAM == sock->sk->sk_type)
+			return 1;
+	case TCP_ESTABLISHED:
+		return sock->sk->sk_receive_queue.qlen > 0;
+	case TCP_SYN_SENT:
+	case TCP_SYN_RECV:
+	case TCP_LAST_ACK:
+	case TCP_CLOSING:
+		return 0;
+	case TCP_FIN_WAIT1:
+	case TCP_FIN_WAIT2:
+	case TCP_TIME_WAIT:
+	case TCP_CLOSE_WAIT:
+		return 1;
+	case TCP_LISTEN:
+	{
+		icsk = inet_csk(sock->sk);
+		return !reqsk_queue_empty(&icsk->icsk_accept_queue);
+	}
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+int lib_sock_cansend(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+
+	return sock_writeable(sock->sk);
+}
+
+/**
+ * Struct used to pass pool table context between DCE and Kernel and back from
+ * Kernel to DCE
+ *
+ * When calling sock_poll we provide in ret field the wanted eventmask, and in
+ * the opaque field the DCE poll table
+ *
+ * if a corresponding event occurs later, the PollEvent will be called by kernel
+ * with the DCE poll table in context variable, then we will able to wake up the
+ * thread blocked in poll call.
+ *
+ * Back from sock_poll method the kernel change ret field with the response from
+ * poll return of the corresponding kernel socket, and in opaque field there is
+ * a reference to the kernel poll table we will use this reference to remove us
+ * from the file wait queue when ending the DCE poll call or when ending the DCE
+ * process which is currently polling.
+ *
+ */
+struct poll_table_ref {
+	int ret;
+	void *opaque;
+};
+
+/* Because the poll main loop code is in NS3/DCE we have only on entry
+   in our kernel poll table */
+struct lib_ptable_entry {
+	wait_queue_t wait;
+	wait_queue_head_t *wait_address;
+	int eventMask;  /* Poll wanted event mask. */
+	void *opaque;   /* Pointeur to DCE poll table */
+};
+
+static int lib_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)wait->private;
+
+	/* Filter only wanted events */
+	if (key && !((unsigned long)key & entry->eventMask))
+		return 0;
+
+	lib_poll_event((unsigned long)key, entry->opaque);
+	return 1;
+}
+
+static void lib_pollwait(struct file *filp, wait_queue_head_t *wait_address,
+			 poll_table *p)
+{
+	struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)
+		lib_malloc(sizeof(struct lib_ptable_entry));
+	struct poll_table_ref *fromDCE =  (struct poll_table_ref *)pwq->table;
+
+	if (!entry)
+		return;
+
+	entry->opaque = fromDCE->opaque; /* Copy DCE poll table reference */
+	entry->eventMask = fromDCE->ret; /* Copy poll mask of wanted events. */
+
+	pwq->table = (struct poll_table_page *)entry;
+
+	init_waitqueue_func_entry(&entry->wait, lib_pollwake);
+	entry->wait.private = entry;
+	entry->wait_address = wait_address;
+	add_wait_queue(wait_address, &entry->wait);
+}
+
+void dce_poll_initwait(struct poll_wqueues *pwq)
+{
+	init_poll_funcptr(&pwq->pt, lib_pollwait);
+	pwq->polling_task = current;
+	pwq->triggered = 0;
+	pwq->error = 0;
+	pwq->table = NULL;
+	pwq->inline_index = 0;
+}
+
+/* call poll on socket ... */
+void lib_sock_poll(struct SimSocket *socket, struct poll_table_ref *ret)
+{
+	struct socket *sock = (struct socket *)socket;
+	/* Provide a fake file structure */
+	struct file zero;
+	poll_table *pwait = 0;
+	struct poll_wqueues *ptable = 0;
+
+	lib_memset(&zero, 0, sizeof(struct file));
+
+	if (ret->opaque) {
+		ptable =
+			(struct poll_wqueues *)lib_malloc(sizeof(struct
+								 poll_wqueues));
+		if (!ptable)
+			return;
+
+		dce_poll_initwait(ptable);
+
+		pwait = &(ptable->pt);
+		/* Pass the DCE pool table to lib_pollwait function */
+		ptable->table = (struct poll_table_page *)ret;
+	}
+
+	ret->ret = sock->ops->poll(&zero, sock, pwait);
+	/* Pass back the kernel poll table to DCE in order to DCE to */
+	/* remove from wait queue */
+	/* using lib_sock_pollfreewait method below */
+	ret->opaque = ptable;
+}
+
+void lib_sock_pollfreewait(void *polltable)
+{
+	struct poll_wqueues *ptable = (struct poll_wqueues *)polltable;
+
+	if (ptable && ptable->table) {
+		struct lib_ptable_entry *entry =
+			(struct lib_ptable_entry *)ptable->table;
+		remove_wait_queue(entry->wait_address, &entry->wait);
+		lib_free(entry);
+	}
+	lib_free(ptable);
+}
+
+
+
+
diff --git a/arch/lib/lib.c b/arch/lib/lib.c
new file mode 100644
index 0000000..52d638e
--- /dev/null
+++ b/arch/lib/lib.c
@@ -0,0 +1,294 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/init.h>         /* initcall_t */
+#include <linux/kernel.h>       /* SYSTEM_BOOTING */
+#include <linux/sched.h>        /* struct task_struct */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <drivers/base/base.h>
+#include <linux/idr.h>
+#include <linux/rcupdate.h>
+#include "sim-init.h"
+#include "sim.h"
+
+enum system_states system_state = SYSTEM_BOOTING;
+/* glues */
+struct task_struct init_task;
+
+struct SimImported g_imported;
+
+
+#define RETURN_void(rettype, v)				     \
+	({						     \
+		(v);					     \
+		lib_softirq_wakeup();			     \
+	})
+
+#define RETURN_nvoid(rettype, v)			     \
+	({						     \
+		rettype x = (v);			     \
+		lib_softirq_wakeup();			     \
+		x;					     \
+	})
+
+#define FORWARDER1(name, type, rettype, t0)			    \
+	extern rettype name(t0);				    \
+	static rettype name ## _forwarder(t0 v0)		    \
+	{							    \
+		lib_update_jiffies();				    \
+		return RETURN_ ## type(rettype, (name(v0)));        \
+	}
+
+#define FORWARDER2(name, type, rettype, t0, t1)				\
+	extern rettype name(t0, t1);					\
+	static rettype name ## _forwarder(t0 v0, t1 v1)			\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1)));	\
+	}
+#define FORWARDER3(name, type, rettype, t0, t1, t2)			\
+	extern rettype name(t0, t1, t2);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2)		\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2)));	\
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER5(name, type, rettype, t0, t1, t2, t3, t4)		\
+	extern rettype name(t0, t1, t2, t3, t4);			\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3, t4 v4) \
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3, v4))); \
+	}
+
+FORWARDER3(lib_dev_create, nvoid, struct SimDevice *, const char *, void *,
+	   enum SimDevFlags);
+FORWARDER1(lib_dev_destroy, void, void, struct SimDevice *);
+FORWARDER2(lib_dev_set_address, void, void, struct SimDevice *,
+	   unsigned char *);
+FORWARDER2(lib_dev_set_mtu, void, void, struct SimDevice *, int);
+FORWARDER2(lib_dev_create_packet, nvoid, struct SimDevicePacket,
+	   struct SimDevice *, int);
+FORWARDER2(lib_dev_rx, void, void, struct SimDevice *, struct SimDevicePacket);
+
+FORWARDER4(lib_sock_socket, nvoid, int, int, int, int, struct SimSocket **);
+FORWARDER1(lib_sock_close, nvoid, int, struct SimSocket *);
+FORWARDER3(lib_sock_recvmsg, nvoid, ssize_t, struct SimSocket *,
+	   struct msghdr *, int);
+FORWARDER3(lib_sock_sendmsg, nvoid, ssize_t, struct SimSocket *,
+	   const struct msghdr *, int);
+FORWARDER3(lib_sock_getsockname, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_getpeername, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_bind, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int);
+FORWARDER4(lib_sock_connect, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int, int);
+FORWARDER2(lib_sock_listen, nvoid, int, struct SimSocket *, int);
+FORWARDER2(lib_sock_shutdown, nvoid, int, struct SimSocket *, int);
+FORWARDER3(lib_sock_accept, nvoid, int, struct SimSocket *,
+	   struct SimSocket **, int);
+FORWARDER3(lib_sock_ioctl, nvoid, int, struct SimSocket *, int, char *);
+FORWARDER5(lib_sock_setsockopt, nvoid, int, struct SimSocket *, int, int,
+	   const void *, int);
+FORWARDER5(lib_sock_getsockopt, nvoid, int, struct SimSocket *, int, int,
+	   void *, int *);
+
+FORWARDER2(lib_sock_poll, void, void, struct SimSocket *, void *);
+FORWARDER1(lib_sock_pollfreewait, void, void, void *);
+
+FORWARDER1(lib_sys_iterate_files, void, void, const struct SimSysIterator *);
+FORWARDER4(lib_sys_file_read, nvoid, int, const struct SimSysFile *, char *,
+	   int, int);
+FORWARDER4(lib_sys_file_write, nvoid, int, const struct SimSysFile *,
+	   const char *, int, int);
+
+struct SimKernel *g_kernel;
+
+void lib_init(struct SimExported *exported, const struct SimImported *imported,
+	      struct SimKernel *kernel)
+{
+	/* make sure we can call the callbacks */
+	g_imported = *imported;
+	g_kernel = kernel;
+	exported->task_create = lib_task_create;
+	exported->task_destroy = lib_task_destroy;
+	exported->task_get_private = lib_task_get_private;
+	exported->sock_socket = lib_sock_socket_forwarder;
+	exported->sock_close = lib_sock_close_forwarder;
+	exported->sock_recvmsg = lib_sock_recvmsg_forwarder;
+	exported->sock_sendmsg = lib_sock_sendmsg_forwarder;
+	exported->sock_getsockname = lib_sock_getsockname_forwarder;
+	exported->sock_getpeername = lib_sock_getpeername_forwarder;
+	exported->sock_bind = lib_sock_bind_forwarder;
+	exported->sock_connect = lib_sock_connect_forwarder;
+	exported->sock_listen = lib_sock_listen_forwarder;
+	exported->sock_shutdown = lib_sock_shutdown_forwarder;
+	exported->sock_accept = lib_sock_accept_forwarder;
+	exported->sock_ioctl = lib_sock_ioctl_forwarder;
+	exported->sock_setsockopt = lib_sock_setsockopt_forwarder;
+	exported->sock_getsockopt = lib_sock_getsockopt_forwarder;
+
+	exported->sock_poll = lib_sock_poll_forwarder;
+	exported->sock_pollfreewait = lib_sock_pollfreewait_forwarder;
+
+	exported->dev_create = lib_dev_create_forwarder;
+	exported->dev_destroy = lib_dev_destroy_forwarder;
+	exported->dev_get_private = lib_dev_get_private;
+	exported->dev_set_address = lib_dev_set_address_forwarder;
+	exported->dev_set_mtu = lib_dev_set_mtu_forwarder;
+	exported->dev_create_packet = lib_dev_create_packet_forwarder;
+	exported->dev_rx = lib_dev_rx_forwarder;
+
+	exported->sys_iterate_files = lib_sys_iterate_files_forwarder;
+	exported->sys_file_write = lib_sys_file_write_forwarder;
+	exported->sys_file_read = lib_sys_file_read_forwarder;
+
+	pr_notice("%s", linux_banner);
+
+	rcu_init();
+
+	/* in drivers/base/core.c (called normally by drivers/base/init.c) */
+	devices_init();
+	/* in lib/idr.c (called normally by init/main.c) */
+	idr_init_cache();
+	vfs_caches_init(totalram_pages);
+
+	lib_proc_net_initialize();
+
+	/* and, then, call the normal initcalls */
+	initcall_t *call;
+	extern initcall_t __initcall_start[], __initcall_end[];
+
+	call = __initcall_start;
+	do {
+		(*call)();
+		call++;
+	} while (call < __initcall_end);
+
+	/* finally, put the system in RUNNING state. */
+	system_state = SYSTEM_RUNNING;
+}
+
+int lib_vprintf(const char *str, va_list args)
+{
+	return g_imported.vprintf(g_kernel, str, args);
+}
+void *lib_malloc(unsigned long size)
+{
+	return g_imported.malloc(g_kernel, size);
+}
+void lib_free(void *buffer)
+{
+	return g_imported.free(g_kernel, buffer);
+}
+void *lib_memcpy(void *dst, const void *src, unsigned long size)
+{
+	return g_imported.memcpy(g_kernel, dst, src, size);
+}
+void *lib_memset(void *dst, char value, unsigned long size)
+{
+	return g_imported.memset(g_kernel, dst, value, size);
+}
+unsigned long lib_random(void)
+{
+	return g_imported.random(g_kernel);
+}
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context), void *context)
+{
+	return g_imported.event_schedule_ns(g_kernel, ns, fn, context,
+					    lib_update_jiffies);
+}
+void lib_event_cancel(void *event)
+{
+	return g_imported.event_cancel(g_kernel, event);
+}
+__u64 lib_current_ns(void)
+{
+	return g_imported.current_ns(g_kernel);
+}
+struct SimTaskTrampolineContext {
+	void (*callback)(void *);
+	void *context;
+};
+static void lib_task_start_trampoline(void *context)
+{
+	/* we use this trampoline solely for the purpose of executing
+	   lib_update_jiffies prior to calling the callback. */
+	struct SimTaskTrampolineContext *ctx = context;
+	void (*callback)(void *) = ctx->callback;
+	void *callback_context = ctx->context;
+
+	lib_free(ctx);
+	lib_update_jiffies();
+	callback(callback_context);
+}
+struct SimTask *lib_task_start(void (*callback) (void *), void *context)
+{
+	struct SimTaskTrampolineContext *ctx =
+		lib_malloc(sizeof(struct SimTaskTrampolineContext));
+
+	if (!ctx)
+		return NULL;
+	ctx->callback = callback;
+	ctx->context = context;
+	return g_imported.task_start(g_kernel, &lib_task_start_trampoline, ctx);
+}
+void lib_task_wait(void)
+{
+	rcu_sched_qs();
+	g_imported.task_wait(g_kernel);
+	lib_update_jiffies();
+}
+struct SimTask *lib_task_current(void)
+{
+	return g_imported.task_current(g_kernel);
+}
+int lib_task_wakeup(struct SimTask *task)
+{
+	return g_imported.task_wakeup(g_kernel, task);
+}
+void lib_task_yield(void)
+{
+	rcu_idle_enter();
+	g_imported.task_yield(g_kernel);
+	rcu_idle_exit();
+	lib_update_jiffies();
+}
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len)
+{
+	return g_imported.dev_xmit(g_kernel, dev, data, len);
+}
+
+void lib_signal_raised(struct SimTask *task, int sig)
+{
+	g_imported.signal_raised(g_kernel, task, sig);
+}
+
+void lib_poll_event(int flag, void *context)
+{
+	g_imported.poll_event(flag, context);
+}
diff --git a/arch/lib/lib.h b/arch/lib/lib.h
new file mode 100644
index 0000000..abf2a26
--- /dev/null
+++ b/arch/lib/lib.h
@@ -0,0 +1,21 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#ifndef LIB_H
+#define LIB_H
+
+#include <linux/sched.h>
+
+struct SimTask {
+	struct list_head head;
+	struct task_struct kernel_task;
+	void *private;
+};
+
+#endif /* LIB_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 04/11] lib: memory management (kernel glue code)
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (2 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 03/11] lib: public headers and API implementations for userspace programs Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 05/11] lib: time handling " Hajime Tazaki
                     ` (7 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/slab.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 203 insertions(+)
 create mode 100644 arch/lib/slab.c

diff --git a/arch/lib/slab.c b/arch/lib/slab.c
new file mode 100644
index 0000000..a08f736
--- /dev/null
+++ b/arch/lib/slab.c
@@ -0,0 +1,203 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/page-flags.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+/* glues */
+struct kmem_cache *files_cachep;
+
+void kfree(const void *p)
+{
+	unsigned long start;
+
+	if (p == 0)
+		return;
+	start = (unsigned long)p;
+	start -= sizeof(size_t);
+	lib_free((void *)start);
+}
+size_t ksize(const void *p)
+{
+	size_t *psize = (size_t *)p;
+
+	psize--;
+	return *psize;
+}
+void *__kmalloc(size_t size, gfp_t flags)
+{
+	void *p = lib_malloc(size + sizeof(size));
+	unsigned long start;
+
+	if (!p)
+		return NULL;
+
+	if (p != 0 && (flags & __GFP_ZERO))
+		lib_memset(p, 0, size + sizeof(size));
+	lib_memcpy(p, &size, sizeof(size));
+	start = (unsigned long)p;
+	return (void *)(start + sizeof(size));
+}
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
+{
+	return kmalloc(size, flags);
+}
+
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+
+	if (!new_size) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ret = __kmalloc(new_size, flags);
+	if (ret && p != ret)
+		kfree(p);
+
+	return ret;
+}
+
+struct kmem_cache *
+kmem_cache_create(const char *name, size_t size, size_t align,
+		  unsigned long flags, void (*ctor)(void *))
+{
+	struct kmem_cache *cache = kmalloc(sizeof(struct kmem_cache), flags);
+
+	if (!cache)
+		return NULL;
+	cache->name = name;
+	cache->size = size;
+	cache->align = align;
+	cache->flags = flags;
+	cache->ctor = ctor;
+	return cache;
+}
+void kmem_cache_destroy(struct kmem_cache *cache)
+{
+	kfree(cache);
+}
+int kmem_cache_shrink(struct kmem_cache *cache)
+{
+	return 1;
+}
+const char *kmem_cache_name(struct kmem_cache *cache)
+{
+	return cache->name;
+}
+void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+	void *p = kmalloc(cache->size, flags);
+
+	if (p == 0)
+		return NULL;
+	if (cache->ctor)
+		(cache->ctor)(p);
+	return p;
+
+}
+void kmem_cache_free(struct kmem_cache *cache, void *p)
+{
+	kfree(p);
+}
+
+struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+		       struct zonelist *zonelist, nodemask_t *nodemask)
+{
+	void *p;
+	struct page *page;
+	unsigned long pointer;
+
+	/* typically, called from networking code by alloc_page or */
+	/* directly with an order = 0. */
+	if (order)
+		return NULL;
+	p = lib_malloc(sizeof(struct page) + (1 << PAGE_SHIFT));
+	page = (struct page *)p;
+
+	atomic_set(&page->_count, 1);
+	page->flags = 0;
+	pointer = (unsigned long)page;
+	pointer += sizeof(struct page);
+	page->virtual = (void *)pointer;
+	return page;
+}
+void __free_pages(struct page *page, unsigned int order)
+{
+	/* typically, called from networking code by __free_page */
+	lib_assert(order == 0);
+	lib_free(page);
+}
+
+void put_page(struct page *page)
+{
+	if (atomic_dec_and_test(&page->_count))
+		lib_free(page);
+}
+unsigned long get_zeroed_page(gfp_t gfp_mask)
+{
+	return __get_free_pages(gfp_mask | __GFP_ZERO, 0);
+}
+
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+	return alloc_pages(gfp_mask, get_order(size));
+}
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+{
+	int size = (1 << order) * PAGE_SIZE;
+	void *p = kmalloc(size, gfp_mask);
+
+	return (unsigned long)p;
+}
+void free_pages(unsigned long addr, unsigned int order)
+{
+	if (addr != 0)
+		kfree((void *)addr);
+}
+
+void *vmalloc(unsigned long size)
+{
+	return lib_malloc(size);
+}
+void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return kmalloc(size, gfp_mask);
+}
+void vfree(const void *addr)
+{
+	lib_free((void *)addr);
+}
+void *vmalloc_node(unsigned long size, int node)
+{
+	return lib_malloc(size);
+}
+void vmalloc_sync_all(void)
+{
+}
+void *__alloc_percpu(size_t size, size_t align)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+void free_percpu(void __percpu *ptr)
+{
+	kfree(ptr);
+}
+void *__alloc_bootmem_nopanic(unsigned long size,
+			      unsigned long align,
+			      unsigned long goal)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 05/11] lib: time handling (kernel glue code)
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (3 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 04/11] lib: memory management (kernel glue code) Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 06/11] lib: context and scheduling " Hajime Tazaki
                     ` (6 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/hrtimer.c         | 122 +++++++++++++++++++++++
 arch/lib/tasklet-hrtimer.c |  57 +++++++++++
 arch/lib/time.c            | 144 +++++++++++++++++++++++++++
 arch/lib/timer.c           | 238 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 561 insertions(+)
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c

diff --git a/arch/lib/hrtimer.c b/arch/lib/hrtimer.c
new file mode 100644
index 0000000..4565b59
--- /dev/null
+++ b/arch/lib/hrtimer.c
@@ -0,0 +1,122 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/hrtimer.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ * @timer:      the timer to be initialized
+ * @clock_id:   the clock to be used
+ * @mode:       timer mode abs/rel
+ */
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+		  enum hrtimer_mode mode)
+{
+	memset(timer, 0, sizeof(*timer));
+}
+static void trampoline(void *context)
+{
+	struct hrtimer *timer = context;
+	enum hrtimer_restart restart = timer->function(timer);
+
+	if (restart == HRTIMER_RESTART) {
+		void *event =
+			lib_event_schedule_ns(ktime_to_ns(timer->_softexpires),
+					      &trampoline, timer);
+		timer->base = event;
+	} else {
+		/* mark as completed. */
+		timer->base = 0;
+	}
+}
+/**
+ * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
+ * @timer:      the timer to be added
+ * @tim:        expiry time
+ * @delta_ns:   "slack" range for the timer
+ * @mode:       expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
+ *
+ * Returns:
+ *  0 on success
+ *  1 when the timer was active
+ */
+int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			     unsigned long delta_ns,
+			     const enum hrtimer_mode mode,
+			     int wakeup)
+{
+	int ret = hrtimer_cancel(timer);
+	s64 ns = ktime_to_ns(tim);
+	void *event;
+
+	if (mode == HRTIMER_MODE_ABS)
+		ns -= lib_current_ns();
+	timer->_softexpires = ns_to_ktime(ns);
+	event = lib_event_schedule_ns(ns, &trampoline, timer);
+	timer->base = event;
+	return ret;
+}
+/**
+ * hrtimer_try_to_cancel - try to deactivate a timer
+ * @timer:      hrtimer to stop
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ * -1 when the timer is currently excuting the callback function and
+ *    cannot be stopped
+ */
+int hrtimer_try_to_cancel(struct hrtimer *timer)
+{
+	/* Note: we cannot return -1 from this function.
+	   see comment in hrtimer_cancel. */
+	if (timer->base == 0)
+		/* timer was not active yet */
+		return 1;
+	lib_event_cancel(timer->base);
+	timer->base = 0;
+	return 0;
+}
+/**
+ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
+ * @timer:      the timer to be cancelled
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ */
+int hrtimer_cancel(struct hrtimer *timer)
+{
+	/* Note: because we assume a uniprocessor non-interruptible */
+	/* system when running in the kernel, we know that the timer */
+	/* is not running when we execute this code, so, know that */
+	/* try_to_cancel cannot return -1 and we don't need to retry */
+	/* the cancel later to wait for the handler to finish. */
+	int ret = hrtimer_try_to_cancel(timer);
+
+	lib_assert(ret >= 0);
+	return ret;
+}
+int
+hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
+}
+int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			   unsigned long delta_ns, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, delta_ns, mode, 1);
+}
+
+int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+{
+	*tp = ns_to_timespec(1);
+	return 0;
+}
diff --git a/arch/lib/tasklet-hrtimer.c b/arch/lib/tasklet-hrtimer.c
new file mode 100644
index 0000000..fef4902
--- /dev/null
+++ b/arch/lib/tasklet-hrtimer.c
@@ -0,0 +1,57 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
+{
+	struct tasklet_hrtimer *ttimer =
+		container_of(timer, struct tasklet_hrtimer, timer);
+
+	tasklet_schedule(&ttimer->tasklet);
+	return HRTIMER_NORESTART;
+}
+static void __tasklet_hrtimer_trampoline(unsigned long data)
+{
+	struct tasklet_hrtimer *ttimer = (void *)data;
+	enum hrtimer_restart restart;
+
+	restart = ttimer->function(&ttimer->timer);
+	if (restart != HRTIMER_NORESTART)
+		hrtimer_restart(&ttimer->timer);
+}
+/**
+ * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
+ * @ttimer:      tasklet_hrtimer which is initialized
+ * @function:    hrtimer callback function which gets called from softirq context
+ * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
+ * @mode:        hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
+ */
+void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+			  enum hrtimer_restart (*function)(struct hrtimer *),
+			  clockid_t which_clock, enum hrtimer_mode mode)
+{
+	hrtimer_init(&ttimer->timer, which_clock, mode);
+	ttimer->timer.function = __hrtimer_tasklet_trampoline;
+	tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
+		     (unsigned long)ttimer);
+	ttimer->function = function;
+}
+
+void __tasklet_hi_schedule(struct tasklet_struct *t)
+{
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	void *event =
+		lib_event_schedule_ns(0, (void *)&t->func, (void *)t->data);
+	t->next = event;
+}
diff --git a/arch/lib/time.c b/arch/lib/time.c
new file mode 100644
index 0000000..b54be75
--- /dev/null
+++ b/arch/lib/time.c
@@ -0,0 +1,144 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/ktime.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+unsigned long volatile jiffies = INITIAL_JIFFIES;
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+struct timespec xtime;
+seqlock_t xtime_lock;
+/* accessed from wrap_clock from do_sys_settimeofday.
+   We don't call the latter so we should never access this variable. */
+struct timespec wall_to_monotonic;
+
+uint64_t ns_to_jiffies(uint64_t ns)
+{
+	do_div(ns, (1000000000 / HZ));
+	return ns;
+}
+
+void lib_update_jiffies(void)
+{
+	jiffies = ns_to_jiffies(lib_current_ns());
+	jiffies_64 = ns_to_jiffies(lib_current_ns());
+}
+
+struct timespec current_kernel_time(void)
+{
+	u64 ns = lib_current_ns();
+	struct timespec spec = ns_to_timespec(ns);
+
+	return spec;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	u64 ns = lib_current_ns();
+
+	*tv = ns_to_timeval(ns);
+}
+
+int do_adjtimex(struct timex *timex)
+{
+	lib_assert(false);
+	return -EPERM;
+}
+ktime_t ktime_get(void)
+{
+	u64 ns = lib_current_ns();
+
+	return ns_to_ktime(ns);
+}
+ktime_t ktime_get_with_offset(enum tk_offsets offs)
+{
+	/* FIXME */
+	return ktime_get();
+}
+
+/* copied from kernel/time/hrtimeer.c */
+#if BITS_PER_LONG < 64
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+u64 __ktime_divns(const ktime_t kt, s64 div)
+{
+	u64 dclc;
+	int sft = 0;
+
+	dclc = ktime_to_ns(kt);
+	/* Make sure the divisor is less than 2^32: */
+	while (div >> 32) {
+		sft++;
+		div >>= 1;
+	}
+	dclc >>= sft;
+	do_div(dclc, (unsigned long)div);
+
+	return dclc;
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+void update_xtime_cache(u64 nsec)
+{
+}
+unsigned long get_seconds(void)
+{
+	u64 ns = lib_current_ns();
+
+	do_div(ns, 1000000000);
+	return ns;
+}
+static unsigned long
+round_jiffies_common(unsigned long j,
+		     bool force_up)
+{
+	int rem;
+	unsigned long original = j;
+
+	rem = j % HZ;
+	if (rem < HZ / 4 && !force_up)  /* round down */
+		j = j - rem;
+	else                            /* round up */
+		j = j - rem + HZ;
+	if (j <= jiffies)               /* rounding ate our timeout entirely; */
+		return original;
+	return j;
+}
+unsigned long round_jiffies(unsigned long j)
+{
+	return round_jiffies_common(j, false);
+}
+unsigned long round_jiffies_relative(unsigned long j)
+{
+	unsigned long j0 = jiffies;
+
+	/* Use j0 because jiffies might change while we run */
+	return round_jiffies_common(j + j0, false) - j0;
+}
+unsigned long round_jiffies_up(unsigned long j)
+{
+	return round_jiffies_common(j, true);
+}
+static void msleep_trampoline(void *context)
+{
+	struct SimTask *task = context;
+
+	lib_task_wakeup(task);
+}
+void msleep(unsigned int msecs)
+{
+	lib_event_schedule_ns(((__u64)msecs) * 1000000, &msleep_trampoline,
+			      lib_task_current());
+	lib_task_wait();
+}
diff --git a/arch/lib/timer.c b/arch/lib/timer.c
new file mode 100644
index 0000000..87d2283
--- /dev/null
+++ b/arch/lib/timer.c
@@ -0,0 +1,238 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * init_timer_key - initialize a timer
+ * @timer: the timer to be initialized
+ * @name: name of the timer
+ * @key: lockdep class key of the fake lock used for tracking timer
+ *       sync lock dependencies
+ *
+ * init_timer_key() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void init_timer_key(struct timer_list *timer,
+		    unsigned int flags,
+		    const char *name,
+		    struct lock_class_key *key)
+{
+	/**
+	 * Note: name and key are used for debugging. We ignore them
+	 * unconditionally.
+	 * Note: we do not initialize the lockdep map either because we
+	 * don't care.
+	 * and, finally, we never care about the base field either.
+	 *
+	 * So, for now, we have a timer which is marked as "not started"
+	 * thanks to its entry.next field set to NULL (timer_pending
+	 * will return 0)
+	 */
+	timer->entry.next = NULL;
+	timer->base = 0;
+}
+
+struct list_head g_expired_events = LIST_HEAD_INIT(g_expired_events);
+struct list_head g_pending_events = LIST_HEAD_INIT(g_pending_events);
+
+static void run_timer_softirq(struct softirq_action *h)
+{
+	while (!list_empty(&g_expired_events)) {
+		struct timer_list *timer = list_first_entry(&g_expired_events,
+							    struct timer_list,
+							    entry);
+		void (*fn)(unsigned long);
+		unsigned long data;
+
+		fn = timer->function;
+		data = timer->data;
+		lib_assert(timer->base == 0);
+		if (timer->entry.prev != LIST_POISON2) {
+			list_del(&timer->entry);
+			timer->entry.next = NULL;
+			fn(data);
+		}
+	}
+}
+
+static void ensure_softirq_opened(void)
+{
+	static bool opened = false;
+
+	if (opened)
+		return;
+	opened = true;
+	open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
+}
+static void timer_trampoline(void *context)
+{
+	struct timer_list *timer;
+
+	ensure_softirq_opened();
+	timer = context;
+	timer->base = 0;
+	if (timer->entry.prev != LIST_POISON2)
+		list_del(&timer->entry);
+	list_add_tail(&timer->entry, &g_expired_events);
+	raise_softirq(TIMER_SOFTIRQ);
+}
+/**
+ * add_timer - start a timer
+ * @timer: the timer to be added
+ *
+ * The kernel will do a ->function(->data) callback from the
+ * timer interrupt at the ->expires point in the future. The
+ * current time is 'jiffies'.
+ *
+ * The timer's ->expires, ->function (and if the handler uses it, ->data)
+ * fields must be set prior calling this function.
+ *
+ * Timers with an ->expires field in the past will be executed in the next
+ * timer tick.
+ */
+void add_timer(struct timer_list *timer)
+{
+	__u64 delay_ns = 0;
+
+	lib_assert(!timer_pending(timer));
+	if (timer->expires <= jiffies)
+		delay_ns = (1000000000 / HZ); /* next tick. */
+	else
+		delay_ns =
+			((__u64)timer->expires *
+			 (1000000000 / HZ)) - lib_current_ns();
+	void *event = lib_event_schedule_ns(delay_ns, &timer_trampoline, timer);
+	/* store the external event in the base field */
+	/* to be able to retrieve it from del_timer */
+	timer->base = event;
+	/* finally, store timer in list of pending events. */
+	list_add_tail(&timer->entry, &g_pending_events);
+}
+/**
+ * del_timer - deactive a timer.
+ * @timer: the timer to be deactivated
+ *
+ * del_timer() deactivates a timer - this works on both active and inactive
+ * timers.
+ *
+ * The function returns whether it has deactivated a pending timer or not.
+ * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
+ * active timer returns 1.)
+ */
+int del_timer(struct timer_list *timer)
+{
+	int retval;
+
+	if (timer->entry.next == 0)
+		return 0;
+	if (timer->base != 0) {
+		lib_event_cancel(timer->base);
+		retval = 1;
+	} else
+		retval = 0;
+	if (timer->entry.prev != LIST_POISON2) {
+		list_del(&timer->entry);
+		timer->entry.next = NULL;
+	}
+	return retval;
+}
+
+/* ////////////////////// */
+
+void init_timer_deferrable_key(struct timer_list *timer,
+			       const char *name,
+			       struct lock_class_key *key)
+{
+	/**
+	 * From lwn.net:
+	 * Timers which are initialized in this fashion will be
+	 * recognized as deferrable by the kernel. They will not
+	 * be considered when the kernel makes its "when should
+	 * the next timer interrupt be?" decision. When the system
+	 * is busy these timers will fire at the scheduled time. When
+	 * things are idle, instead, they will simply wait until
+	 * something more important wakes up the processor.
+	 *
+	 * Note: Our implementation of deferrable timers uses
+	 * non-deferrable timers for simplicity.
+	 */
+	init_timer_key(timer, 0, name, key);
+}
+/**
+ * add_timer_on - start a timer on a particular CPU
+ * @timer: the timer to be added
+ * @cpu: the CPU to start it on
+ *
+ * This is not very scalable on SMP. Double adds are not possible.
+ */
+void add_timer_on(struct timer_list *timer, int cpu)
+{
+	/* we ignore the cpu: we have only one. */
+	add_timer(timer);
+}
+/**
+ * mod_timer - modify a timer's timeout
+ * @timer: the timer to be modified
+ * @expires: new timeout in jiffies
+ *
+ * mod_timer() is a more efficient way to update the expire field of an
+ * active timer (if the timer is inactive it will be activated)
+ *
+ * mod_timer(timer, expires) is equivalent to:
+ *
+ *     del_timer(timer); timer->expires = expires; add_timer(timer);
+ *
+ * Note that if there are multiple unserialized concurrent users of the
+ * same timer, then mod_timer() is the only safe way to modify the timeout,
+ * since add_timer() cannot modify an already running timer.
+ *
+ * The function returns whether it has modified a pending timer or not.
+ * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
+ * active timer returns 1.)
+ */
+int mod_timer(struct timer_list *timer, unsigned long expires)
+{
+	int ret;
+
+	/* common optimization stolen from kernel */
+	if (timer_pending(timer) && timer->expires == expires)
+		return 1;
+
+	ret = del_timer(timer);
+	timer->expires = expires;
+	add_timer(timer);
+	return ret;
+}
+/**
+ * mod_timer_pending - modify a pending timer's timeout
+ * @timer: the pending timer to be modified
+ * @expires: new timeout in jiffies
+ *
+ * mod_timer_pending() is the same for pending timers as mod_timer(),
+ * but will not re-activate and modify already deleted timers.
+ *
+ * It is useful for unserialized use of timers.
+ */
+int mod_timer_pending(struct timer_list *timer, unsigned long expires)
+{
+	if (timer_pending(timer))
+		return 0;
+	return mod_timer(timer, expires);
+}
+
+int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
+{
+	if (timer->expires == expires && timer_pending(timer))
+		return 1;
+
+	return mod_timer(timer, expires);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 06/11] lib: context and scheduling handling (kernel glue code)
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (4 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 05/11] lib: time handling " Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 07/11] lib: sysctl " Hajime Tazaki
                     ` (5 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/sched.c     | 406 +++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/softirq.c   | 108 ++++++++++++++
 arch/lib/tasklet.c   |  76 ++++++++++
 arch/lib/workqueue.c | 242 ++++++++++++++++++++++++++++++
 4 files changed, 832 insertions(+)
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/workqueue.c

diff --git a/arch/lib/sched.c b/arch/lib/sched.c
new file mode 100644
index 0000000..98a568a
--- /dev/null
+++ b/arch/lib/sched.c
@@ -0,0 +1,406 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+#include <linux/hash.h>
+#include <net/net_namespace.h>
+#include "lib.h"
+#include "sim.h"
+#include "sim-assert.h"
+
+/**
+   called by wait_event macro:
+   - prepare_to_wait
+   - schedule
+   - finish_wait
+ */
+
+struct SimTask *lib_task_create(void *private, unsigned long pid)
+{
+	struct SimTask *task = lib_malloc(sizeof(struct SimTask));
+	struct cred *cred;
+	struct nsproxy *ns;
+	struct user_struct *user;
+	struct thread_info *info;
+	struct pid *kpid;
+
+	if (!task)
+		return NULL;
+	memset(task, 0, sizeof(struct SimTask));
+	cred = lib_malloc(sizeof(struct cred));
+	if (!cred)
+		return NULL;
+	/* XXX: we could optimize away this allocation by sharing it
+	   for all tasks */
+	ns = lib_malloc(sizeof(struct nsproxy));
+	if (!ns)
+		return NULL;
+	user = lib_malloc(sizeof(struct user_struct));
+	if (!user)
+		return NULL;
+	info = alloc_thread_info(&task->kernel_task);
+	if (!info)
+		return NULL;
+	kpid = lib_malloc(sizeof(struct pid));
+	if (!kpid)
+		return NULL;
+	kpid->numbers[0].nr = pid;
+	cred->fsuid = make_kuid(current_user_ns(), 0);
+	cred->fsgid = make_kgid(current_user_ns(), 0);
+	cred->user = user;
+	atomic_set(&cred->usage, 1);
+	info->task = &task->kernel_task;
+	info->preempt_count = 0;
+	info->flags = 0;
+	atomic_set(&ns->count, 1);
+	ns->uts_ns = 0;
+	ns->ipc_ns = 0;
+	ns->mnt_ns = 0;
+	ns->pid_ns_for_children = 0;
+	ns->net_ns = &init_net;
+	task->kernel_task.cred = cred;
+	task->kernel_task.pid = pid;
+	task->kernel_task.pids[PIDTYPE_PID].pid = kpid;
+	task->kernel_task.pids[PIDTYPE_PGID].pid = kpid;
+	task->kernel_task.pids[PIDTYPE_SID].pid = kpid;
+	task->kernel_task.nsproxy = ns;
+	task->kernel_task.stack = info;
+	/* this is a hack. */
+	task->kernel_task.group_leader = &task->kernel_task;
+	task->private = private;
+	return task;
+}
+void lib_task_destroy(struct SimTask *task)
+{
+	lib_free((void *)task->kernel_task.nsproxy);
+	lib_free((void *)task->kernel_task.cred);
+	lib_free((void *)task->kernel_task.cred->user);
+	free_thread_info(task->kernel_task.stack);
+	lib_free(task);
+}
+void *lib_task_get_private(struct SimTask *task)
+{
+	return task->private;
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct SimTask *task = lib_task_start((void (*)(void *))fn, arg);
+
+	return task->kernel_task.pid;
+}
+
+struct task_struct *get_current(void)
+{
+	struct SimTask *lib_task = lib_task_current();
+
+	return &lib_task->kernel_task;
+}
+
+struct thread_info *current_thread_info(void)
+{
+	return task_thread_info(get_current());
+}
+struct thread_info *alloc_thread_info(struct task_struct *task)
+{
+	return lib_malloc(sizeof(struct thread_info));
+}
+void free_thread_info(struct thread_info *ti)
+{
+	lib_free(ti);
+}
+
+
+void __put_task_struct(struct task_struct *t)
+{
+	lib_free(t);
+}
+
+void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+	list_add(&wait->task_list, &q->task_list);
+}
+void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	list_add_tail(&wait->task_list, &q->task_list);
+}
+void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	if (wait->task_list.prev != LIST_POISON2)
+		list_del(&wait->task_list);
+}
+void
+prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	if (list_empty(&wait->task_list))
+		list_add_tail(&wait->task_list, &q->task_list);
+	set_current_state(state);
+}
+void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	unsigned long flags;
+
+	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+	spin_lock_irqsave(&q->lock, flags);
+	if (list_empty(&wait->task_list))
+		__add_wait_queue(q, wait);
+	set_current_state(state);
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	set_current_state(TASK_RUNNING);
+	if (!list_empty(&wait->task_list))
+		list_del_init(&wait->task_list);
+}
+int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync,
+			     void *key)
+{
+	int ret = default_wake_function(wait, mode, sync, key);
+
+	if (ret && (wait->task_list.prev != LIST_POISON2))
+		list_del_init(&wait->task_list);
+
+	return ret;
+}
+
+int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	wait->flags |= WQ_FLAG_WOKEN;
+	return default_wake_function(wait, mode, sync, key);
+}
+
+void __init_waitqueue_head(wait_queue_head_t *q, const char *name,
+			   struct lock_class_key *k)
+{
+	INIT_LIST_HEAD(&q->task_list);
+}
+/**
+ * wait_for_completion: - waits for completion of a task
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It is NOT
+ * interruptible and there is no timeout.
+ *
+ * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
+ * and interrupt capability. Also see complete().
+ */
+void wait_for_completion(struct completion *x)
+{
+	wait_for_completion_timeout(x, MAX_SCHEDULE_TIMEOUT);
+}
+unsigned long wait_for_completion_timeout(struct completion *x,
+					  unsigned long timeout)
+{
+	if (!x->done) {
+		DECLARE_WAITQUEUE(wait, current);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		wait.flags |= WQ_FLAG_EXCLUSIVE;
+		list_add_tail(&wait.task_list, &x->wait.task_list);
+		do
+			timeout = schedule_timeout(timeout);
+		while (!x->done && timeout);
+		if (wait.task_list.prev != LIST_POISON2)
+			list_del(&wait.task_list);
+
+		if (!x->done)
+			return timeout;
+	}
+	x->done--;
+	return timeout ? : 1;
+}
+
+/**
+ * __wake_up - wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ * @key: is directly passed to the wakeup function
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void __wake_up(wait_queue_head_t *q, unsigned int mode,
+	       int nr_exclusive, void *key)
+{
+	wait_queue_t *curr, *next;
+
+	list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
+		unsigned flags = curr->flags;
+
+		if (curr->func(curr, mode, 0, key) &&
+		    (flags & WQ_FLAG_EXCLUSIVE) &&
+		    !--nr_exclusive)
+			break;
+	}
+}
+void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
+			int nr_exclusive, void *key)
+{
+	__wake_up(q, mode, nr_exclusive, key);
+}
+int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
+			  void *key)
+{
+	struct task_struct *task = (struct task_struct *)curr->private;
+	struct SimTask *lib_task = container_of(task, struct SimTask,
+						kernel_task);
+
+	return lib_task_wakeup(lib_task);
+}
+__sched int bit_wait(struct wait_bit_key *word)
+{
+	if (signal_pending_state(current->state, current))
+		return 1;
+	schedule();
+	return 0;
+}
+int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *arg)
+{
+	struct wait_bit_key *key = arg;
+	struct wait_bit_queue *wait_bit
+		= container_of(wait, struct wait_bit_queue, wait);
+
+	if (wait_bit->key.flags != key->flags ||
+			wait_bit->key.bit_nr != key->bit_nr ||
+			test_bit(key->bit_nr, key->flags))
+		return 0;
+	else
+		return autoremove_wake_function(wait, mode, sync, key);
+}
+void __wake_up_bit(wait_queue_head_t *wq, void *word, int bit)
+{
+	struct wait_bit_key key = __WAIT_BIT_KEY_INITIALIZER(word, bit);
+	if (waitqueue_active(wq))
+		__wake_up(wq, TASK_NORMAL, 1, &key);
+}
+void wake_up_bit(void *word, int bit)
+{
+	/* FIXME */
+	return;
+	__wake_up_bit(bit_waitqueue(word, bit), word, bit);
+}
+wait_queue_head_t *bit_waitqueue(void *word, int bit)
+{
+	const int shift = BITS_PER_LONG == 32 ? 5 : 6;
+	const struct zone *zone = page_zone(virt_to_page(word));
+	unsigned long val = (unsigned long)word << shift | bit;
+
+	return &zone->wait_table[hash_long(val, zone->wait_table_bits)];
+}
+
+
+void schedule(void)
+{
+	lib_task_wait();
+}
+
+static void trampoline(void *context)
+{
+	struct SimTask *task = context;
+
+	lib_task_wakeup(task);
+}
+
+signed long schedule_timeout(signed long timeout)
+{
+	u64 ns;
+	struct SimTask *self;
+
+	if (timeout == MAX_SCHEDULE_TIMEOUT) {
+		lib_task_wait();
+		return MAX_SCHEDULE_TIMEOUT;
+	}
+	lib_assert(timeout >= 0);
+	ns = ((__u64)timeout) * (1000000000 / HZ);
+	self = lib_task_current();
+	lib_event_schedule_ns(ns, &trampoline, self);
+	lib_task_wait();
+	/* we know that we are always perfectly on time. */
+	return 0;
+}
+
+signed long schedule_timeout_uninterruptible(signed long timeout)
+{
+	return schedule_timeout(timeout);
+}
+signed long schedule_timeout_interruptible(signed long timeout)
+{
+	return schedule_timeout(timeout);
+}
+
+void yield(void)
+{
+	lib_task_yield();
+}
+
+void complete_all(struct completion *x)
+{
+	x->done += UINT_MAX / 2;
+	__wake_up(&x->wait, TASK_NORMAL, 0, 0);
+}
+void complete(struct completion *x)
+{
+	x->done++;
+	__wake_up(&x->wait, TASK_NORMAL, 1, 0);
+}
+
+long wait_for_completion_interruptible_timeout(
+	struct completion *x, unsigned long timeout)
+{
+	return wait_for_completion_timeout(x, timeout);
+}
+int wait_for_completion_interruptible(struct completion *x)
+{
+	wait_for_completion_timeout(x, MAX_SCHEDULE_TIMEOUT);
+	return 0;
+}
+int wake_up_process(struct task_struct *tsk)
+{
+	struct SimTask *lib_task =
+		container_of(tsk, struct SimTask, kernel_task);
+
+	return lib_task_wakeup(lib_task);
+}
+int _cond_resched(void)
+{
+	/* we never schedule to decrease latency. */
+	return 0;
+}
+int idle_cpu(int cpu)
+{
+	/* we are never idle: we call this from rcutiny.c and the answer */
+	/* does not matter, really. */
+	return 0;
+}
+
+unsigned long long __attribute__((weak)) sched_clock(void)
+{
+	return (unsigned long long)(jiffies - INITIAL_JIFFIES)
+	       * (NSEC_PER_SEC / HZ);
+}
+
+u64 local_clock(void)
+{
+	return sched_clock();
+}
+
+void __sched schedule_preempt_disabled(void)
+{
+}
+
+void resched_cpu(int cpu)
+{
+	rcu_sched_qs();
+}
diff --git a/arch/lib/softirq.c b/arch/lib/softirq.c
new file mode 100644
index 0000000..3f6363a
--- /dev/null
+++ b/arch/lib/softirq.c
@@ -0,0 +1,108 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim-init.h"
+#include "sim.h"
+#include "sim-assert.h"
+
+
+static struct softirq_action softirq_vec[NR_SOFTIRQS];
+static struct SimTask *g_softirq_task = 0;
+static int g_n_raises = 0;
+
+void lib_softirq_wakeup(void)
+{
+	g_n_raises++;
+	lib_task_wakeup(g_softirq_task);
+}
+
+static void softirq_task_function(void *context)
+{
+	while (true) {
+		do_softirq();
+		g_n_raises--;
+		if (g_n_raises == 0 || local_softirq_pending() == 0) {
+			g_n_raises = 0;
+			lib_task_wait();
+		}
+	}
+}
+
+static void ensure_task_created(void)
+{
+	if (g_softirq_task != 0)
+		return;
+	g_softirq_task = lib_task_start(&softirq_task_function, 0);
+}
+
+void open_softirq(int nr, void (*action)(struct softirq_action *))
+{
+	ensure_task_created();
+	softirq_vec[nr].action = action;
+}
+#define MAX_SOFTIRQ_RESTART 10
+
+void do_softirq(void)
+{
+	__u32 pending;
+	int max_restart = MAX_SOFTIRQ_RESTART;
+	struct softirq_action *h;
+
+	pending = local_softirq_pending();
+
+restart:
+	/* Reset the pending bitmask before enabling irqs */
+	set_softirq_pending(0);
+
+	local_irq_enable();
+
+	h = softirq_vec;
+
+	do {
+		if (pending & 1)
+			h->action(h);
+		h++;
+		pending >>= 1;
+	} while (pending);
+
+	local_irq_disable();
+
+	pending = local_softirq_pending();
+	if (pending && --max_restart)
+		goto restart;
+}
+void raise_softirq_irqoff(unsigned int nr)
+{
+	__raise_softirq_irqoff(nr);
+
+	lib_softirq_wakeup();
+}
+void __raise_softirq_irqoff(unsigned int nr)
+{
+	/* trace_softirq_raise(nr); */
+	or_softirq_pending(1UL << nr);
+}
+int __cond_resched_softirq(void)
+{
+	/* tell the caller that we did not need to re-schedule. */
+	return 0;
+}
+void raise_softirq(unsigned int nr)
+{
+	/* copy/paste from kernel/softirq.c */
+	unsigned long flags;
+
+	local_irq_save(flags);
+	raise_softirq_irqoff(nr);
+	local_irq_restore(flags);
+}
+
+void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
+{
+}
diff --git a/arch/lib/tasklet.c b/arch/lib/tasklet.c
new file mode 100644
index 0000000..6cc68f4
--- /dev/null
+++ b/arch/lib/tasklet.c
@@ -0,0 +1,76 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+void tasklet_init(struct tasklet_struct *t,
+		  void (*func)(unsigned long), unsigned long data)
+{
+	t->next = NULL;
+	t->state = 0;
+	atomic_set(&t->count, 0);
+	t->func = func;
+	t->data = data;
+}
+
+void tasklet_kill(struct tasklet_struct *t)
+{
+	/* theoretically, called from user context */
+	while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
+		do
+			lib_task_yield();
+		while (test_bit(TASKLET_STATE_SCHED, &t->state));
+	}
+	clear_bit(TASKLET_STATE_SCHED, &t->state);
+}
+struct tasklet_struct *g_sched_events = NULL;
+static void run_tasklet_softirq(struct softirq_action *h)
+{
+	/* while (!list_empty (&g_sched_events)) */
+	/*   { */
+	struct tasklet_struct *tasklet = g_sched_events;
+
+	if (atomic_read(&tasklet->count) == 0) {
+		/* this tasklet is enabled so, we run it. */
+		test_and_clear_bit(TASKLET_STATE_SCHED, &tasklet->state);
+		tasklet->func(tasklet->data);
+	}
+	/* } */
+}
+static void ensure_softirq_opened(void)
+{
+	static bool opened = false;
+
+	if (opened)
+		return;
+	opened = true;
+	open_softirq(TASKLET_SOFTIRQ, run_tasklet_softirq);
+}
+static void trampoline(void *context)
+{
+	ensure_softirq_opened();
+	struct tasklet_struct *tasklet = context;
+	/* allow the tasklet to re-schedule itself */
+	lib_assert(tasklet->next != 0);
+	tasklet->next = 0;
+	g_sched_events = tasklet;
+	raise_softirq(TASKLET_SOFTIRQ);
+}
+void __tasklet_schedule(struct tasklet_struct *t)
+{
+	void *event;
+
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	event = lib_event_schedule_ns(0, &trampoline, t);
+	t->next = event;
+}
diff --git a/arch/lib/workqueue.c b/arch/lib/workqueue.c
new file mode 100644
index 0000000..bd0e9c5
--- /dev/null
+++ b/arch/lib/workqueue.c
@@ -0,0 +1,242 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+/* copy from kernel/workqueue.c */
+typedef unsigned long mayday_mask_t;
+struct workqueue_struct {
+	unsigned int flags;                     /* W: WQ_* flags */
+	union {
+		struct cpu_workqueue_struct __percpu *pcpu;
+		struct cpu_workqueue_struct *single;
+		unsigned long v;
+	} cpu_wq;                               /* I: cwq's */
+	struct list_head list;                  /* W: list of all workqueues */
+
+	struct mutex flush_mutex;               /* protects wq flushing */
+	int work_color;                         /* F: current work color */
+	int flush_color;                        /* F: current flush color */
+	atomic_t nr_cwqs_to_flush;              /* flush in progress */
+	struct wq_flusher *first_flusher;       /* F: first flusher */
+	struct list_head flusher_queue;         /* F: flush waiters */
+	struct list_head flusher_overflow;      /* F: flush overflow list */
+
+	mayday_mask_t mayday_mask;              /* cpus requesting rescue */
+	struct worker *rescuer;                 /* I: rescue worker */
+
+	int nr_drainers;                        /* W: drain in progress */
+	int saved_max_active;                   /* W: saved cwq max_active */
+#ifdef CONFIG_LOCKDEP
+	struct lockdep_map lockdep_map;
+#endif
+	char name[];                            /* I: workqueue name */
+};
+
+struct wq_barrier {
+	struct SimTask *waiter;
+	struct workqueue_struct wq;
+};
+
+static void
+workqueue_function(void *context)
+{
+	struct workqueue_struct *wq = context;
+
+	while (true) {
+		lib_task_wait();
+		while (!list_empty(&wq->list)) {
+			struct work_struct *work =
+				list_first_entry(&wq->list, struct work_struct,
+						entry);
+			work_func_t f = work->func;
+
+			if (work->entry.prev != LIST_POISON2) {
+				list_del_init(&work->entry);
+				clear_bit(WORK_STRUCT_PENDING_BIT,
+					  work_data_bits(work));
+				f(work);
+			}
+		}
+	}
+}
+
+static struct SimTask *workqueue_task(struct workqueue_struct *wq)
+{
+	struct wq_barrier *barr = container_of(wq, struct wq_barrier, wq);
+
+	if (barr->waiter == 0)
+		barr->waiter = lib_task_start(&workqueue_function, wq);
+	return barr->waiter;
+}
+
+static int flush_entry(struct workqueue_struct *wq, struct list_head *prev)
+{
+	int active = 0;
+
+	if (!list_empty(&wq->list)) {
+		active = 1;
+		lib_task_wakeup(workqueue_task(wq));
+		/* XXX: should wait for completion? but this will block
+		   and init won't return.. */
+		/* lib_task_wait (); */
+	}
+
+	return active;
+}
+
+void delayed_work_timer_fn(unsigned long data)
+{
+	struct delayed_work *dwork = (struct delayed_work *)data;
+	struct work_struct *work = &dwork->work;
+
+	list_add_tail(&work->entry, &dwork->wq->list);
+	lib_task_wakeup(workqueue_task(dwork->wq));
+}
+
+bool queue_work_on(int cpu, struct workqueue_struct *wq,
+		   struct work_struct *work)
+{
+	int ret = 0;
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
+		list_add_tail(&work->entry, &wq->list);
+		lib_task_wakeup(workqueue_task(wq));
+		ret = 1;
+	}
+	return ret;
+}
+
+void flush_scheduled_work(void)
+{
+	flush_entry(system_wq, system_wq->list.prev);
+}
+bool flush_work(struct work_struct *work)
+{
+	return flush_entry(system_wq, &work->entry);
+}
+void flush_workqueue(struct workqueue_struct *wq)
+{
+	flush_entry(wq, wq->list.prev);
+}
+bool cancel_work_sync(struct work_struct *work)
+{
+	int retval = 0;
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)))
+		/* work was not yet queued */
+		return 0;
+	if (!list_empty(&work->entry)) {
+		/* work was queued. now unqueued. */
+		if (work->entry.prev != LIST_POISON2) {
+			list_del_init(&work->entry);
+			clear_bit(WORK_STRUCT_PENDING_BIT,
+				  work_data_bits(work));
+			retval = 1;
+		}
+	}
+	return retval;
+}
+bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+			   struct delayed_work *dwork, unsigned long delay)
+{
+	int ret = 0;
+	struct timer_list *timer = &dwork->timer;
+	struct work_struct *work = &dwork->work;
+
+	if (delay == 0)
+		return queue_work(wq, work);
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
+		lib_assert(!timer_pending(timer));
+		dwork->wq = wq;
+		/* This stores cwq for the moment, for the timer_fn */
+		timer->expires = jiffies + delay;
+		timer->data = (unsigned long)dwork;
+		timer->function = delayed_work_timer_fn;
+		add_timer(timer);
+		ret = 1;
+	}
+	return ret;
+}
+bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
+			 struct delayed_work *dwork, unsigned long delay)
+{
+	del_timer(&dwork->timer);
+	__clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&dwork->work));
+	return queue_delayed_work(wq, dwork, delay);
+}
+bool cancel_delayed_work(struct delayed_work *dwork)
+{
+	del_timer(&dwork->timer);
+	return cancel_work_sync(&dwork->work);
+}
+
+struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
+					       unsigned int flags,
+					       int max_active,
+					       struct lock_class_key *key,
+					       const char *lock_name, ...)
+{
+	va_list args, args1;
+	struct wq_barrier *barr;
+	struct workqueue_struct *wq;
+	size_t namelen;
+
+	/* determine namelen, allocate wq and format name */
+	va_start(args, lock_name);
+	va_copy(args1, args);
+	namelen = vsnprintf(NULL, 0, fmt, args) + 1;
+
+	barr = kzalloc(sizeof(*barr) + namelen, GFP_KERNEL);
+	if (!barr)
+		goto err;
+	barr->waiter = 0;
+	wq = &barr->wq;
+
+	vsnprintf(wq->name, namelen, fmt, args1);
+	va_end(args);
+	va_end(args1);
+
+	max_active = max_active ? : WQ_DFL_ACTIVE;
+	/* init wq */
+	wq->flags = flags;
+	wq->saved_max_active = max_active;
+	mutex_init(&wq->flush_mutex);
+	atomic_set(&wq->nr_cwqs_to_flush, 0);
+	INIT_LIST_HEAD(&wq->flusher_queue);
+	INIT_LIST_HEAD(&wq->flusher_overflow);
+
+	lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
+	INIT_LIST_HEAD(&wq->list);
+
+	/* start waiter task */
+	workqueue_task(wq);
+	return wq;
+err:
+	if (barr)
+		kfree(barr);
+	return NULL;
+}
+
+struct workqueue_struct *system_wq __read_mostly;
+struct workqueue_struct *system_power_efficient_wq __read_mostly;
+/* from linux/workqueue.h */
+#define system_nrt_wq                   __system_nrt_wq()
+
+static int __init init_workqueues(void)
+{
+	system_wq = alloc_workqueue("events", 0, 0);
+	system_power_efficient_wq = alloc_workqueue("events_power_efficient",
+						    WQ_POWER_EFFICIENT, 0);
+	return 0;
+}
+early_initcall(init_workqueues);
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 07/11] lib: sysctl handling (kernel glue code)
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (5 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 06/11] lib: context and scheduling " Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 08/11] lib: other kernel glue layer code Hajime Tazaki
                     ` (4 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

This interacts with fs/proc_fs.c for sysctl-like interface accessed via
lib_init() API.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/sysctl.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 270 insertions(+)
 create mode 100644 arch/lib/sysctl.c

diff --git a/arch/lib/sysctl.c b/arch/lib/sysctl.c
new file mode 100644
index 0000000..5f08f9f
--- /dev/null
+++ b/arch/lib/sysctl.c
@@ -0,0 +1,270 @@
+/*
+ * sysctl wrapper for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/mman.h>
+#include <linux/ratelimit.h>
+#include <linux/proc_fs.h>
+#include "sim-assert.h"
+#include "sim-types.h"
+
+int drop_caches_sysctl_handler(struct ctl_table *table, int write,
+			       void *buffer, size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *table, int write,
+					void *buffer, size_t *length,
+					loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write,
+					    void *buffer, size_t *length,
+					    loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_background_ratio_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *lenp,
+				   loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_background_bytes_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *lenp,
+				   loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_ratio_handler(struct ctl_table *table, int write,
+			void *buffer, size_t *lenp,
+			loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_bytes_handler(struct ctl_table *table, int write,
+			void *buffer, size_t *lenp,
+			loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_writeback_centisecs_handler(struct ctl_table *table, int write,
+				      void *buffer, size_t *length,
+				      loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int scan_unevictable_handler(struct ctl_table *table, int write,
+			     void __user *buffer,
+			     size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int sched_rt_handler(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS;
+int sysctl_overcommit_ratio = 50;
+int sysctl_panic_on_oom = 0;
+int sysctl_oom_dump_tasks = 0;
+int sysctl_oom_kill_allocating_task = 0;
+int sysctl_nr_trim_pages = 0;
+int sysctl_drop_caches = 0;
+int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES - 1] = { 32 };
+unsigned int sysctl_sched_child_runs_first = 0;
+unsigned int sysctl_sched_compat_yield = 0;
+unsigned int sysctl_sched_rt_period = 1000000;
+int sysctl_sched_rt_runtime = 950000;
+
+int vm_highmem_is_dirtyable;
+unsigned long vm_dirty_bytes = 0;
+int vm_dirty_ratio = 20;
+int dirty_background_ratio = 10;
+unsigned int dirty_expire_interval = 30 * 100;
+unsigned int dirty_writeback_interval = 5 * 100;
+unsigned long dirty_background_bytes = 0;
+int percpu_pagelist_fraction = 0;
+int panic_timeout = 0;
+int panic_on_oops = 0;
+int printk_delay_msec = 0;
+int panic_on_warn = 0;
+DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
+
+#define RESERVED_PIDS 300
+int pid_max = PID_MAX_DEFAULT;
+int pid_max_min = RESERVED_PIDS + 1;
+int pid_max_max = PID_MAX_LIMIT;
+int min_free_kbytes = 1024;
+int max_threads = 100;
+int laptop_mode = 0;
+
+#define DEFAULT_MESSAGE_LOGLEVEL 4
+#define MINIMUM_CONSOLE_LOGLEVEL 1
+#define DEFAULT_CONSOLE_LOGLEVEL 7
+int console_printk[4] = {
+	DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
+	DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
+	MINIMUM_CONSOLE_LOGLEVEL,       /* minimum_console_loglevel */
+	DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
+};
+
+int print_fatal_signals = 0;
+unsigned int core_pipe_limit = 0;
+int core_uses_pid = 0;
+int vm_swappiness = 60;
+int nr_pdflush_threads = 0;
+unsigned long scan_unevictable_pages = 0;
+int suid_dumpable = 0;
+int page_cluster = 0;
+int block_dump = 0;
+int C_A_D = 0;
+#include <linux/nsproxy.h>
+struct nsproxy init_nsproxy;
+#include <linux/reboot.h>
+char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
+unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
+unsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */
+
+int pdflush_proc_obsolete(struct ctl_table *table, int write,
+			  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return nr_pdflush_threads;
+}
+#include <linux/fs.h>
+
+/**
+ * Honestly, I don't understand half of that code.
+ * It was modeled after fs/proc/proc_sysctl.c proc_sys_readdir
+ *
+ * Me either ;) (Hajime, Jan 2013)
+ */
+
+/* from proc_sysctl.c (XXX) */
+extern struct ctl_table_root sysctl_table_root;
+void ctl_table_first_entry(struct ctl_dir *dir,
+		 struct ctl_table_header **phead, struct ctl_table **pentry);
+void ctl_table_next_entry(struct ctl_table_header **phead, struct ctl_table **pentry);
+struct ctl_table *ctl_table_find_entry(struct ctl_table_header **phead,
+			     struct ctl_dir *dir, const char *name,
+			     int namelen);
+struct ctl_dir *ctl_table_xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir);
+/* for init_net (XXX, should be fixed) */
+#include <net/net_namespace.h>
+
+static void iterate_table_recursive(const struct SimSysIterator *iter,
+				    struct ctl_table_header *head)
+{
+	struct ctl_table *entry;
+
+	for (entry = head->ctl_table; entry->procname; entry++) {
+		bool may_read = (head->ctl_table->mode & MAY_READ);
+		bool may_write = (head->ctl_table->mode & MAY_WRITE);
+		int flags = 0;
+
+		flags |= may_read ? SIM_SYS_FILE_READ : 0;
+		flags |= may_write ? SIM_SYS_FILE_WRITE : 0;
+		iter->report_file(iter, entry->procname, flags,
+				  (struct SimSysFile *)entry);
+	}
+}
+
+
+static void iterate_recursive(const struct SimSysIterator *iter,
+			      struct ctl_table_header *head)
+{
+	struct ctl_table_header *h = NULL;
+	struct ctl_table *entry;
+	struct ctl_dir *ctl_dir;
+
+	ctl_dir = container_of(head, struct ctl_dir, header);
+	for (ctl_table_first_entry(ctl_dir, &h, &entry); h;
+	     ctl_table_next_entry(&h, &entry)) {
+		struct ctl_dir *dir;
+		int ret;
+		const char *procname;
+
+		/* copy from sysctl_follow_link () */
+		if (S_ISLNK(entry->mode)) {
+			dir = ctl_table_xlate_dir(&init_net.sysctls, h->parent);
+			if (IS_ERR(dir)) {
+				ret = PTR_ERR(dir);
+				lib_assert(false);
+			} else {
+				procname = entry->procname;
+				h = NULL;
+				entry =
+					ctl_table_find_entry(&h, dir, procname,
+							     strlen(procname));
+				ret = -ENOENT;
+			}
+		}
+
+		if (S_ISDIR(entry->mode)) {
+			iter->report_start_dir(iter, entry->procname);
+			iterate_recursive(iter, h);
+			iter->report_end_dir(iter);
+		} else
+			iterate_table_recursive(iter, h);
+	}
+
+}
+
+
+void lib_sys_iterate_files(const struct SimSysIterator *iter)
+{
+	struct ctl_table_header *root =
+		&sysctl_table_root.default_set.dir.header;
+
+	iterate_recursive(iter, root);
+}
+
+int lib_sys_file_read(const struct SimSysFile *file, char *buffer, int size,
+		      int offset)
+{
+	struct ctl_table *table = (struct ctl_table *)file;
+	loff_t ppos = offset;
+	size_t result = size;
+	int error;
+
+	error = table->proc_handler(table, 0, buffer, &result, &ppos);
+	return result;
+}
+int lib_sys_file_write(const struct SimSysFile *file, const char *buffer,
+		       int size, int offset)
+{
+	struct ctl_table *table = (struct ctl_table *)file;
+	loff_t ppos = offset;
+	size_t result = size;
+	int error;
+
+	error = table->proc_handler(table, 1, (char *)buffer, &result, &ppos);
+	return result;
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 08/11] lib: other kernel glue layer code
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (6 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 07/11] lib: sysctl " Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 09/11] lib: asm-generic files Hajime Tazaki
                     ` (3 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

These files are used to provide the same function calls so that other
network stack code keeps untouched.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Christoph Paasch <christoph.paasch@gmail.com>
---
 arch/lib/capability.c |  47 +++++++++
 arch/lib/filemap.c    |  32 ++++++
 arch/lib/fs.c         |  70 +++++++++++++
 arch/lib/glue.c       | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/modules.c    |  36 +++++++
 arch/lib/pid.c        |  29 ++++++
 arch/lib/print.c      |  56 ++++++++++
 arch/lib/proc.c       |  34 ++++++
 arch/lib/random.c     |  53 ++++++++++
 arch/lib/sysfs.c      |  83 +++++++++++++++
 arch/lib/vmscan.c     |  26 +++++
 11 files changed, 749 insertions(+)
 create mode 100644 arch/lib/capability.c
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/vmscan.c

diff --git a/arch/lib/capability.c b/arch/lib/capability.c
new file mode 100644
index 0000000..7054fea
--- /dev/null
+++ b/arch/lib/capability.c
@@ -0,0 +1,47 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "linux/capability.h"
+
+struct sock;
+struct sk_buff;
+
+int file_caps_enabled = 0;
+
+bool capable(int cap)
+{
+	switch (cap) {
+	case CAP_NET_RAW:
+	case CAP_NET_BIND_SERVICE:
+	case CAP_NET_ADMIN:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int cap_netlink_recv(struct sk_buff *skb, int cap)
+{
+	return 0;
+}
+
+int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	return 0;
+}
+bool ns_capable(struct user_namespace *ns, int cap)
+{
+	return true;
+}
+bool file_ns_capable(const struct file *file, struct user_namespace *ns,
+		     int cap)
+{
+	return true;
+}
diff --git a/arch/lib/filemap.c b/arch/lib/filemap.c
new file mode 100644
index 0000000..ce424ff
--- /dev/null
+++ b/arch/lib/filemap.c
@@ -0,0 +1,32 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/fs.h>
+
+
+ssize_t generic_file_aio_read(struct kiocb *a, const struct iovec *b,
+			      unsigned long c, loff_t d)
+{
+	lib_assert(false);
+
+	return 0;
+}
+
+int generic_file_readonly_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return -ENOSYS;
+}
+
+ssize_t
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+	return 0;
+}
diff --git a/arch/lib/fs.c b/arch/lib/fs.c
new file mode 100644
index 0000000..324e10b
--- /dev/null
+++ b/arch/lib/fs.c
@@ -0,0 +1,70 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <fs/mount.h>
+
+#include "sim-assert.h"
+
+__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
+unsigned int dirtytime_expire_interval;
+
+void __init mnt_init(void)
+{
+}
+
+/* Implementation taken from vfs_kern_mount from linux/namespace.c */
+struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
+{
+	static struct mount local_mnt;
+	static int count = 0;
+	struct mount *mnt = &local_mnt;
+	struct dentry *root = 0;
+
+	/* XXX */
+	if (count != 0) return &local_mnt.mnt;
+	count++;
+
+	memset(mnt, 0, sizeof(struct mount));
+	if (!type)
+		return ERR_PTR(-ENODEV);
+	int flags = MS_KERNMOUNT;
+	char *name = (char *)type->name;
+
+	if (flags & MS_KERNMOUNT)
+		mnt->mnt.mnt_flags = MNT_INTERNAL;
+
+	root = type->mount(type, flags, name, data);
+	if (IS_ERR(root))
+		return ERR_CAST(root);
+
+	mnt->mnt.mnt_root = root;
+	mnt->mnt.mnt_sb = root->d_sb;
+	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+	mnt->mnt_parent = mnt;
+	/* DCE is monothreaded , so we do not care of lock here */
+	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
+
+	return &mnt->mnt;
+}
+void inode_wait_for_writeback(struct inode *inode)
+{
+}
+void truncate_inode_pages_final(struct address_space *mapping)
+{
+}
+int dirtytime_interval_handler(struct ctl_table *table, int write,
+			       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return -ENOSYS;
+}
+
+unsigned int nr_free_buffer_pages(void)
+{
+	return 1024;
+}
diff --git a/arch/lib/glue.c b/arch/lib/glue.c
new file mode 100644
index 0000000..928040d
--- /dev/null
+++ b/arch/lib/glue.c
@@ -0,0 +1,283 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <linux/types.h>        /* loff_t */
+#include <linux/errno.h>        /* ESPIPE */
+#include <linux/pagemap.h>      /* PAGE_CACHE_SIZE */
+#include <linux/limits.h>       /* NAME_MAX */
+#include <linux/statfs.h>       /* struct kstatfs */
+#include <linux/bootmem.h>      /* HASHDIST_DEFAULT */
+#include <linux/utsname.h>
+#include <linux/binfmts.h>
+#include <linux/init_task.h>
+#include <linux/sched/rt.h>
+#include <linux/backing-dev.h>
+#include <stdarg.h>
+#include "sim-assert.h"
+#include "sim.h"
+#include "lib.h"
+
+
+struct pipe_buffer;
+struct file;
+struct pipe_inode_info;
+struct wait_queue_t;
+struct kernel_param;
+struct super_block;
+struct tvec_base {};
+
+/* defined in sched.c, used in net/sched/em_meta.c */
+unsigned long avenrun[3];
+/* defined in mm/page_alloc.c, used in net/xfrm/xfrm_hash.c */
+int hashdist = HASHDIST_DEFAULT;
+/* defined in mm/page_alloc.c */
+struct pglist_data __refdata contig_page_data;
+/* defined in linux/mmzone.h mm/memory.c */
+struct page *mem_map = 0;
+/* used during boot. */
+struct tvec_base boot_tvec_bases;
+/* used by sysinfo in kernel/timer.c */
+int nr_threads = 0;
+/* not very useful in mm/vmstat.c */
+atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+
+/* XXX: used in network stack ! */
+unsigned long num_physpages = 0;
+unsigned long totalram_pages = 0;
+
+/* XXX figure out initial value */
+unsigned int interrupt_pending = 0;
+static unsigned long g_irqflags = 0;
+static unsigned long local_irqflags = 0;
+int overflowgid = 0;
+int overflowuid = 0;
+int fs_overflowgid = 0;
+int fs_overflowuid = 0;
+unsigned long sysctl_overcommit_kbytes __read_mostly;
+DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
+const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
+
+struct backing_dev_info noop_backing_dev_info = {
+	.name		= "noop",
+	.capabilities	= 0,
+};
+
+/* from rt.c */
+int sched_rr_timeslice = RR_TIMESLICE;
+/* from main.c */
+bool initcall_debug;
+bool static_key_initialized __read_mostly = false;
+unsigned long __start_rodata, __end_rodata;
+
+unsigned long arch_local_save_flags(void)
+{
+	return local_irqflags;
+}
+void arch_local_irq_restore(unsigned long flags)
+{
+	local_irqflags = flags;
+}
+
+
+unsigned long long nr_context_switches(void)
+{
+	/* we just need to return >0 to avoid the warning
+	   in kernel/rcupdate.c */
+	return 1;
+}
+
+
+long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+		    unsigned long start, unsigned long nr_pages,
+		    int write, int force, struct page **pages,
+		    struct vm_area_struct **vmas)
+{
+	/* in practice, this function is never called. It's linked in because */
+	/* we link in get_user_pages_fast which is included only because it */
+	/* is located in mm/util.c */
+	lib_assert(false);
+	return 0;
+}
+
+
+void dump_stack(void)
+{
+	/* we assert to make sure that we catch whoever calls dump_stack */
+	lib_assert(false);
+}
+
+
+void lib_printf(const char *str, ...)
+{
+	va_list args;
+
+	va_start(args, str);
+	lib_vprintf(str, args);
+	va_end(args);
+}
+
+#include <linux/vmalloc.h>
+#include <linux/kmemleak.h>
+
+static unsigned long __meminitdata nr_kernel_pages = 8192;
+static unsigned long __meminitdata nr_all_pages = 81920;
+/*
+ * allocate a large system hash table from bootmem
+ * - it is assumed that the hash table must contain an exact power-of-2
+ *   quantity of entries
+ * - limit is the number of hash buckets, not the total allocation size
+ */
+void *__init alloc_large_system_hash(const char *tablename,
+				     unsigned long bucketsize,
+				     unsigned long numentries,
+				     int scale,
+				     int flags,
+				     unsigned int *_hash_shift,
+				     unsigned int *_hash_mask,
+				     unsigned long low_limit,
+				     unsigned long high_limit)
+{
+	unsigned long long max = high_limit;
+	unsigned long log2qty, size;
+	void *table = NULL;
+
+	/* allow the kernel cmdline to have a say */
+	if (!numentries) {
+		/* round applicable memory size up to nearest megabyte */
+		numentries = nr_kernel_pages;
+		numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
+		numentries >>= 20 - PAGE_SHIFT;
+		numentries <<= 20 - PAGE_SHIFT;
+
+		/* limit to 1 bucket per 2^scale bytes of low memory */
+		if (scale > PAGE_SHIFT)
+			numentries >>= (scale - PAGE_SHIFT);
+		else
+			numentries <<= (PAGE_SHIFT - scale);
+
+		/* Make sure we've got at least a 0-order allocation.. */
+		if (unlikely(flags & HASH_SMALL)) {
+			/* Makes no sense without HASH_EARLY */
+			WARN_ON(!(flags & HASH_EARLY));
+			if (!(numentries >> *_hash_shift)) {
+				numentries = 1UL << *_hash_shift;
+				BUG_ON(!numentries);
+			}
+		} else if (unlikely((numentries * bucketsize) < PAGE_SIZE))
+			numentries = PAGE_SIZE / bucketsize;
+	}
+	numentries = roundup_pow_of_two(numentries);
+
+	/* limit allocation size to 1/16 total memory by default */
+	if (max == 0) {
+		max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
+		do_div(max, bucketsize);
+	}
+
+	if (numentries > max)
+		numentries = max;
+
+	log2qty = ilog2(numentries);
+
+	do {
+		size = bucketsize << log2qty;
+		if (flags & HASH_EARLY)
+			table = alloc_bootmem_nopanic(size);
+		else if (hashdist)
+			table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
+		else {
+			/*
+			 * If bucketsize is not a power-of-two, we may free
+			 * some pages at the end of hash table which
+			 * alloc_pages_exact() automatically does
+			 */
+			if (get_order(size) < MAX_ORDER) {
+				table = alloc_pages_exact(size, GFP_ATOMIC);
+				kmemleak_alloc(table, size, 1, GFP_ATOMIC);
+			}
+		}
+	} while (!table && size > PAGE_SIZE && --log2qty);
+
+	if (!table)
+		panic("Failed to allocate %s hash table\n", tablename);
+
+	pr_info("%s hash table entries: %d (order: %d, %lu bytes)\n",
+	       tablename,
+	       (1U << log2qty),
+	       ilog2(size) - PAGE_SHIFT,
+	       size);
+
+	if (_hash_shift)
+		*_hash_shift = log2qty;
+	if (_hash_mask)
+		*_hash_mask = (1 << log2qty) - 1;
+
+	return table;
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+	/* This function is called from the ip layer to get information about
+	   the amount of memory in the system and make some educated guesses
+	   about some default buffer sizes. We pick a value which ensures
+	   small buffers. */
+	val->totalram = 0;
+}
+int slab_is_available(void)
+{
+	/* called from kernel/param.c. */
+	return 1;
+}
+
+/* used from kern_ptr_validate from mm/util.c which is never called */
+void *high_memory = 0;
+
+
+
+void async_synchronize_full(void)
+{
+	/* called from drivers/base/ *.c */
+	/* there is nothing to do, really. */
+}
+
+int send_sig(int signal, struct task_struct *task, int x)
+{
+	struct SimTask *lib_task = container_of(task, struct SimTask,
+						kernel_task);
+
+	lib_signal_raised((struct SimTask *)lib_task, signal);
+	/* lib_assert (false); */
+	return 0;
+}
+unsigned long get_taint(void)
+{
+	/* never tainted. */
+	return 0;
+}
+void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
+{
+}
+struct pid *cad_pid = 0;
+
+void add_device_randomness(const void *buf, unsigned int size)
+{
+}
+
+int sched_rr_handler(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos)
+{
+	return 0;
+}
+
+void on_each_cpu_mask(const struct cpumask *mask,
+		      smp_call_func_t func, void *info, bool wait)
+{
+}
diff --git a/arch/lib/modules.c b/arch/lib/modules.c
new file mode 100644
index 0000000..ca43fdc
--- /dev/null
+++ b/arch/lib/modules.c
@@ -0,0 +1,36 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-assert.h"
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+
+int modules_disabled = 0;
+char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
+
+static struct module_version_attribute g_empty_attr_buffer;
+/* we make the array empty by default because, really, we don't need */
+/* to look at the builtin params */
+const struct kernel_param __start___param[] = {{0}} ;
+const struct kernel_param __stop___param[] = {{0}} ;
+const struct module_version_attribute *__start___modver[] = {
+	&g_empty_attr_buffer};
+const struct module_version_attribute *__stop___modver[] = {
+	&g_empty_attr_buffer};
+
+struct module_attribute module_uevent;
+struct ctl_table usermodehelper_table[] = {};
+
+int __request_module(bool wait, const char *fmt, ...)
+{
+	/* we really should never be trying to load modules that way. */
+	/*  lib_assert (false); */
+	return 0;
+}
diff --git a/arch/lib/pid.c b/arch/lib/pid.c
new file mode 100644
index 0000000..00cf7b6
--- /dev/null
+++ b/arch/lib/pid.c
@@ -0,0 +1,29 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/pid.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+void put_pid(struct pid *pid)
+{
+}
+pid_t pid_vnr(struct pid *pid)
+{
+	return pid_nr(pid);
+}
+struct task_struct *find_task_by_vpid(pid_t nr)
+{
+	lib_assert(false);
+	return 0;
+}
+struct pid *find_get_pid(int nr)
+{
+	lib_assert(false);
+	return 0;
+}
diff --git a/arch/lib/print.c b/arch/lib/print.c
new file mode 100644
index 0000000..09b1bb5
--- /dev/null
+++ b/arch/lib/print.c
@@ -0,0 +1,56 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <stdarg.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+int dmesg_restrict = 1;
+
+/* from lib/vsprintf.c */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
+int printk(const char *fmt, ...)
+{
+	va_list args;
+	static char buf[256];
+	int value;
+
+	va_start(args, fmt);
+	value = vsnprintf(buf, 256, printk_skip_level(fmt), args);
+	lib_printf("<%c>%s", printk_get_level(fmt), buf);
+	va_end(args);
+	return value;
+}
+void panic(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	lib_vprintf(fmt, args);
+	va_end(args);
+	lib_assert(false);
+}
+
+void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
+{
+	va_list args;
+
+	printk("%s:%d -- ", file, line);
+	va_start(args, fmt);
+	lib_vprintf(fmt, args);
+	va_end(args);
+}
+
+void warn_slowpath_null(const char *file, int line)
+{
+	printk("%s:%d -- ", file, line);
+}
+
diff --git a/arch/lib/proc.c b/arch/lib/proc.c
new file mode 100644
index 0000000..5507730
--- /dev/null
+++ b/arch/lib/proc.c
@@ -0,0 +1,34 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2014 Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/fs.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <net/net_namespace.h>
+#include "sim-types.h"
+#include "sim-assert.h"
+#include "fs/proc/internal.h"           /* XXX */
+
+struct proc_dir_entry;
+static char proc_root_data[sizeof(struct proc_dir_entry) + 4];
+
+static struct proc_dir_entry *proc_root_sim  =
+	(struct proc_dir_entry *)proc_root_data;
+
+void lib_proc_net_initialize(void)
+{
+	proc_root_sim->parent = proc_root_sim;
+	strcpy(proc_root_sim->name, "net");
+	proc_root_sim->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+	proc_root_sim->subdir = RB_ROOT;
+	init_net.proc_net = proc_root_sim;
+	init_net.proc_net_stat = proc_mkdir("stat", proc_root_sim);
+}
+
diff --git a/arch/lib/random.c b/arch/lib/random.c
new file mode 100644
index 0000000..9fbb8bf
--- /dev/null
+++ b/arch/lib/random.c
@@ -0,0 +1,53 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include <linux/random.h>
+
+u32 random32(void)
+{
+	return lib_random();
+}
+
+void get_random_bytes(void *buf, int nbytes)
+{
+	char *p = (char *)buf;
+	int i;
+
+	for (i = 0; i < nbytes; i++)
+		p[i] = lib_random();
+}
+void srandom32(u32 entropy)
+{
+}
+
+u32 prandom_u32(void)
+{
+	return lib_random();
+}
+void prandom_seed(u32 entropy)
+{
+}
+
+void prandom_bytes(void *buf, size_t bytes)
+{
+	return get_random_bytes(buf, bytes);
+}
+
+#include <linux/sysctl.h>
+
+static int nothing;
+struct ctl_table random_table[] = {
+	{
+		.procname       = "nothing",
+		.data           = &nothing,
+		.maxlen         = sizeof(int),
+		.mode           = 0444,
+		.proc_handler   = proc_dointvec,
+	}
+};
diff --git a/arch/lib/sysfs.c b/arch/lib/sysfs.c
new file mode 100644
index 0000000..2def2ca
--- /dev/null
+++ b/arch/lib/sysfs.c
@@ -0,0 +1,83 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+int sysfs_create_bin_file(struct kobject *kobj,
+			  const struct bin_attribute *attr)
+{
+	return 0;
+}
+void sysfs_remove_bin_file(struct kobject *kobj,
+			   const struct bin_attribute *attr)
+{
+}
+int sysfs_create_dir(struct kobject *kobj)
+{
+	return 0;
+}
+int sysfs_create_link(struct kobject *kobj, struct kobject *target,
+		      const char *name)
+{
+	return 0;
+}
+int sysfs_move_dir(struct kobject *kobj,
+		   struct kobject *new_parent_kobj)
+{
+	return 0;
+}
+void sysfs_remove_dir(struct kobject *kobj)
+{
+}
+void sysfs_remove_group(struct kobject *kobj,
+			const struct attribute_group *grp)
+{
+}
+int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+{
+	return 0;
+}
+int __must_check sysfs_create_group(struct kobject *kobj,
+				    const struct attribute_group *grp)
+{
+	return 0;
+}
+int sysfs_create_groups(struct kobject *kobj,
+			const struct attribute_group **groups)
+{
+	return 0;
+}
+int sysfs_schedule_callback(struct kobject *kobj,
+			    void (*func)(
+				    void *), void *data, struct module *owner)
+{
+	return 0;
+}
+void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
+		       const char *name)
+{
+}
+void sysfs_exit_ns(enum kobj_ns_type type, const void *tag)
+{
+}
+void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
+{
+}
+int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
+{
+	kobj->sd = lib_malloc(sizeof(struct kernfs_node));
+	return 0;
+}
+int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
+			 const void *ns)
+{
+	return 0;
+}
diff --git a/arch/lib/vmscan.c b/arch/lib/vmscan.c
new file mode 100644
index 0000000..3132f66
--- /dev/null
+++ b/arch/lib/vmscan.c
@@ -0,0 +1,26 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/mm.h>
+#include <linux/shrinker.h>
+
+/*
+ * Add a shrinker callback to be called from the vm
+ */
+int register_shrinker(struct shrinker *shrinker)
+{
+	return 0;
+}
+
+/*
+ * Remove one
+ */
+void unregister_shrinker(struct shrinker *shrinker)
+{
+}
+
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 09/11] lib: asm-generic files
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (7 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 08/11] lib: other kernel glue layer code Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 10/11] lib: libos build scripts and documentation Hajime Tazaki
                     ` (2 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/include/asm/Kbuild           | 57 +++++++++++++++++++++++++++++++++++
 arch/lib/include/asm/atomic.h         | 50 ++++++++++++++++++++++++++++++
 arch/lib/include/asm/barrier.h        |  8 +++++
 arch/lib/include/asm/bitsperlong.h    | 12 ++++++++
 arch/lib/include/asm/current.h        |  7 +++++
 arch/lib/include/asm/elf.h            | 10 ++++++
 arch/lib/include/asm/hardirq.h        |  8 +++++
 arch/lib/include/asm/page.h           | 14 +++++++++
 arch/lib/include/asm/pgtable.h        | 30 ++++++++++++++++++
 arch/lib/include/asm/processor.h      | 19 ++++++++++++
 arch/lib/include/asm/ptrace.h         |  4 +++
 arch/lib/include/asm/segment.h        |  6 ++++
 arch/lib/include/asm/sembuf.h         |  4 +++
 arch/lib/include/asm/shmbuf.h         |  4 +++
 arch/lib/include/asm/shmparam.h       |  4 +++
 arch/lib/include/asm/sigcontext.h     |  6 ++++
 arch/lib/include/asm/slab.h           | 21 +++++++++++++
 arch/lib/include/asm/stat.h           |  4 +++
 arch/lib/include/asm/statfs.h         |  4 +++
 arch/lib/include/asm/swab.h           |  7 +++++
 arch/lib/include/asm/thread_info.h    | 36 ++++++++++++++++++++++
 arch/lib/include/asm/uaccess.h        | 14 +++++++++
 arch/lib/include/asm/unistd.h         |  4 +++
 arch/lib/include/uapi/asm/byteorder.h |  6 ++++
 24 files changed, 339 insertions(+)
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/slab.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h

diff --git a/arch/lib/include/asm/Kbuild b/arch/lib/include/asm/Kbuild
new file mode 100644
index 0000000..c647b1c
--- /dev/null
+++ b/arch/lib/include/asm/Kbuild
@@ -0,0 +1,57 @@
+generic-y += auxvec.h
+generic-y += bitops.h
+generic-y += bug.h
+generic-y += cache.h
+generic-y += cacheflush.h
+generic-y += checksum.h
+generic-y += cputime.h
+generic-y += cmpxchg.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += exec.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += io.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq.h
+generic-y += irqflags.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += linkage.h
+generic-y += local.h
+generic-y += mcs_spinlock.h
+generic-y += mman.h
+generic-y += mmu.h
+generic-y += mmu_context.h
+generic-y += module.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += preempt.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += setup.h
+generic-y += signal.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += string.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += timex.h
+generic-y += tlbflush.h
+generic-y += types.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += unaligned.h
diff --git a/arch/lib/include/asm/atomic.h b/arch/lib/include/asm/atomic.h
new file mode 100644
index 0000000..41a49285
--- /dev/null
+++ b/arch/lib/include/asm/atomic.h
@@ -0,0 +1,50 @@
+#ifndef _ASM_SIM_ATOMIC_H
+#define _ASM_SIM_ATOMIC_H
+
+#include <linux/types.h>
+
+#if !defined(CONFIG_64BIT)
+typedef struct {
+	volatile long long counter;
+} atomic64_t;
+#endif
+
+#define ATOMIC64_INIT(i) { (i) }
+
+#define atomic64_read(v)        (*(volatile long *)&(v)->counter)
+void atomic64_add(long i, atomic64_t *v);
+static inline void atomic64_sub(long i, atomic64_t *v)
+{
+	v->counter -= i;
+}
+static inline void atomic64_inc(atomic64_t *v)
+{
+	v->counter++;
+}
+int atomic64_sub_and_test(long i, atomic64_t *v);
+#define atomic64_dec(v)			atomic64_sub(1LL, (v))
+int atomic64_dec_and_test(atomic64_t *v);
+int atomic64_inc_and_test(atomic64_t *v);
+int atomic64_add_negative(long i, atomic64_t *v);
+/* long atomic64_add_return(long i, atomic64_t *v); */
+static inline long atomic64_add_return(long i, atomic64_t *v)
+{
+	v->counter += i;
+	return v->counter;
+}
+static inline void atomic64_set(atomic64_t *v, long i)
+{
+	v->counter = i;
+}
+long atomic64_sub_return(long i, atomic64_t *v);
+long atomic64_inc_return(atomic64_t *v);
+long atomic64_dec_return(atomic64_t *v);
+long atomic64_cmpxchg(atomic64_t *v, long old, long new);
+long atomic64_xchg(atomic64_t *v, long new);
+int atomic64_add_unless(atomic64_t *v, long a, long u);
+int atomic64_inc_is_not_zero(atomic64_t *v);
+#define atomic64_inc_not_zero(v) 	atomic64_add_unless((v), 1LL, 0LL)
+
+#include <asm-generic/atomic.h>
+
+#endif /* _ASM_SIM_ATOMIC_H */
diff --git a/arch/lib/include/asm/barrier.h b/arch/lib/include/asm/barrier.h
new file mode 100644
index 0000000..47adcc6
--- /dev/null
+++ b/arch/lib/include/asm/barrier.h
@@ -0,0 +1,8 @@
+#include <asm-generic/barrier.h>
+
+#undef smp_store_release
+#define smp_store_release(p, v)						\
+	do {								\
+		smp_mb();						\
+		ACCESS_ONCE(*p) = (v);					\
+	} while (0)
diff --git a/arch/lib/include/asm/bitsperlong.h b/arch/lib/include/asm/bitsperlong.h
new file mode 100644
index 0000000..c7592f9
--- /dev/null
+++ b/arch/lib/include/asm/bitsperlong.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_SIM_BITSPERLONG_H
+#define _ASM_SIM_BITSPERLONG_H
+
+#ifdef CONFIG_64BIT
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif /* CONFIG_64BIT */
+
+#define __BITS_PER_LONG BITS_PER_LONG
+
+#endif /* _ASM_SIM_BITSPERLONG_H */
diff --git a/arch/lib/include/asm/current.h b/arch/lib/include/asm/current.h
new file mode 100644
index 0000000..62489cd
--- /dev/null
+++ b/arch/lib/include/asm/current.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SIM_CURRENT_H
+#define _ASM_SIM_CURRENT_H
+
+struct task_struct *get_current(void);
+#define current get_current()
+
+#endif /* _ASM_SIM_CURRENT_H */
diff --git a/arch/lib/include/asm/elf.h b/arch/lib/include/asm/elf.h
new file mode 100644
index 0000000..a7396c9
--- /dev/null
+++ b/arch/lib/include/asm/elf.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_SIM_ELF_H
+#define _ASM_SIM_ELF_H
+
+#if defined(CONFIG_64BIT)
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
+#endif /* _ASM_SIM_ELF_H */
diff --git a/arch/lib/include/asm/hardirq.h b/arch/lib/include/asm/hardirq.h
new file mode 100644
index 0000000..47d47f9
--- /dev/null
+++ b/arch/lib/include/asm/hardirq.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_SIM_HARDIRQ_H
+#define _ASM_SIM_HARDIRQ_H
+
+extern unsigned int interrupt_pending;
+
+#define local_softirq_pending() (interrupt_pending)
+
+#endif /* _ASM_SIM_HARDIRQ_H */
diff --git a/arch/lib/include/asm/page.h b/arch/lib/include/asm/page.h
new file mode 100644
index 0000000..8c0aa74
--- /dev/null
+++ b/arch/lib/include/asm/page.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_SIM_PAGE_H
+#define _ASM_SIM_PAGE_H
+
+typedef struct {} pud_t;
+
+#define THREAD_ORDER    1
+#define THREAD_SIZE  (PAGE_SIZE << THREAD_ORDER)
+
+#define WANT_PAGE_VIRTUAL 1
+
+#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
+
+#endif /* _ASM_SIM_PAGE_H */
diff --git a/arch/lib/include/asm/pgtable.h b/arch/lib/include/asm/pgtable.h
new file mode 100644
index 0000000..ce599c8
--- /dev/null
+++ b/arch/lib/include/asm/pgtable.h
@@ -0,0 +1,30 @@
+#ifndef _ASM_SIM_PGTABLE_H
+#define _ASM_SIM_PGTABLE_H
+
+#define PAGE_KERNEL ((pgprot_t) {0 })
+
+#define arch_start_context_switch(prev) do {} while (0)
+
+#define kern_addr_valid(addr)(1)
+#define pte_file(pte)(1)
+/* Encode and de-code a swap entry */
+#define __swp_type(x)                   (((x).val >> 5) & 0x1f)
+#define __swp_offset(x)                 ((x).val >> 11)
+#define __swp_entry(type, offset) \
+	((swp_entry_t) {((type) << 5) | ((offset) << 11) })
+#define __pte_to_swp_entry(pte)         ((swp_entry_t) {pte_val((pte)) })
+#define __swp_entry_to_pte(x)           ((pte_t) {(x).val })
+#define pmd_page(pmd) (struct page *)(pmd_val(pmd) & PAGE_MASK)
+#define pgtable_cache_init()   do { } while (0)
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+	return 0;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+	return pte;
+}
+
+#endif /* _ASM_SIM_PGTABLE_H */
diff --git a/arch/lib/include/asm/processor.h b/arch/lib/include/asm/processor.h
new file mode 100644
index 0000000..b673ee0
--- /dev/null
+++ b/arch/lib/include/asm/processor.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_SIM_PROCESSOR_H
+#define _ASM_SIM_PROCESSOR_H
+
+struct thread_struct {};
+
+#define cpu_relax()
+#define cpu_relax_lowlatency() cpu_relax()
+#define KSTK_ESP(tsk)	(0)
+
+void *current_text_addr(void);
+
+#define TASK_SIZE ((~(long)0))
+
+#define thread_saved_pc(x) (unsigned long)0
+#define task_pt_regs(t) NULL
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+#endif /* _ASM_SIM_PROCESSOR_H */
diff --git a/arch/lib/include/asm/ptrace.h b/arch/lib/include/asm/ptrace.h
new file mode 100644
index 0000000..ddd9708
--- /dev/null
+++ b/arch/lib/include/asm/ptrace.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_PTRACE_H
+#define _ASM_SIM_PTRACE_H
+
+#endif /* _ASM_SIM_PTRACE_H */
diff --git a/arch/lib/include/asm/segment.h b/arch/lib/include/asm/segment.h
new file mode 100644
index 0000000..e056922
--- /dev/null
+++ b/arch/lib/include/asm/segment.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SIM_SEGMENT_H
+#define _ASM_SIM_SEGMENT_H
+
+typedef struct { int seg; } mm_segment_t;
+
+#endif /* _ASM_SIM_SEGMENT_H */
diff --git a/arch/lib/include/asm/sembuf.h b/arch/lib/include/asm/sembuf.h
new file mode 100644
index 0000000..d64927b
--- /dev/null
+++ b/arch/lib/include/asm/sembuf.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SEMBUF_H
+#define _ASM_SIM_SEMBUF_H
+
+#endif /* _ASM_SIM_SEMBUF_H */
diff --git a/arch/lib/include/asm/shmbuf.h b/arch/lib/include/asm/shmbuf.h
new file mode 100644
index 0000000..42d0a71
--- /dev/null
+++ b/arch/lib/include/asm/shmbuf.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SHMBUF_H
+#define _ASM_SIM_SHMBUF_H
+
+#endif /* _ASM_SIM_SHMBUF_H */
diff --git a/arch/lib/include/asm/shmparam.h b/arch/lib/include/asm/shmparam.h
new file mode 100644
index 0000000..3410f1b
--- /dev/null
+++ b/arch/lib/include/asm/shmparam.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SHMPARAM_H
+#define _ASM_SIM_SHMPARAM_H
+
+#endif /* _ASM_SIM_SHMPARAM_H */
diff --git a/arch/lib/include/asm/sigcontext.h b/arch/lib/include/asm/sigcontext.h
new file mode 100644
index 0000000..230b4b5
--- /dev/null
+++ b/arch/lib/include/asm/sigcontext.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SIM_SIGCONTEXT_H
+#define _ASM_SIM_SIGCONTEXT_H
+
+struct sigcontext {};
+
+#endif /* _ASM_SIM_SIGCONTEXT_H */
diff --git a/arch/lib/include/asm/slab.h b/arch/lib/include/asm/slab.h
new file mode 100644
index 0000000..a3f5d19
--- /dev/null
+++ b/arch/lib/include/asm/slab.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SIM_SLAB_H
+#define _ASM_SIM_SLAB_H
+
+
+struct kmem_cache {
+	unsigned int object_size;
+	const char *name;
+	size_t size;
+	size_t align;
+	unsigned long flags;
+	void (*ctor)(void *);
+};
+
+void *__kmalloc(size_t size, gfp_t flags);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+static __always_inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc(size, flags);
+}
+
+#endif /* _ASM_SIM_SLAB_H */
diff --git a/arch/lib/include/asm/stat.h b/arch/lib/include/asm/stat.h
new file mode 100644
index 0000000..80fa2cb
--- /dev/null
+++ b/arch/lib/include/asm/stat.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_STAT_H
+#define _ASM_SIM_STAT_H
+
+#endif /* _ASM_SIM_STAT_H */
diff --git a/arch/lib/include/asm/statfs.h b/arch/lib/include/asm/statfs.h
new file mode 100644
index 0000000..881ce51
--- /dev/null
+++ b/arch/lib/include/asm/statfs.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_STATFS_H
+#define _ASM_SIM_STATFS_H
+
+#endif /* _ASM_SIM_STATFS_H */
diff --git a/arch/lib/include/asm/swab.h b/arch/lib/include/asm/swab.h
new file mode 100644
index 0000000..d81376a
--- /dev/null
+++ b/arch/lib/include/asm/swab.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SIM_SWAB_H
+#define _ASM_SIM_SWAB_H
+
+#include <linux/types.h>
+
+
+#endif /* _ASM_SIM_SWAB_H */
diff --git a/arch/lib/include/asm/thread_info.h b/arch/lib/include/asm/thread_info.h
new file mode 100644
index 0000000..ec316c6
--- /dev/null
+++ b/arch/lib/include/asm/thread_info.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_SIM_THREAD_INFO_H
+#define _ASM_SIM_THREAD_INFO_H
+
+#define TIF_NEED_RESCHED 1
+#define TIF_SIGPENDING 2
+#define TIF_MEMDIE 5
+
+struct thread_info {
+	__u32 flags;
+	int preempt_count;
+	struct task_struct *task;
+	struct restart_block restart_block;
+};
+
+struct thread_info *current_thread_info(void);
+struct thread_info *alloc_thread_info(struct task_struct *task);
+void free_thread_info(struct thread_info *ti);
+
+#define TS_RESTORE_SIGMASK      0x0008  /* restore signal mask in do_signal() */
+#define HAVE_SET_RESTORE_SIGMASK        1
+static inline void set_restore_sigmask(void)
+{
+}
+static inline void clear_restore_sigmask(void)
+{
+}
+static inline bool test_restore_sigmask(void)
+{
+	return true;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+	return true;
+}
+
+#endif /* _ASM_SIM_THREAD_INFO_H */
diff --git a/arch/lib/include/asm/uaccess.h b/arch/lib/include/asm/uaccess.h
new file mode 100644
index 0000000..74f973b
--- /dev/null
+++ b/arch/lib/include/asm/uaccess.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_SIM_UACCESS_H
+#define _ASM_SIM_UACCESS_H
+
+#define KERNEL_DS ((mm_segment_t) {0 })
+#define USER_DS ((mm_segment_t) {0 })
+#define get_fs() KERNEL_DS
+#define get_ds() USER_DS
+#define set_fs(x) do {} while ((x.seg) != (x.seg))
+
+#define __access_ok(addr, size) (1)
+
+#include <asm-generic/uaccess.h>
+
+#endif /* _ASM_SIM_UACCESS_H */
diff --git a/arch/lib/include/asm/unistd.h b/arch/lib/include/asm/unistd.h
new file mode 100644
index 0000000..6b482b4
--- /dev/null
+++ b/arch/lib/include/asm/unistd.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_UNISTD_H
+#define _ASM_SIM_UNISTD_H
+
+#endif /* _ASM_SIM_UNISTD_H */
diff --git a/arch/lib/include/uapi/asm/byteorder.h b/arch/lib/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..b13a7a8
--- /dev/null
+++ b/arch/lib/include/uapi/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_BYTEORDER_H
+#define _ASM_X86_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_X86_BYTEORDER_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 10/11] lib: libos build scripts and documentation
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (8 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 09/11] lib: asm-generic files Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-17  9:36   ` [RFC PATCH v2 11/11] lib: tools used for test scripts Hajime Tazaki
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 Documentation/virtual/libos-howto.txt | 144 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   8 +
 arch/lib/Kconfig                      | 121 +++++++
 arch/lib/Makefile                     | 251 +++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/processor.mk                 |   7 +
 9 files changed, 1288 insertions(+)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/defconfig
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/processor.mk

diff --git a/Documentation/virtual/libos-howto.txt b/Documentation/virtual/libos-howto.txt
new file mode 100644
index 0000000..fbf7946
--- /dev/null
+++ b/Documentation/virtual/libos-howto.txt
@@ -0,0 +1,144 @@
+Library operating system (libos) version of Linux
+=================================================
+
+* Overview
+
+New hardware independent architecture 'arch/lib', configured by
+CONFIG_LIB gives you two features.
+
+- network stack in userspace (NUSE)
+  NUSE will give you a personalized network stack for each application
+  without replacing host operating system.
+
+- network simulator integration, which is called Direct Code Execution (DCE)
+  DCE will give us a network simulation environment with Linux network stack
+  to investigate the detail behavior protocol implementation with a flexible
+  network configuration. This is also useful for the testing environment.
+
+(- more abstracted implementation of underlying platform will be a future
+   direction (e.g., rump hypercall))
+
+In both features, Linux kernel network stack is running on top of
+userspace application with a linked or dynamically loaded library.
+
+They have their own, isolated network stack from host operating system
+so they are configured different IP addresses as other virtualization
+methods do.
+
+
+* How different with others ?
+
+- User-mode Linux (UML)
+
+UML is a way to execute Linux kernel code as a userspace
+application. It is completely isolated from host kernel but can host
+arbitrary userspace applications on top of UML.
+
+- namespace / container
+
+Container technologies with namespace brings a process-level isolation
+to host multiple network entities but shares the kernel among
+processes, which prevents to introduce new features implemented in
+kernel space.
+
+
+* How to build it ?
+
+configuration of arch/lib follows a standard configuration of kernel.
+
+ make defconfig ARCH=lib
+
+or
+
+ make menuconfig ARCH=lib
+
+then you can build a set of libraries for libos.
+
+ make library ARCH=lib
+
+This will give you a shared library file liblinux-$(KERNELVERSION).so
+in the top directory.
+
+* Hello world
+
+you may first need to configure a configuration file, named
+'nuse.conf' so that the library version of network stack can know what
+kind of IP configuration should be used. There is an example file
+at arch/lib/nuse.conf.sample: you may copy and modify it for your purpose.
+
+ sudo NUSECONF=nuse.conf ./nuse ping www.google.com
+
+
+
+* Example use cases
+- regression test with Direct Code Execution (DCE)
+
+'make test' by DCE gives a test platform for networking code, with the
+help of network simulator facilities like link delay/bandwidth/drop
+configurations, large network topology with userspace routing protocol
+daemons, etc.
+
+An interesting feature is the determinism of any test executions. A
+test script always gives same results in every execution if there is
+no modification on test target code.
+
+For the first step, you need to obtain network simulator
+environment. 'make testbin' does all the stuff for the preparation.
+
+% make testbin -C tools/testing/libos
+
+Then, you can 'make test' for your code.
+
+% make test ARCH=lib
+
+ PASS: TestSuite netlink-socket
+ PASS: TestSuite process-manager
+ PASS: TestSuite dce-cradle
+ PASS: TestSuite dce-mptcp
+ PASS: TestSuite dce-umip
+ PASS: TestSuite dce-quagga
+ PASS: Example dce-tcp-simple
+ PASS: Example dce-udp-simple
+
+
+- userspace network stack (NUSE)
+
+an application can use its own network stack, distinct from host network stack
+in order to personalize any network feature to the application specific one.
+The 'nuse' wrapper script, based on LD_PRELOAD technique, carefully replaces
+socket API and redirects system calls to the network stack library, provided by
+this framework.
+
+the network stack can be used with any kind of raw-socket like
+technologies such as Intel DPDK, netmap, etc.
+
+
+
+* Files / External Repository
+
+The kernel source tree (i.e., arch/lib) only contains a shared part of
+applications (NUSE/DCE). Pure userspace part is managed at a different
+repository, called Linux-libos-tools: it is automatically downloaded
+during make library.
+
+ https://github.com/libos-nuse/linux-libos-tools
+
+
+* More information
+- libos-nuse@googlegroups.com (LibOS in general and NUSE related questions)
+- ns-3-users@googlegroups.com (ns-3 related questions)
+- articles, slides
+ Experimentation Tools for Networking Research (Lacage, 2010)
+   http://cutebugs.net/files/thesis.pdf
+ Direct code execution: revisiting library OS architecture for reproducible
+  network experiments (Tazaki et al., 2013)
+   http://dx.doi.org/10.1145/2535372.2535374
+ Library Operating System with Mainline Linux Network Stack (Tazaki et al., 2015)
+   https://www.netdev01.org/docs/netdev01-tazaki-libos.pdf (slides)
+
+
+* Authors
+ Mathieu Lacage <mathieu.lacage@gmail.com>
+ Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ Frederic Urbani <frederic.urbani@gmail.com>
+ Ryo Nakamura <upa@haeena.net>
diff --git a/MAINTAINERS b/MAINTAINERS
index 3589d67..ae88290 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5699,6 +5699,15 @@ M:	Sasha Levin <sasha.levin@oracle.com>
 S:	Maintained
 F:	tools/lib/lockdep/
 
+LIBRARY OS (LIBOS)
+M:	Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+L:	libos-nuse@googlegroups.com
+W:	http://libos-nuse.github.io/
+S:	Maintained
+F:	Documentation/virtual/libos-howto.txt
+F:	arch/lib/
+F:	tools/testing/libos/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:	Paul Mackerras <paulus@au.ibm.com>
 W:	http://www.ibm.com/linux/ltc/projects/ppc
diff --git a/arch/lib/.gitignore b/arch/lib/.gitignore
new file mode 100644
index 0000000..9f48573
--- /dev/null
+++ b/arch/lib/.gitignore
@@ -0,0 +1,8 @@
+linker.lds
+autoconf.h
+objs.mk
+timeconst.h
+hz.bc
+crc32table.h
+*.d
+tools
diff --git a/arch/lib/Kconfig b/arch/lib/Kconfig
new file mode 100644
index 0000000..eb7dede
--- /dev/null
+++ b/arch/lib/Kconfig
@@ -0,0 +1,121 @@
+menuconfig LIB
+       bool "LibOS-specific options"
+       def_bool n
+       select PROC_FS
+       select PROC_SYSCTL
+       select SYSCTL
+       select SYSFS
+       help
+          The 'lib' architecture is a library (user-mode) version of
+          the linux kernel that includes only its network stack and is
+	  used within the userspace application, and ns-3 simulator.
+	  For more information, about ns-3, see http://www.nsnam.org.
+
+config EXPERIMENTAL
+	def_bool y
+
+config MMU
+        def_bool n
+config FPU
+        def_bool n
+config SMP
+        def_bool n
+
+config ARCH
+	string
+	option env="ARCH"
+
+config KTIME_SCALAR
+       def_bool y
+
+config MODULES
+       def_bool y
+       option modules
+
+config GENERIC_CSUM
+	def_bool y
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+config PRINTK
+       def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+config GENERIC_HWEIGHT
+       def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config NO_HZ
+	def_bool y
+
+config BASE_FULL
+       def_bool n
+
+config SELECT_MEMORY_MODEL
+       def_bool n
+
+config FLAT_NODE_MEM_MAP
+       def_bool n
+
+config PAGEFLAGS_EXTENDED
+       def_bool n
+
+config VIRT_TO_BUS
+       def_bool n
+
+config HAS_DMA
+       def_bool n
+
+config HZ
+        int
+        default 250
+
+config TINY_RCU
+       def_bool y
+
+config HZ_250
+       def_bool y
+
+config BASE_SMALL
+       int
+       default 1
+
+config SPLIT_PTLOCK_CPUS
+       int
+       default 1
+
+config FLATMEM
+       def_bool y
+
+config SYSCTL
+       def_bool y
+
+config PROC_FS
+       def_bool y
+
+config SYSFS
+       def_bool y
+
+config PROC_SYSCTL
+       def_bool y
+
+config NETDEVICES
+       def_bool y
+
+source "net/Kconfig"
+
+source "drivers/base/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+
diff --git a/arch/lib/Makefile b/arch/lib/Makefile
new file mode 100644
index 0000000..624c2ef
--- /dev/null
+++ b/arch/lib/Makefile
@@ -0,0 +1,251 @@
+ARCH_DIR := arch/lib
+SRCDIR=$(dir $(firstword $(MAKEFILE_LIST)))
+DCE_TESTDIR=$(srctree)/tools/testing/libos/
+KBUILD_KCONFIG := arch/$(ARCH)/Kconfig
+
+CC = gcc
+GCCVERSIONGTEQ48 := $(shell expr `gcc -dumpversion` \>= 4.8)
+ifeq "$(GCCVERSIONGTEQ48)" "1"
+   NO_TREE_LOOP_OPT += -fno-tree-loop-distribute-patterns
+endif
+
+
+-include $(ARCH_DIR)/objs.mk
+-include $(srctree)/.config
+include $(srctree)/scripts/Kbuild.include
+include $(ARCH_DIR)/processor.mk
+
+# targets
+LIBOS_TOOLS=$(ARCH_DIR)/tools
+LIBOS_GIT_REPO=git://github.com/libos-nuse/linux-libos-tools
+KERNEL_LIB=liblinux-$(KERNELVERSION).so
+
+ALL_OBJS=$(OBJS) $(KERNEL_LIB) $(modules) $(all-obj-for-clean)
+
+# auto generated files
+AUTOGENS=$(CRC32TABLE) $(COMPILE_H) $(BOUNDS_H) $(ARCH_DIR)/timeconst.h $(ARCH_DIR)/linker.lds
+COMPILE_H=$(srctree)/include/generated/compile.h
+BOUNDS_H=$(srctree)/include/generated/bounds.h
+
+# from lib/Makefile
+CRC32TABLE = $(ARCH_DIR)/crc32table.h
+hostprogs-y	:= $(srctree)/lib/gen_crc32table
+clean-files	:= crc32table.h
+
+# sources and objects
+LIB_SRC=\
+lib.c lib-device.c lib-socket.c random.c softirq.c time.c \
+timer.c hrtimer.c sched.c workqueue.c \
+print.c slab.c tasklet.c tasklet-hrtimer.c \
+glue.c fs.c sysctl.c proc.c sysfs.c \
+capability.c pid.c modules.c filemap.c vmscan.c
+
+LIB_OBJ=$(addprefix $(ARCH_DIR)/,$(addsuffix .o,$(basename $(LIB_SRC))))
+LIB_DEPS=$(addprefix $(ARCH_DIR)/.,$(addsuffix .o.cmd,$(basename $(LIB_SRC))))
+-include $(LIB_DEPS)
+
+DEPENDS=$(addprefix $(ARCH_DIR)/.,\
+	$(addsuffix .d,$(basename $(LIB_SRC)))\
+	)
+
+# options
+COV?=no
+cov_yes=-fprofile-arcs -ftest-coverage
+cov_no=
+covl_yes=-fprofile-arcs
+covl_no=
+OPT?=yes
+opt_yes=-O3 -fomit-frame-pointer $(NO_TREE_LOOP_OPT)
+opt_no=-O0
+PIC?=yes
+pic_yes=-fpic -DPIC
+pic_no=-mcmodel=large
+PIC_CFLAGS=$(pic_$(PIC))
+
+# flags
+CFLAGS_USPACE= \
+ -Wp,-MD,$(depfile) $(opt_$(OPT)) -g3 -Wall -Wstrict-prototypes -Wno-trigraphs \
+ -fno-inline -fno-strict-aliasing -fno-common \
+ -fno-delete-null-pointer-checks -fno-builtin \
+ -fno-stack-protector -Wno-unused -Wno-pointer-sign \
+ $(PIC_CFLAGS) -D_DEBUG $(cov_$(COV)) -I$(ARCH_DIR)/include
+
+CFLAGS+= \
+ $(CFLAGS_USPACE) -nostdinc -D__KERNEL__ -iwithprefix $(srctree)/include \
+ -DKBUILD_BASENAME=\"clnt\" -DKBUILD_MODNAME=\"nsc\" -DMODVERSIONS \
+ -DEXPORT_SYMTAB \
+ -U__FreeBSD__ -D__linux__=1 -Dlinux=1 -D__linux=1 \
+ -DCONFIG_DEFAULT_HOSTNAME=\"lib\" \
+ -I$(ARCH_DIR)/include/generated/uapi \
+ -I$(ARCH_DIR)/include/generated \
+ -I$(srctree)/include -I$(ARCH_DIR)/include/uapi \
+ -I$(srctree)/include/uapi -I$(srctree)/include/generated/uapi \
+ -include $(srctree)/include/linux/kconfig.h \
+ -I$(ARCH_DIR) -I.
+
+ifeq ($(PROCESSOR_SIZE),64)
+CFLAGS+= -DCONFIG_64BIT
+endif
+
+LDFLAGS += -shared -nodefaultlibs -g3 -Wl,-O1 -Wl,-T$(ARCH_DIR)/linker.lds $(covl_$(COV))
+
+# targets
+
+modules:=
+all-obj-for-clean:=
+
+all: library modules
+
+# note: the directory order below matters to ensure that we match the kernel order
+dirs=kernel/ kernel/time/ kernel/rcu/ kernel/locking/ kernel/bpf/ mm/ fs/ fs/proc/ crypto/ lib/ drivers/base/ drivers/net/ net/ init/
+empty:=
+space:= $(empty) $(empty)
+colon:= :
+comma= ,
+kernel/_to_keep=notifier.o params.o sysctl.o \
+rwsem.o semaphore.o kfifo.o cred.o user.o groups.o ksysfs.o
+kernel/time/_to_keep=time.o
+kernel/rcu_to_keep=rcu/srcu.o rcu/pdate.o rcu/tiny.o
+kernel/locking_to_keep=locking/mutex.o
+kernel/bpf_to_keep=bpf/core.o
+mm/_to_keep=util.o list_lru.o
+crypto/_to_keep=aead.o ahash.o shash.o api.o algapi.o cipher.o compress.o proc.o \
+crc32c_generic.o
+drivers/base/_to_keep=class.o core.o bus.o dd.o driver.o devres.o module.o map.o
+drivers/net/_to_keep=loopback.o
+lib/_to_keep=klist.o kobject.o kref.o hweight.o int_sqrt.o checksum.o \
+find_last_bit.o find_next_bit.o bitmap.o nlattr.o idr.o libcrc32c.o \
+ctype.o string.o kasprintf.o rbtree.o sha1.o textsearch.o vsprintf.o \
+rwsem-spinlock.o scatterlist.o ratelimit.o hexdump.o dec_and_lock.o \
+div64.o dynamic_queue_limits.o md5.o kstrtox.o iovec.o lockref.o crc32.o \
+rhashtable.o iov_iter.o cmdline.o kobject_uevent.o
+fs/_to_keep=read_write.o libfs.o namei.o filesystems.o file.o file_table.o \
+dcache.o inode.o pipe.o char_dev.o splice.o no-block.o seq_file.o super.o \
+fcntl.o coredump.o
+fs/proc/_to_keep=proc_sysctl.o proc_net.o root.o generic.o inode.o
+init/_to_keep=version.o
+
+quiet_cmd_objsmk = OBJS-MK   $@
+      cmd_objsmk = \
+	for i in 1; do \
+	$(foreach d,$(dirs), \
+           $(MAKE) -i -s -f $< srcdir=$(srctree)/$(d) \
+	    objdir=$(srctree)/$(d) \
+            config=$(srctree)/.config \
+	    to_keep=$(subst $(space),$(colon),$($(d)_to_keep)) print;) \
+	done > $@
+
+$(ARCH_DIR)/objs.mk: $(ARCH_DIR)/Makefile.print $(srctree)/.config $(ARCH_DIR)/Makefile
+	+$(call if_changed,objsmk)
+
+quiet_cmd_timeconst = GEN     $@
+      cmd_timeconst = echo "hz=$(CONFIG_HZ)" > $(ARCH_DIR)/hz.bc ; \
+                      bc $(ARCH_DIR)/hz.bc kernel/time/timeconst.bc > $@
+$(ARCH_DIR)/timeconst.h: $(srctree)/.config
+	$(call if_changed,timeconst)
+
+quiet_cmd_linker = GEN     $@
+      cmd_linker = ld -shared --verbose | ./$^ > $@
+$(ARCH_DIR)/linker.lds: $(ARCH_DIR)/generate-linker-script.py
+	$(call if_changed,linker)
+
+quiet_cmd_crc32src = GEN     $@
+      cmd_crc32src = $(MAKE) -f $(srctree)/Makefile silentoldconfig ; \
+                     cc $^ -o $@
+$(srctree)/lib/gen_crc32table: $(srctree)/lib/gen_crc32table.c
+	$(call if_changed,crc32src)
+
+quiet_cmd_crc32 = GEN     $@
+      cmd_crc32 = $< > $@
+
+$(CRC32TABLE): $(srctree)/lib/gen_crc32table
+	$(call if_changed,crc32)
+
+# copied from init/Makefile
+       chk_compile.h = :
+ quiet_chk_compile.h = echo '  CHK     $@'
+silent_chk_compile.h = :
+$(COMPILE_H): include/generated/utsrelease.h asm-generic $(version_h)
+	@$($(quiet)chk_compile.h)
+	+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
+	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
+
+# crafted from $(srctree)/Kbuild
+quiet_cmd_lib_bounds = GEN     $@
+define cmd_lib_bounds
+	(set -e; \
+	 echo "#ifndef GENERATED_BOUNDS_H"; \
+	 echo "#define GENERATED_BOUNDS_H"; \
+	 echo ""; \
+	 echo "#define NR_PAGEFLAGS (__NR_PAGEFLAGS)"; \
+	 echo "#define MAX_NR_ZONES (__MAX_NR_ZONES)"; \
+	 echo ""; \
+	 echo "#endif /* GENERATED_BOUNDS_H */") > $@
+endef
+
+$(BOUNDS_H):
+	$(Q)mkdir -p $(dir $@)
+	$(call cmd,lib_bounds)
+
+
+KERNEL_BUILTIN=$(addprefix $(srctree)/,$(addsuffix builtin.o,$(dirs)))
+OBJS=$(LIB_OBJ) $(foreach builtin,$(KERNEL_BUILTIN),$(if $($(builtin)),$($(builtin))))
+export OBJS KERNEL_LIB COV covl_yes covl_no
+
+quiet_cmd_cc = CC      $@
+      cmd_cc = 	mkdir -p $(dir $@);	\
+		$(CC) $(CFLAGS) -c $< -o $@
+quiet_cmd_linkko = KO   $@
+      cmd_linkko = $(CC) -shared -o $@ -nostdlib $^
+quiet_cmd_builtin = BUILTIN   $@
+      cmd_builtin = mkdir -p $(dir $(srctree)/$@); rm -f $(srctree)/$@; \
+		    if test -n "$($(srctree)/$@)"; then for f in $($(srctree)/$@); \
+		    do $(AR) Tcru $@ $$f; done; else $(AR) Tcru $@; fi
+
+%/builtin.o:
+	$(call if_changed,builtin)
+%.ko:%.o
+	$(call if_changed,linkko)
+%.o:%.c
+	$(call if_changed_dep,cc)
+
+library: $(KERNEL_LIB) $(LIBOS_TOOLS)
+modules: $(modules)
+
+$(LIBOS_TOOLS): $(KERNEL_LIB) Makefile FORCE
+	$(Q) if [ ! -d "$@" ]; then \
+		git clone $(LIBOS_GIT_REPO) $@ ;\
+	fi
+	$(Q) $(MAKE) -C $(LIBOS_TOOLS)
+
+install: modules library
+
+install-dir:
+
+$(KERNEL_LIB): $(ARCH_DIR)/objs.mk $(AUTOGENS) $(OBJS)
+	$(call if_changed,linklib)
+
+quiet_cmd_linklib = LIB     $@
+      cmd_linklib = $(CC) -Wl,--whole-archive $(OBJS) $(LDFLAGS) -o $@; \
+		    ln -s -f $(KERNEL_LIB) liblinux.so
+
+quiet_cmd_clean = CLEAN   $@
+      cmd_clean = for f in $(foreach m,$(modules),$($(m))) ; do rm -f $$f 2>/dev/null; done ; \
+		  for f in $(ALL_OBJS); do rm -f $$f; done 2>/dev/null ;\
+		  rm -rf $(AUTOGENS) $(ARCH_DIR)/objs.mk 2>/dev/null ;\
+		  if [ -d $(LIBOS_TOOLS) ]; then $(MAKE) -C $(LIBOS_TOOLS) clean ; fi
+
+archclean:
+	$(call if_changed,clean)
+
+.%.d:%.c $(srctree)/.config
+	$(Q) set -e; $(CC) -MM -MT $(<:.c=.o) $(CFLAGS) $< > $@
+
+deplib: $(DEPENDS)
+	-include $(DEPENDS)
+
+test:
+	$(Q) $(MAKE) -C $(DCE_TESTDIR)/
+
+.PHONY : clean deplib
+
diff --git a/arch/lib/Makefile.print b/arch/lib/Makefile.print
new file mode 100644
index 0000000..40e6db0
--- /dev/null
+++ b/arch/lib/Makefile.print
@@ -0,0 +1,45 @@
+# inherit $(objdir) $(config) $(srcdir) $(to_keep) from command-line
+
+include $(config)
+include $(srcdir)Makefile
+
+# fix minor nits for make version dependencies
+ifeq (3.82,$(firstword $(sort $(MAKE_VERSION) 3.82)))
+  SEPARATOR=
+else
+  SEPARATOR=/
+endif
+
+to_keep_list=$(subst :, ,$(to_keep))
+obj-y += $(lib-y)
+obj-m += $(lib-m)
+subdirs := $(filter %/, $(obj-y) $(obj-m))
+subdirs-y := $(filter %/, $(obj-y))
+subdirs-m := $(filter %/, $(obj-m))
+tmp1-obj-y=$(patsubst %/,%/builtin.o,$(obj-y))
+tmp1-obj-m=$(filter-out $(subdirs-m),$(obj-m))
+tmp2-obj-y=$(foreach m,$(tmp1-obj-y), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
+tmp2-obj-m=$(foreach m,$(tmp1-obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
+tmp3-obj-y=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-y)),$(tmp2-obj-y))
+tmp3-obj-m=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-m)),$(tmp2-obj-m))
+final-obj-y=$(tmp3-obj-y)
+final-obj-m=$(tmp3-obj-m)
+
+print: $(final-obj-m) $(subdirs)
+	@if test $(if $(final-obj-y),1); then \
+	  echo -n $(objdir)builtin.o; echo -n "="; echo $(addprefix $(objdir),$(final-obj-y)); \
+	  echo -n $(objdir)builtin.o; echo -n ": "; echo $(addprefix $(objdir),$(final-obj-y)); \
+          echo -n "-include "; echo $(addprefix $(objdir).,$(addsuffix ".cmd", $(final-obj-y))); \
+	  echo -n "all-obj-for-clean+="; echo $(addprefix $(objdir),$(final-obj-y)) $(objdir)builtin.o; \
+	fi
+$(final-obj-m):
+	@echo -n "modules+="; echo $(addprefix $(objdir),$(@:.o=.ko))
+	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n ": "
+	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
+	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n "="
+	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
+$(subdirs):
+	@$(MAKE) -s -f $(firstword $(MAKEFILE_LIST)) objdir=$(objdir)$@$(SEPARATOR) config=$(config) srcdir=$(srcdir)$@$(SEPARATOR) to_keep=$(to_keep) print 2>/dev/null
+
+.PHONY : core
+.NOTPARALLEL : print $(subdirs) $(final-obj-m)
diff --git a/arch/lib/defconfig b/arch/lib/defconfig
new file mode 100644
index 0000000..9307e6f
--- /dev/null
+++ b/arch/lib/defconfig
@@ -0,0 +1,653 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux Kernel Configuration
+#
+CONFIG_LIB=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+# CONFIG_SMP is not set
+CONFIG_KTIME_SCALAR=y
+CONFIG_MODULES=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_PRINTK=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_NO_HZ=y
+# CONFIG_BASE_FULL is not set
+# CONFIG_SELECT_MEMORY_MODEL is not set
+# CONFIG_FLAT_NODE_MEM_MAP is not set
+# CONFIG_PAGEFLAGS_EXTENDED is not set
+# CONFIG_VIRT_TO_BUS is not set
+# CONFIG_HAS_DMA is not set
+CONFIG_HZ=250
+CONFIG_TINY_RCU=y
+CONFIG_HZ_250=y
+CONFIG_BASE_SMALL=1
+CONFIG_SPLIT_PTLOCK_CPUS=1
+CONFIG_FLATMEM=y
+CONFIG_SYSCTL=y
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=y
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_NET_UDP_TUNNEL=m
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_GENEVE is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=y
+CONFIG_TCP_CONG_HSTCP=y
+CONFIG_TCP_CONG_HYBLA=y
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=y
+CONFIG_TCP_CONG_LP=y
+CONFIG_TCP_CONG_VENO=y
+CONFIG_TCP_CONG_YEAH=y
+CONFIG_TCP_CONG_ILLINOIS=y
+CONFIG_TCP_CONG_DCTCP=y
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_HYBLA is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_VENO is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_DCTCP is not set
+CONFIG_DEFAULT_RENO=y
+CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=y
+# CONFIG_IPV6_GRE is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=m
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_ACCT=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_LOG_COMMON=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_DCCP=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+CONFIG_NF_NAT_PROTO_SCTP=y
+CONFIG_NF_NAT_AMANDA=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_NF_NAT_TFTP is not set
+CONFIG_NF_NAT_REDIRECT=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_EXTHDR=y
+CONFIG_NFT_META=y
+CONFIG_NFT_CT=y
+CONFIG_NFT_RBTREE=y
+CONFIG_NFT_HASH=y
+CONFIG_NFT_COUNTER=y
+CONFIG_NFT_LOG=y
+CONFIG_NFT_LIMIT=y
+CONFIG_NFT_MASQ=y
+# CONFIG_NFT_REDIR is not set
+CONFIG_NFT_NAT=y
+# CONFIG_NFT_QUEUE is not set
+# CONFIG_NFT_REJECT is not set
+# CONFIG_NFT_REJECT_INET is not set
+# CONFIG_NFT_COMPAT is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+# CONFIG_NETFILTER_XT_SET is not set
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_NETMAP=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_RATEEST=y
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=y
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_L2TP=m
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+CONFIG_IP_SET=y
+CONFIG_IP_SET_MAX=256
+# CONFIG_IP_SET_BITMAP_IP is not set
+# CONFIG_IP_SET_BITMAP_IPMAC is not set
+# CONFIG_IP_SET_BITMAP_PORT is not set
+# CONFIG_IP_SET_HASH_IP is not set
+# CONFIG_IP_SET_HASH_IPMARK is not set
+# CONFIG_IP_SET_HASH_IPPORT is not set
+# CONFIG_IP_SET_HASH_IPPORTIP is not set
+# CONFIG_IP_SET_HASH_IPPORTNET is not set
+# CONFIG_IP_SET_HASH_MAC is not set
+# CONFIG_IP_SET_HASH_NETPORTNET is not set
+# CONFIG_IP_SET_HASH_NET is not set
+# CONFIG_IP_SET_HASH_NETNET is not set
+# CONFIG_IP_SET_HASH_NETPORT is not set
+# CONFIG_IP_SET_HASH_NETIFACE is not set
+# CONFIG_IP_SET_LIST_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_LOG_ARP is not set
+CONFIG_NF_LOG_IPV4=y
+CONFIG_NF_TABLES_IPV4=y
+CONFIG_NFT_CHAIN_ROUTE_IPV4=y
+# CONFIG_NF_REJECT_IPV4 is not set
+# CONFIG_NFT_REJECT_IPV4 is not set
+# CONFIG_NF_TABLES_ARP is not set
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_FILTER is not set
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_TABLES_IPV6=y
+# CONFIG_NFT_CHAIN_ROUTE_IPV6 is not set
+# CONFIG_NF_REJECT_IPV6 is not set
+# CONFIG_NFT_REJECT_IPV6 is not set
+CONFIG_NF_LOG_IPV6=y
+# CONFIG_NF_NAT_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+# CONFIG_NF_TABLES_BRIDGE is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=y
+CONFIG_INET_DCCP_DIAG=y
+
+#
+# DCCP CCIDs Configuration
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=y
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE=y
+# CONFIG_SCTP_COOKIE_HMAC_MD5 is not set
+# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_L2TP=m
+# CONFIG_L2TP_V3 is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_VLAN_8021Q_MVRP is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+CONFIG_IPX_INTERN=y
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_PHONET=m
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_SJA1000=m
+# CONFIG_CAN_SJA1000_ISA is not set
+CONFIG_CAN_SJA1000_PLATFORM=m
+# CONFIG_CAN_C_CAN is not set
+# CONFIG_CAN_M_CAN is not set
+# CONFIG_CAN_CC770 is not set
+# CONFIG_CAN_SOFTING is not set
+CONFIG_CAN_DEBUG_DEVICES=y
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+
+#
+# Dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_BT=m
+CONFIG_BT_BREDR=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_LE=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+# CONFIG_NET_9P is not set
+CONFIG_CAIF=m
+CONFIG_CAIF_DEBUG=y
+CONFIG_CAIF_NETDEV=m
+# CONFIG_CAIF_USB is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_MCRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST_COMMON=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_DRBG_MENU is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
diff --git a/arch/lib/generate-linker-script.py b/arch/lib/generate-linker-script.py
new file mode 100755
index 0000000..db3d7f8
--- /dev/null
+++ b/arch/lib/generate-linker-script.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+import re
+
+def linker_script(reading, writing):
+    delim = re.compile('^==')
+    end_of_ro = re.compile('^ *.gcc_except_table[^:]*:[ ]*ONLY_IF_RW')
+    skipping = True
+    for line in reading.readlines():
+        if delim.search (line) is not None:
+            if skipping:
+                skipping = False
+                continue
+            else:
+                skipping = True
+        if skipping:
+            continue
+        m = end_of_ro.search(line)
+        if m is not None:
+            skipping = False
+            initcall = """
+  /* taken from kernel script*/
+    . = ALIGN (CONSTANT (MAXPAGESIZE));
+    .initcall.init : AT(ADDR(.initcall.init)) {
+     __initcall_start = .;
+     *(.initcallearly.init)
+     *(.initcall0.init)
+     *(.initcall0s.init)
+     *(.initcall1.init)
+     *(.initcall1s.init)
+     *(.initcall2.init)
+     *(.initcall2s.init)
+     *(.initcall3.init)
+     *(.initcall3s.init)
+     *(.initcall4.init)
+     *(.initcall4s.init)
+     *(.initcall5.init)
+     *(.initcall5s.init)
+     *(.initcall6.init)
+     *(.initcall6s.init)
+     *(.initcall7.init)
+     *(.initcall7s.init)
+     __initcall_end = .;
+    }
+"""
+            writing.write (initcall)
+        writing.write(line)
+
+import sys
+linker_script (sys.stdin, sys.stdout)
diff --git a/arch/lib/processor.mk b/arch/lib/processor.mk
new file mode 100644
index 0000000..7331528
--- /dev/null
+++ b/arch/lib/processor.mk
@@ -0,0 +1,7 @@
+PROCESSOR=$(shell uname -m)
+PROCESSOR_x86_64=64
+PROCESSOR_i686=32
+PROCESSOR_i586=32
+PROCESSOR_i386=32
+PROCESSOR_i486=32
+PROCESSOR_SIZE=$(PROCESSOR_$(PROCESSOR))
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v2 11/11] lib: tools used for test scripts
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (9 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 10/11] lib: libos build scripts and documentation Hajime Tazaki
@ 2015-04-17  9:36   ` Hajime Tazaki
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17  9:36 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Jhristoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

These auxiliary files are used for make test ARCH=lib.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 tools/testing/libos/.gitignore   |  6 +++++
 tools/testing/libos/Makefile     | 38 +++++++++++++++++++++++++++
 tools/testing/libos/README       | 15 +++++++++++
 tools/testing/libos/bisect.sh    | 10 +++++++
 tools/testing/libos/dce-test.sh  | 23 ++++++++++++++++
 tools/testing/libos/nuse-test.sh | 57 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 149 insertions(+)
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

diff --git a/tools/testing/libos/.gitignore b/tools/testing/libos/.gitignore
new file mode 100644
index 0000000..57a74a0
--- /dev/null
+++ b/tools/testing/libos/.gitignore
@@ -0,0 +1,6 @@
+*.pcap
+files-*
+bake
+buildtop
+core
+exitprocs
diff --git a/tools/testing/libos/Makefile b/tools/testing/libos/Makefile
new file mode 100644
index 0000000..3da25429
--- /dev/null
+++ b/tools/testing/libos/Makefile
@@ -0,0 +1,38 @@
+ADD_PARAM?=
+
+all: test
+
+bake:
+	hg clone http://code.nsnam.org/bake
+
+check_pkgs:
+	@./bake/bake.py check | grep Bazaar | grep OK || (echo "bzr is missing" && ./bake/bake.py check)
+	@./bake/bake.py check | grep autoreconf | grep OK || (echo "autotools is missing" && ./bake/bake.py check && exit 1)
+
+testbin: bake check_pkgs
+	@cp ../../../arch/lib/tools/bakeconf-linux.xml bake/bakeconf.xml
+	@mkdir -p buildtop/build/bin_dce
+	cd buildtop ; \
+	../bake/bake.py configure -e dce-linux-inkernel $(BAKECONF_PARAMS)
+	cd buildtop ; \
+	../bake/bake.py show --enabledTree | grep -v  -E "pygoocanvas|graphviz|python-dev" | grep Missing && (echo "required packages are missing") || echo ""
+	cd buildtop ; \
+	../bake/bake.py download ; \
+	../bake/bake.py update ; \
+	../bake/bake.py build
+
+test:
+	@./dce-test.sh ADD_PARAM=$(ADD_PARAM)
+
+test-valgrind:
+	@./dce-test.sh -g ADD_PARAM=$(ADD_PARAM)
+
+test-fault-injection:
+	@./dce-test.sh -f ADD_PARAM=$(ADD_PARAM)
+
+clean:
+#	@rm -rf buildtop
+	@rm -f *.pcap
+	@rm -rf files-*
+	@rm -f exitprocs
+	@rm -f core
diff --git a/tools/testing/libos/README b/tools/testing/libos/README
new file mode 100644
index 0000000..51ac5a5
--- /dev/null
+++ b/tools/testing/libos/README
@@ -0,0 +1,15 @@
+
+- bisect.sh
+a sample script to bisect an issue of network stack code with the help
+of LibOS (and ns-3 network simulator). This was used to detect the issue
+for the following patch.
+
+http://patchwork.ozlabs.org/patch/436351/
+
+- dce-test.sh
+a test script invoked by 'make test ARCH=lib'. The contents of test
+scenario are implemented as test suites of ns-3 network simulator.
+
+- nuse-test.sh
+a simple test script for Network Stack in Userspace (NUSE).
+
diff --git a/tools/testing/libos/bisect.sh b/tools/testing/libos/bisect.sh
new file mode 100755
index 0000000..9377ac3
--- /dev/null
+++ b/tools/testing/libos/bisect.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+git merge origin/nuse --no-commit
+make clean ARCH=lib
+make library ARCH=lib OPT=no
+make test ARCH=lib ADD_PARAM=" -s dce-umip"
+RET=$?
+git reset --hard
+
+exit $RET
diff --git a/tools/testing/libos/dce-test.sh b/tools/testing/libos/dce-test.sh
new file mode 100755
index 0000000..e81e2d8
--- /dev/null
+++ b/tools/testing/libos/dce-test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+#set -x
+export LD_LOG=symbol-fail
+#VERBOSE="-v"
+VALGRIND=""
+FAULT_INJECTION=""
+
+if [ "$1" = "-g" ] ; then
+ VALGRIND="-g"
+# Not implemneted yet.
+#elif [ "$1" = "-f" ] ; then
+# FAULT_INJECTION="-f"
+fi
+
+# FIXME
+#export NS_ATTRIBUTE_DEFAULT='ns3::DceManagerHelper::LoaderFactory=ns3::\
+#DlmLoaderFactory[];ns3::TaskManager::FiberManagerType=UcontextFiberManager'
+
+cd buildtop/source/ns-3-dce
+LD_LIBRARY_PATH=${srctree} ./test.py -n ${VALGRIND} ${FAULT_INJECTION}\
+	   ${VERBOSE} ${ADD_PARAM}
diff --git a/tools/testing/libos/nuse-test.sh b/tools/testing/libos/nuse-test.sh
new file mode 100755
index 0000000..198e7e4
--- /dev/null
+++ b/tools/testing/libos/nuse-test.sh
@@ -0,0 +1,57 @@
+#!/bin/bash -e
+
+LIBOS_TOOLS=arch/lib/tools
+
+IFNAME=`ip route |grep default | awk '{print $5}'`
+GW=`ip route |grep default | awk '{print $3}'`
+#XXX
+IPADDR=`echo $GW | sed -r "s/([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)$/\1\`expr \2 + 10\`/"`
+
+# ip route
+# ip address
+# ip link
+
+NUSE_CONF=/tmp/nuse.conf
+
+cat > ${NUSE_CONF} << ENDCONF
+
+interface ${IFNAME}
+	address ${IPADDR}
+	netmask 255.255.255.0
+	macaddr 00:01:01:01:01:02
+	viftype RAW
+
+route
+	network 0.0.0.0
+	netmask 0.0.0.0
+	gateway ${GW}
+
+ENDCONF
+
+cd ${LIBOS_TOOLS}
+sudo NUSECONF=${NUSE_CONF} ./nuse ping 127.0.0.1 -c 2
+
+# rump test
+sudo NUSECONF=${NUSE_CONF} ./nuse sleep 5 &
+
+sleep 2
+PID_SLEEP=`/bin/ls -ltr /tmp/rump-server-nuse.* | tail -1 | awk '{print $9}' | sed -e "s/.*rump-server-nuse\.//g" | sed "s/=//"`
+RUMP_URL=unix:///tmp/rump-server-nuse.$PID_SLEEP
+# ls -ltr /tmp/*
+
+sudo chmod 777 /tmp/rump-server-nuse.$PID_SLEEP
+LD_PRELOAD=./libnuse-hijack.so  RUMPHIJACK=socket=all \
+    RUMP_SERVER=$RUMP_URL ip addr show
+
+wait %1
+
+if [ "$1" == "--extended" ] ; then
+sudo NUSECONF=${NUSE_CONF} ./nuse ping ${GW} -c 2
+sudo NUSECONF=${NUSE_CONF} ./nuse iperf -c ${GW} -p 2000 -t 3
+sudo NUSECONF=${NUSE_CONF} ./nuse iperf -c ${GW} -p 8 -u -t 3
+sudo NUSECONF=${NUSE_CONF} ./nuse dig www.google.com
+sudo NUSECONF=${NUSE_CONF} ./nuse host www.google.com
+sudo NUSECONF=${NUSE_CONF} ./nuse nslookup www.google.com
+#sudo NUSECONF=${NUSE_CONF} ./nuse nc www.google.com 80
+sudo NUSECONF=${NUSE_CONF} ./nuse wget www.google.com -O -
+fi
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17  9:36   ` [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
@ 2015-04-17 12:17     ` Christoph Lameter
  2015-04-17 12:44       ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Christoph Lameter @ 2015-04-17 12:17 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, Arnd Bergmann, Jonathan Corbet, Jekka Enberg,
	Javid Rientjes, Joonsoo Kim, Jndrew Morton, linux-kernel,
	linux-doc, netdev, linux-mm, Jeff Dike, Richard Weinberger,
	Rusty Russell, Ryo Nakamura, Christoph Paasch, Mathieu Lacage,
	libos-nuse

On Fri, 17 Apr 2015, Hajime Tazaki wrote:

> add header includion for CONFIG_LIB to wrap kmalloc and co. This will
> bring malloc(3) based allocator used by arch/lib.

Maybe add another allocator insteadl? SLLB which implements memory
management using malloc()?

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17 12:17     ` Christoph Lameter
@ 2015-04-17 12:44       ` Richard Weinberger
  2015-04-17 15:02         ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-04-17 12:44 UTC (permalink / raw)
  To: Christoph Lameter, Hajime Tazaki
  Cc: linux-arch, Arnd Bergmann, Jonathan Corbet, Jekka Enberg,
	Javid Rientjes, Joonsoo Kim, Jndrew Morton, linux-kernel,
	linux-doc, netdev, linux-mm, Jeff Dike, Rusty Russell,
	Ryo Nakamura, Christoph Paasch, Mathieu Lacage, libos-nuse

Am 17.04.2015 um 14:17 schrieb Christoph Lameter:
> On Fri, 17 Apr 2015, Hajime Tazaki wrote:
> 
>> add header includion for CONFIG_LIB to wrap kmalloc and co. This will
>> bring malloc(3) based allocator used by arch/lib.
> 
> Maybe add another allocator insteadl? SLLB which implements memory
> management using malloc()?

Yeah, that's a good idea.

Hajime, another question, do you really want a malloc/free backend?
I'm not a mm expert, but does malloc() behave exactly as the kernel
counter parts?

In UML we allocate a big file on the host side, mmap() it and give this mapping
to the kernel as physical memory such that any kernel allocator can work with it.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17 12:44       ` Richard Weinberger
@ 2015-04-17 15:02         ` Hajime Tazaki
  2015-04-17 15:08           ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17 15:02 UTC (permalink / raw)
  To: richard
  Cc: cl, linux-arch, arnd, corbet, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	upa, christoph.paasch, mathieu.lacage, libos-nuse


Hi Christoph, Richard,

At Fri, 17 Apr 2015 14:44:35 +0200,
Richard Weinberger wrote:
> 
> Am 17.04.2015 um 14:17 schrieb Christoph Lameter:
> > On Fri, 17 Apr 2015, Hajime Tazaki wrote:
> > 
> >> add header includion for CONFIG_LIB to wrap kmalloc and co. This will
> >> bring malloc(3) based allocator used by arch/lib.
> > 
> > Maybe add another allocator insteadl? SLLB which implements memory
> > management using malloc()?
> 
> Yeah, that's a good idea.

first, my bad, I should be more precise on the commit message.

the patch with 04/11 patch is used _not_ only malloc(3) but
also any allocator registered by our entry API, lib_init().

for NUSE case, we use malloc(3) but for DCE (ns-3) case, we
use our own allocator, which manages the (virtual) process
running on network simulator.

if these externally configurable memory allocator are point
of interest in Linux kernel, maybe adding another allocator
into mm/ is interesting but I'm not sure. what do you think ?

btw, what does stand for SLLB ? (just curious)

> Hajime, another question, do you really want a malloc/free backend?
> I'm not a mm expert, but does malloc() behave exactly as the kernel
> counter parts?

as stated above, A1) yes, we need our own allocator, and A2)
yes as NUSE proofed, it behaves fine.

> In UML we allocate a big file on the host side, mmap() it and give this mapping
> to the kernel as physical memory such that any kernel allocator can work with it.

libos doesn't virtualize a physical memory but provide
allocator functions returning memory block on a request
instead.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17 15:02         ` Hajime Tazaki
@ 2015-04-17 15:08           ` Richard Weinberger
  2015-04-17 15:27             ` Hajime Tazaki
  2015-04-17 22:26             ` Christoph Lameter
  0 siblings, 2 replies; 117+ messages in thread
From: Richard Weinberger @ 2015-04-17 15:08 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: cl, linux-arch, arnd, corbet, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	upa, christoph.paasch, mathieu.lacage, libos-nuse

Am 17.04.2015 um 17:02 schrieb Hajime Tazaki:
> 
> Hi Christoph, Richard,
> 
> At Fri, 17 Apr 2015 14:44:35 +0200,
> Richard Weinberger wrote:
>>
>> Am 17.04.2015 um 14:17 schrieb Christoph Lameter:
>>> On Fri, 17 Apr 2015, Hajime Tazaki wrote:
>>>
>>>> add header includion for CONFIG_LIB to wrap kmalloc and co. This will
>>>> bring malloc(3) based allocator used by arch/lib.
>>>
>>> Maybe add another allocator insteadl? SLLB which implements memory
>>> management using malloc()?
>>
>> Yeah, that's a good idea.
> 
> first, my bad, I should be more precise on the commit message.
> 
> the patch with 04/11 patch is used _not_ only malloc(3) but
> also any allocator registered by our entry API, lib_init().
> 
> for NUSE case, we use malloc(3) but for DCE (ns-3) case, we
> use our own allocator, which manages the (virtual) process
> running on network simulator.
> 
> if these externally configurable memory allocator are point
> of interest in Linux kernel, maybe adding another allocator
> into mm/ is interesting but I'm not sure. what do you think ?

This is the idea behind SLLB.

> btw, what does stand for SLLB ? (just curious)

SLUB is the unqueued SLAB and SLLB is the library SLAB. :D

>> Hajime, another question, do you really want a malloc/free backend?
>> I'm not a mm expert, but does malloc() behave exactly as the kernel
>> counter parts?
> 
> as stated above, A1) yes, we need our own allocator, and A2)
> yes as NUSE proofed, it behaves fine.

Okay.

>> In UML we allocate a big file on the host side, mmap() it and give this mapping
>> to the kernel as physical memory such that any kernel allocator can work with it.
> 
> libos doesn't virtualize a physical memory but provide
> allocator functions returning memory block on a request
> instead.

Makes sense. I thought maybe it can help you reducing the code
footprint.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17 15:08           ` Richard Weinberger
@ 2015-04-17 15:27             ` Hajime Tazaki
  2015-04-17 22:26             ` Christoph Lameter
  1 sibling, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-17 15:27 UTC (permalink / raw)
  To: richard
  Cc: cl, linux-arch, arnd, corbet, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	upa, christoph.paasch, mathieu.lacage, libos-nuse


At Fri, 17 Apr 2015 17:08:22 +0200,
Richard Weinberger wrote:

> >>>> add header includion for CONFIG_LIB to wrap kmalloc and co. This will
> >>>> bring malloc(3) based allocator used by arch/lib.
> >>>
> >>> Maybe add another allocator insteadl? SLLB which implements memory
> >>> management using malloc()?
> >>
> >> Yeah, that's a good idea.
> > 
> > first, my bad, I should be more precise on the commit message.
> > 
> > the patch with 04/11 patch is used _not_ only malloc(3) but
> > also any allocator registered by our entry API, lib_init().
> > 
> > for NUSE case, we use malloc(3) but for DCE (ns-3) case, we
> > use our own allocator, which manages the (virtual) process
> > running on network simulator.
> > 
> > if these externally configurable memory allocator are point
> > of interest in Linux kernel, maybe adding another allocator
> > into mm/ is interesting but I'm not sure. what do you think ?
> 
> This is the idea behind SLLB.
> 
> > btw, what does stand for SLLB ? (just curious)
> 
> SLUB is the unqueued SLAB and SLLB is the library SLAB. :D

thanks.
I will be back with SLLB and give v3 patches soon.

-- Hajime


^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib
  2015-04-17 15:08           ` Richard Weinberger
  2015-04-17 15:27             ` Hajime Tazaki
@ 2015-04-17 22:26             ` Christoph Lameter
  1 sibling, 0 replies; 117+ messages in thread
From: Christoph Lameter @ 2015-04-17 22:26 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Hajime Tazaki, linux-arch, arnd, corbet, penberg, rientjes,
	iamjoonsoo.kim, akpm, linux-kernel, linux-doc, netdev, linux-mm,
	jdike, rusty, upa, christoph.paasch, mathieu.lacage, libos-nuse

On Fri, 17 Apr 2015, Richard Weinberger wrote:

> SLUB is the unqueued SLAB and SLLB is the library SLAB. :D

Good that this convention is now so broadly known that I did not even
have to explain what it meant. But I think you can give it any name you
want. SLLB was just a way to tersely state how this is going to integrate
into the overall scheme of things.


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS)
  2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
                     ` (10 preceding siblings ...)
  2015-04-17  9:36   ` [RFC PATCH v2 11/11] lib: tools used for test scripts Hajime Tazaki
@ 2015-04-19 13:28   ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
                       ` (11 more replies)
  11 siblings, 12 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

changes from v2:
- Patch 02/11 ("slab: add private memory allocator header for arch/lib")
* add new allocator named SLIB (Library Allocator): Patch 04/11 is integrated
  to 02 (commented by Christoph Lameter)
- Overall
* rewrite commit log messages

changes from v1:
- Patch 01/11 ("sysctl: make some functions unstatic to access by arch/lib"):
* add prefix ctl_table_ to newly publiced functions (commented by Joe Perches)
- Patch 08/11 ("lib: other kernel glue layer code"):
* significantly reduce glue codes (stubs) (commented by Richard Weinberger)
- Others
* adapt to linux-4.0.0
* detect make dependency by Kbuild .cmd files

patchset history
-----------------
[v2] : https://lkml.org/lkml/2015/4/17/140
[v1] : https://lkml.org/lkml/2015/3/24/254

This is an introduction of library operating system (LibOS) for Linux.

Our objective is to build the kernel network stack as a shared library
that can be linked to by userspace programs to provide network stack
personalization and testing facilities, and allow researchers to more
easily simulate complex network topologies of linux routers/hosts.

Although the architecture itself can virtualize various things, the
current design only focuses on the network stack. You can benefit
network stack feature such as TCP, UDP, SCTP, DCCP (IPv4 and IPv6),
Mobie IPv6, Multipath TCP (IPv4/IPv6, out-of-tree at the present
moment), and netlink with various userspace applications (quagga,
iproute2, iperf, wget, and thttpd).

== What is LibOS ? ==

The library exposes an entry point as API, which is lib_init(), in
order to connect userspace applications to the (userspace-version)
kernel network stack. The clock source, virtual struct net_device, and
scheduler are provided by caller while kernel resource like system
calls is provided by callee.

Once the LibOS is initialized via the API, userspace applications with
POSIX socket can use the system calls defined in LibOS by replacing
from the original socket-related symbols to the LibOS-specific
one. Then application can benefit the network stack of LibOS without
involving the host network stack.

Currently, there are two users of LibOS: Network Stack in Userspace
(NUSE) and ns-3 network simulatior with Direct Code Execution
(DCE). These codes are managed at an external repository(*1).


== How to use it ? ==

to build the library,
% make {defconfig,menuconfig} ARCH=lib

then, build it.
% make library ARCH=lib

You will see liblinux-$(KERNELVERSION).so in the top directory.

== More information ==

The crucial difference between UML (user-mode linux) and this approach
is that we allow multiple network stack instances to co-exist within a
single process with dlmopen(3) like linking for easy debugging.


These patches are also available on this branch:

git://github.com/libos-nuse/net-next-nuse.git for-asm-upstream-v3


For further information, here is a slideset presented at the last
netdev0.1 conference.

http://www.slideshare.net/hajimetazaki/library-operating-system-for-linux-netdev01

I would appreciate any kind of your feedback regarding to upstream
this feature.

*1 https://github.com/libos-nuse/linux-libos-tools

Hajime Tazaki (10):
  sysctl: make some functions unstatic to access by arch/lib
  slab: add SLIB (Library memory allocator) for arch/lib
  lib: public headers and API implementations for userspace programs
  lib: time handling (kernel glue code)
  lib: context and scheduling functions (kernel glue code) for libos
  lib: sysctl handling (kernel glue code)
  lib: other kernel glue layer code
  lib: auxially files for auto-generated asm-generic files of libos
  lib: libos build scripts and documentation
  lib: tools used for test scripts

 Documentation/virtual/libos-howto.txt | 144 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   8 +
 arch/lib/Kconfig                      | 124 +++++++
 arch/lib/Makefile                     | 251 +++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/capability.c                 |  47 +++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/filemap.c                    |  32 ++
 arch/lib/fs.c                         |  70 ++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/glue.c                       | 283 +++++++++++++++
 arch/lib/hrtimer.c                    | 122 +++++++
 arch/lib/include/asm/Kbuild           |  57 +++
 arch/lib/include/asm/atomic.h         |  50 +++
 arch/lib/include/asm/barrier.h        |   8 +
 arch/lib/include/asm/bitsperlong.h    |  12 +
 arch/lib/include/asm/current.h        |   7 +
 arch/lib/include/asm/elf.h            |  10 +
 arch/lib/include/asm/hardirq.h        |   8 +
 arch/lib/include/asm/page.h           |  14 +
 arch/lib/include/asm/pgtable.h        |  30 ++
 arch/lib/include/asm/processor.h      |  19 +
 arch/lib/include/asm/ptrace.h         |   4 +
 arch/lib/include/asm/segment.h        |   6 +
 arch/lib/include/asm/sembuf.h         |   4 +
 arch/lib/include/asm/shmbuf.h         |   4 +
 arch/lib/include/asm/shmparam.h       |   4 +
 arch/lib/include/asm/sigcontext.h     |   6 +
 arch/lib/include/asm/stat.h           |   4 +
 arch/lib/include/asm/statfs.h         |   4 +
 arch/lib/include/asm/swab.h           |   7 +
 arch/lib/include/asm/thread_info.h    |  36 ++
 arch/lib/include/asm/uaccess.h        |  14 +
 arch/lib/include/asm/unistd.h         |   4 +
 arch/lib/include/sim-assert.h         |  23 ++
 arch/lib/include/sim-init.h           | 134 +++++++
 arch/lib/include/sim-printf.h         |  13 +
 arch/lib/include/sim-types.h          |  53 +++
 arch/lib/include/sim.h                |  51 +++
 arch/lib/include/uapi/asm/byteorder.h |   6 +
 arch/lib/lib-device.c                 | 187 ++++++++++
 arch/lib/lib-socket.c                 | 410 +++++++++++++++++++++
 arch/lib/lib.c                        | 294 +++++++++++++++
 arch/lib/lib.h                        |  21 ++
 arch/lib/modules.c                    |  36 ++
 arch/lib/pid.c                        |  29 ++
 arch/lib/print.c                      |  56 +++
 arch/lib/proc.c                       |  34 ++
 arch/lib/processor.mk                 |   7 +
 arch/lib/random.c                     |  53 +++
 arch/lib/sched.c                      | 406 +++++++++++++++++++++
 arch/lib/softirq.c                    | 108 ++++++
 arch/lib/sysctl.c                     | 270 ++++++++++++++
 arch/lib/sysfs.c                      |  83 +++++
 arch/lib/tasklet-hrtimer.c            |  57 +++
 arch/lib/tasklet.c                    |  76 ++++
 arch/lib/time.c                       | 144 ++++++++
 arch/lib/timer.c                      | 238 +++++++++++++
 arch/lib/vmscan.c                     |  26 ++
 arch/lib/workqueue.c                  | 242 +++++++++++++
 fs/proc/proc_sysctl.c                 |  36 +-
 include/linux/slab.h                  |   6 +-
 include/linux/slib_def.h              |  21 ++
 init/Kconfig                          |   8 +
 mm/Makefile                           |   1 +
 mm/slab.h                             |   4 +
 mm/slib.c                             | 205 +++++++++++
 tools/testing/libos/.gitignore        |   6 +
 tools/testing/libos/Makefile          |  38 ++
 tools/testing/libos/README            |  15 +
 tools/testing/libos/bisect.sh         |  10 +
 tools/testing/libos/dce-test.sh       |  23 ++
 tools/testing/libos/nuse-test.sh      |  57 +++
 74 files changed, 5619 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/capability.c
 create mode 100644 arch/lib/defconfig
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/processor.mk
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/sysctl.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c
 create mode 100644 arch/lib/vmscan.c
 create mode 100644 arch/lib/workqueue.c
 create mode 100644 include/linux/slib_def.h
 create mode 100644 mm/slib.c
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 01/10] sysctl: make some functions unstatic to access by arch/lib
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
                       ` (10 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

libos (arch/lib) emulates a sysctl-like interface by a function call of
userspace by enumerating sysctl tree from sysctl_table_root. It requires
to be publicly accessible to this symbol and related functions.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 fs/proc/proc_sysctl.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f92d5dd..56feec7 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -35,7 +35,7 @@ static struct ctl_table root_table[] = {
 	},
 	{ }
 };
-static struct ctl_table_root sysctl_table_root = {
+struct ctl_table_root sysctl_table_root = {
 	.default_set.dir.header = {
 		{{.count = 1,
 		  .nreg = 1,
@@ -77,8 +77,9 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
 }
 
 /* Called under sysctl_lock */
-static struct ctl_table *find_entry(struct ctl_table_header **phead,
-	struct ctl_dir *dir, const char *name, int namelen)
+struct ctl_table *ctl_table_find_entry(struct ctl_table_header **phead,
+				       struct ctl_dir *dir, const char *name,
+				       int namelen)
 {
 	struct ctl_table_header *head;
 	struct ctl_table *entry;
@@ -300,7 +301,7 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
 	struct ctl_table *entry;
 
 	spin_lock(&sysctl_lock);
-	entry = find_entry(&head, dir, name, namelen);
+	entry = ctl_table_find_entry(&head, dir, name, namelen);
 	if (entry && use_table(head))
 		*phead = head;
 	else
@@ -321,7 +322,7 @@ static struct ctl_node *first_usable_entry(struct rb_node *node)
 	return NULL;
 }
 
-static void first_entry(struct ctl_dir *dir,
+void ctl_table_first_entry(struct ctl_dir *dir,
 	struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = NULL;
@@ -339,7 +340,7 @@ static void first_entry(struct ctl_dir *dir,
 	*pentry = entry;
 }
 
-static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
+void ctl_table_next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = *phead;
 	struct ctl_table *entry = *pentry;
@@ -670,7 +671,8 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
 
 	pos = 2;
 
-	for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
+	for (ctl_table_first_entry(ctl_dir, &h, &entry); h;
+	     ctl_table_next_entry(&h, &entry)) {
 		if (!scan(h, entry, &pos, file, ctx)) {
 			sysctl_head_finish(h);
 			break;
@@ -828,7 +830,7 @@ static struct ctl_dir *find_subdir(struct ctl_dir *dir,
 	struct ctl_table_header *head;
 	struct ctl_table *entry;
 
-	entry = find_entry(&head, dir, name, namelen);
+	entry = ctl_table_find_entry(&head, dir, name, namelen);
 	if (!entry)
 		return ERR_PTR(-ENOENT);
 	if (!S_ISDIR(entry->mode))
@@ -924,13 +926,13 @@ failed:
 	return subdir;
 }
 
-static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
+struct ctl_dir *ctl_table_xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
 {
 	struct ctl_dir *parent;
 	const char *procname;
 	if (!dir->header.parent)
 		return &set->dir;
-	parent = xlate_dir(set, dir->header.parent);
+	parent = ctl_table_xlate_dir(set, dir->header.parent);
 	if (IS_ERR(parent))
 		return parent;
 	procname = dir->header.ctl_table[0].procname;
@@ -951,13 +953,13 @@ static int sysctl_follow_link(struct ctl_table_header **phead,
 	spin_lock(&sysctl_lock);
 	root = (*pentry)->data;
 	set = lookup_header_set(root, namespaces);
-	dir = xlate_dir(set, (*phead)->parent);
+	dir = ctl_table_xlate_dir(set, (*phead)->parent);
 	if (IS_ERR(dir))
 		ret = PTR_ERR(dir);
 	else {
 		const char *procname = (*pentry)->procname;
 		head = NULL;
-		entry = find_entry(&head, dir, procname, strlen(procname));
+		entry = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		ret = -ENOENT;
 		if (entry && use_table(head)) {
 			unuse_table(*phead);
@@ -1069,7 +1071,7 @@ static bool get_links(struct ctl_dir *dir,
 	/* Are there links available for every entry in table? */
 	for (entry = table; entry->procname; entry++) {
 		const char *procname = entry->procname;
-		link = find_entry(&head, dir, procname, strlen(procname));
+		link = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		if (!link)
 			return false;
 		if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
@@ -1082,7 +1084,7 @@ static bool get_links(struct ctl_dir *dir,
 	/* The checks passed.  Increase the registration count on the links */
 	for (entry = table; entry->procname; entry++) {
 		const char *procname = entry->procname;
-		link = find_entry(&head, dir, procname, strlen(procname));
+		link = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		head->nreg++;
 	}
 	return true;
@@ -1098,7 +1100,7 @@ static int insert_links(struct ctl_table_header *head)
 	if (head->set == root_set)
 		return 0;
 
-	core_parent = xlate_dir(root_set, head->parent);
+	core_parent = ctl_table_xlate_dir(root_set, head->parent);
 	if (IS_ERR(core_parent))
 		return 0;
 
@@ -1479,7 +1481,7 @@ static void put_links(struct ctl_table_header *header)
 	if (header->set == root_set)
 		return;
 
-	core_parent = xlate_dir(root_set, parent);
+	core_parent = ctl_table_xlate_dir(root_set, parent);
 	if (IS_ERR(core_parent))
 		return;
 
@@ -1488,7 +1490,7 @@ static void put_links(struct ctl_table_header *header)
 		struct ctl_table *link;
 		const char *name = entry->procname;
 
-		link = find_entry(&link_head, core_parent, name, strlen(name));
+		link = ctl_table_find_entry(&link_head, core_parent, name, strlen(name));
 		if (link &&
 		    ((S_ISDIR(link->mode) && S_ISDIR(entry->mode)) ||
 		     (S_ISLNK(link->mode) && (link->data == root)))) {
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 02/10] slab: add SLIB (Library memory allocator) for arch/lib
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
                       ` (9 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

add SLIB allocator for arch/lib (CONFIG_LIB) to wrap kmalloc and co.
This will bring user's own allocator of libos: malloc(3) etc.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 include/linux/slab.h     |   6 +-
 include/linux/slib_def.h |  21 +++++
 init/Kconfig             |   8 ++
 mm/Makefile              |   1 +
 mm/slab.h                |   4 +
 mm/slib.c                | 205 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 244 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/slib_def.h
 create mode 100644 mm/slib.c

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 9a139b6..b167daa 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -192,7 +192,7 @@ size_t ksize(const void *);
 #endif
 #endif
 
-#ifdef CONFIG_SLOB
+#if defined(CONFIG_SLOB) || defined(CONFIG_SLIB)
 /*
  * SLOB passes all requests larger than one page to the page allocator.
  * No kmalloc array is necessary since objects of different sizes can
@@ -350,6 +350,9 @@ kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
 }
 #endif
 
+#ifdef CONFIG_SLIB
+#include <linux/slib_def.h>
+#else
 static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 {
 	unsigned int order = get_order(size);
@@ -428,6 +431,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 	}
 	return __kmalloc(size, flags);
 }
+#endif /* CONFIG_SLIB */
 
 /*
  * Determine size used for the nth kmalloc cache.
diff --git a/include/linux/slib_def.h b/include/linux/slib_def.h
new file mode 100644
index 0000000..d9fe7d5
--- /dev/null
+++ b/include/linux/slib_def.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_SLLB_DEF_H
+#define _LINUX_SLLB_DEF_H
+
+
+struct kmem_cache {
+	unsigned int object_size;
+	const char *name;
+	size_t size;
+	size_t align;
+	unsigned long flags;
+	void (*ctor)(void *);
+};
+
+void *__kmalloc(size_t size, gfp_t flags);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+static __always_inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc(size, flags);
+}
+
+#endif /* _LINUX_SLLB_DEF_H */
diff --git a/init/Kconfig b/init/Kconfig
index 9afb971..8bdee98 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1695,6 +1695,14 @@ config SLOB
 	   allocator. SLOB is generally more space efficient but
 	   does not perform as well on large systems.
 
+config SLIB
+	bool "SLIB (Library Allocator)"
+	depends on LIB
+	help
+	   SLIB replaces the slab allocator with a registered allocator
+	   function via lib_init() used by libos (CONFIG_LIB). It usually
+	   used malloc(3) or any allocators.
+
 endchoice
 
 config SLUB_CPU_PARTIAL
diff --git a/mm/Makefile b/mm/Makefile
index 4bf586e..8c66951 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
 obj-$(CONFIG_SLOB) += slob.o
+obj-$(CONFIG_SLIB) += slib.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_KSM) += ksm.o
 obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
diff --git a/mm/slab.h b/mm/slab.h
index 1cf40054..89c2319 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -37,6 +37,10 @@ struct kmem_cache {
 #include <linux/slub_def.h>
 #endif
 
+#ifdef CONFIG_SLIB
+#include <linux/slib_def.h>
+#endif
+
 #include <linux/memcontrol.h>
 
 /*
diff --git a/mm/slib.c b/mm/slib.c
new file mode 100644
index 0000000..37596862
--- /dev/null
+++ b/mm/slib.c
@@ -0,0 +1,205 @@
+/*
+ * Library Slab Allocator (SLIB)
+ *
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/page-flags.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/slib_def.h>
+
+/* glues */
+struct kmem_cache *files_cachep;
+
+void kfree(const void *p)
+{
+	unsigned long start;
+
+	if (p == 0)
+		return;
+	start = (unsigned long)p;
+	start -= sizeof(size_t);
+	lib_free((void *)start);
+}
+size_t ksize(const void *p)
+{
+	size_t *psize = (size_t *)p;
+
+	psize--;
+	return *psize;
+}
+void *__kmalloc(size_t size, gfp_t flags)
+{
+	void *p = lib_malloc(size + sizeof(size));
+	unsigned long start;
+
+	if (!p)
+		return NULL;
+
+	if (p != 0 && (flags & __GFP_ZERO))
+		lib_memset(p, 0, size + sizeof(size));
+	lib_memcpy(p, &size, sizeof(size));
+	start = (unsigned long)p;
+	return (void *)(start + sizeof(size));
+}
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
+{
+	return kmalloc(size, flags);
+}
+
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+
+	if (!new_size) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ret = __kmalloc(new_size, flags);
+	if (ret && p != ret)
+		kfree(p);
+
+	return ret;
+}
+
+struct kmem_cache *
+kmem_cache_create(const char *name, size_t size, size_t align,
+		  unsigned long flags, void (*ctor)(void *))
+{
+	struct kmem_cache *cache = kmalloc(sizeof(struct kmem_cache), flags);
+
+	if (!cache)
+		return NULL;
+	cache->name = name;
+	cache->size = size;
+	cache->align = align;
+	cache->flags = flags;
+	cache->ctor = ctor;
+	return cache;
+}
+void kmem_cache_destroy(struct kmem_cache *cache)
+{
+	kfree(cache);
+}
+int kmem_cache_shrink(struct kmem_cache *cache)
+{
+	return 1;
+}
+const char *kmem_cache_name(struct kmem_cache *cache)
+{
+	return cache->name;
+}
+void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+	void *p = kmalloc(cache->size, flags);
+
+	if (p == 0)
+		return NULL;
+	if (cache->ctor)
+		(cache->ctor)(p);
+	return p;
+
+}
+void kmem_cache_free(struct kmem_cache *cache, void *p)
+{
+	kfree(p);
+}
+
+struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+		       struct zonelist *zonelist, nodemask_t *nodemask)
+{
+	void *p;
+	struct page *page;
+	unsigned long pointer;
+
+	/* typically, called from networking code by alloc_page or */
+	/* directly with an order = 0. */
+	if (order)
+		return NULL;
+	p = lib_malloc(sizeof(struct page) + (1 << PAGE_SHIFT));
+	page = (struct page *)p;
+
+	atomic_set(&page->_count, 1);
+	page->flags = 0;
+	pointer = (unsigned long)page;
+	pointer += sizeof(struct page);
+	page->virtual = (void *)pointer;
+	return page;
+}
+void __free_pages(struct page *page, unsigned int order)
+{
+	/* typically, called from networking code by __free_page */
+	lib_assert(order == 0);
+	lib_free(page);
+}
+
+void put_page(struct page *page)
+{
+	if (atomic_dec_and_test(&page->_count))
+		lib_free(page);
+}
+unsigned long get_zeroed_page(gfp_t gfp_mask)
+{
+	return __get_free_pages(gfp_mask | __GFP_ZERO, 0);
+}
+
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+	return alloc_pages(gfp_mask, get_order(size));
+}
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+{
+	int size = (1 << order) * PAGE_SIZE;
+	void *p = kmalloc(size, gfp_mask);
+
+	return (unsigned long)p;
+}
+void free_pages(unsigned long addr, unsigned int order)
+{
+	if (addr != 0)
+		kfree((void *)addr);
+}
+
+void *vmalloc(unsigned long size)
+{
+	return lib_malloc(size);
+}
+void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return kmalloc(size, gfp_mask);
+}
+void vfree(const void *addr)
+{
+	lib_free((void *)addr);
+}
+void *vmalloc_node(unsigned long size, int node)
+{
+	return lib_malloc(size);
+}
+void vmalloc_sync_all(void)
+{
+}
+void *__alloc_percpu(size_t size, size_t align)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+void free_percpu(void __percpu *ptr)
+{
+	kfree(ptr);
+}
+void *__alloc_bootmem_nopanic(unsigned long size,
+			      unsigned long align,
+			      unsigned long goal)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 03/10] lib: public headers and API implementations for userspace programs
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 04/10] lib: time handling (kernel glue code) Hajime Tazaki
                       ` (8 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

userspace programs which uses libos access via a public API, lib_init(),
with passed arguments struct SimImported and struct SimExported.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 arch/lib/include/sim-assert.h |  23 +++
 arch/lib/include/sim-init.h   | 134 ++++++++++++++
 arch/lib/include/sim-printf.h |  13 ++
 arch/lib/include/sim-types.h  |  53 ++++++
 arch/lib/include/sim.h        |  51 ++++++
 arch/lib/lib-device.c         | 187 +++++++++++++++++++
 arch/lib/lib-socket.c         | 410 ++++++++++++++++++++++++++++++++++++++++++
 arch/lib/lib.c                | 294 ++++++++++++++++++++++++++++++
 arch/lib/lib.h                |  21 +++
 9 files changed, 1186 insertions(+)
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h

diff --git a/arch/lib/include/sim-assert.h b/arch/lib/include/sim-assert.h
new file mode 100644
index 0000000..974122c
--- /dev/null
+++ b/arch/lib/include/sim-assert.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_ASSERT_H
+#define SIM_ASSERT_H
+
+#include "sim-printf.h"
+
+#define lib_assert(v) {							\
+		while (!(v)) {						\
+			lib_printf("Assert failed %s:%u \"" #v "\"\n",	\
+				__FILE__, __LINE__);			\
+			char *p = 0;					\
+			*p = 1;						\
+		}							\
+	}
+
+
+#endif /* SIM_ASSERT_H */
diff --git a/arch/lib/include/sim-init.h b/arch/lib/include/sim-init.h
new file mode 100644
index 0000000..e871a59
--- /dev/null
+++ b/arch/lib/include/sim-init.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_INIT_H
+#define SIM_INIT_H
+
+#include <linux/socket.h>
+#include "sim-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
+
+struct SimExported {
+	struct SimTask *(*task_create)(void *priv, unsigned long pid);
+	void (*task_destroy)(struct SimTask *task);
+	void *(*task_get_private)(struct SimTask *task);
+
+	int (*sock_socket)(int domain, int type, int protocol,
+			struct SimSocket **socket);
+	int (*sock_close)(struct SimSocket *socket);
+	ssize_t (*sock_recvmsg)(struct SimSocket *socket, struct msghdr *msg,
+				int flags);
+	ssize_t (*sock_sendmsg)(struct SimSocket *socket,
+				const struct msghdr *msg, int flags);
+	int (*sock_getsockname)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_getpeername)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_bind)(struct SimSocket *socket, const struct sockaddr *name,
+			int namelen);
+	int (*sock_connect)(struct SimSocket *socket,
+			const struct sockaddr *name, int namelen,
+			int flags);
+	int (*sock_listen)(struct SimSocket *socket, int backlog);
+	int (*sock_shutdown)(struct SimSocket *socket, int how);
+	int (*sock_accept)(struct SimSocket *socket,
+			struct SimSocket **newSocket, int flags);
+	int (*sock_ioctl)(struct SimSocket *socket, int request, char *argp);
+	int (*sock_setsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			const void *optval, int optlen);
+	int (*sock_getsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			void *optval, int *optlen);
+
+	void (*sock_poll)(struct SimSocket *socket, void *ret);
+	void (*sock_pollfreewait)(void *polltable);
+
+	struct SimDevice *(*dev_create)(const char *ifname, void *priv,
+					enum SimDevFlags flags);
+	void (*dev_destroy)(struct SimDevice *dev);
+	void *(*dev_get_private)(struct SimDevice *task);
+	void (*dev_set_address)(struct SimDevice *dev,
+				unsigned char buffer[6]);
+	void (*dev_set_mtu)(struct SimDevice *dev, int mtu);
+	struct SimDevicePacket (*dev_create_packet)(struct SimDevice *dev,
+						int size);
+	void (*dev_rx)(struct SimDevice *dev, struct SimDevicePacket packet);
+
+	void (*sys_iterate_files)(const struct SimSysIterator *iter);
+	int (*sys_file_read)(const struct SimSysFile *file, char *buffer,
+			int size, int offset);
+	int (*sys_file_write)(const struct SimSysFile *file,
+			const char *buffer, int size, int offset);
+};
+
+struct SimImported {
+	int (*vprintf)(struct SimKernel *kernel, const char *str,
+		va_list args);
+	void *(*malloc)(struct SimKernel *kernel, unsigned long size);
+	void (*free)(struct SimKernel *kernel, void *buffer);
+	void *(*memcpy)(struct SimKernel *kernel, void *dst, const void *src,
+			unsigned long size);
+	void *(*memset)(struct SimKernel *kernel, void *dst, char value,
+			unsigned long size);
+	int (*atexit)(struct SimKernel *kernel, void (*function)(void));
+	int (*access)(struct SimKernel *kernel, const char *pathname,
+		int mode);
+	char *(*getenv)(struct SimKernel *kernel, const char *name);
+	int (*mkdir)(struct SimKernel *kernel, const char *pathname,
+		mode_t mode);
+	int (*open)(struct SimKernel *kernel, const char *pathname, int flags);
+	int (*__fxstat)(struct SimKernel *kernel, int ver, int fd, void *buf);
+	int (*fseek)(struct SimKernel *kernel, FILE *stream, long offset,
+		int whence);
+	void (*setbuf)(struct SimKernel *kernel, FILE *stream, char *buf);
+	FILE *(*fdopen)(struct SimKernel *kernel, int fd, const char *mode);
+	long (*ftell)(struct SimKernel *kernel, FILE *stream);
+	int (*fclose)(struct SimKernel *kernel, FILE *fp);
+	size_t (*fread)(struct SimKernel *kernel, void *ptr, size_t size,
+			size_t nmemb, FILE *stream);
+	size_t (*fwrite)(struct SimKernel *kernel, const void *ptr, size_t size,
+			 size_t nmemb, FILE *stream);
+
+	unsigned long (*random)(struct SimKernel *kernel);
+	void *(*event_schedule_ns)(struct SimKernel *kernel, __u64 ns,
+				void (*fn)(void *context), void *context,
+				void (*pre_fn)(void));
+	void (*event_cancel)(struct SimKernel *kernel, void *event);
+	__u64 (*current_ns)(struct SimKernel *kernel);
+
+	struct SimTask *(*task_start)(struct SimKernel *kernel,
+				void (*callback)(void *),
+				void *context);
+	void (*task_wait)(struct SimKernel *kernel);
+	struct SimTask *(*task_current)(struct SimKernel *kernel);
+	int (*task_wakeup)(struct SimKernel *kernel, struct SimTask *task);
+	void (*task_yield)(struct SimKernel *kernel);
+
+	void (*dev_xmit)(struct SimKernel *kernel, struct SimDevice *dev,
+			unsigned char *data, int len);
+	void (*signal_raised)(struct SimKernel *kernel, struct SimTask *task,
+			int sig);
+	void (*poll_event)(int flag, void *context);
+};
+
+typedef void (*SimInit)(struct SimExported *, const struct SimImported *,
+			struct SimKernel *kernel);
+void sim_init(struct SimExported *exported, const struct SimImported *imported,
+	struct SimKernel *kernel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_INIT_H */
diff --git a/arch/lib/include/sim-printf.h b/arch/lib/include/sim-printf.h
new file mode 100644
index 0000000..2bf8245
--- /dev/null
+++ b/arch/lib/include/sim-printf.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_PRINTF_H
+#define SIM_PRINTF_H
+
+void lib_printf(const char *str, ...);
+
+#endif /* SIM_PRINTF_H */
diff --git a/arch/lib/include/sim-types.h b/arch/lib/include/sim-types.h
new file mode 100644
index 0000000..d50b99b
--- /dev/null
+++ b/arch/lib/include/sim-types.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_TYPES_H
+#define SIM_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBOS_API_VERSION     2
+
+struct SimTask;
+struct SimDevice;
+struct SimSocket;
+struct SimKernel;
+struct SimSysFile;
+
+enum SimDevFlags {
+	SIM_DEV_NOARP         = (1 << 0),
+	SIM_DEV_POINTTOPOINT  = (1 << 1),
+	SIM_DEV_MULTICAST     = (1 << 2),
+	SIM_DEV_BROADCAST     = (1 << 3),
+};
+
+struct SimDevicePacket {
+	void *buffer;
+	void *token;
+};
+
+enum SimSysFileFlags {
+	SIM_SYS_FILE_READ  = 1 << 0,
+	SIM_SYS_FILE_WRITE = 1 << 1,
+};
+
+struct SimSysIterator {
+	void (*report_start_dir)(const struct SimSysIterator *iter,
+				const char *dirname);
+	void (*report_end_dir)(const struct SimSysIterator *iter);
+	void (*report_file)(const struct SimSysIterator *iter,
+			const char *filename,
+			int flags, struct SimSysFile *file);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_TYPES_H */
diff --git a/arch/lib/include/sim.h b/arch/lib/include/sim.h
new file mode 100644
index 0000000..b30d7e8
--- /dev/null
+++ b/arch/lib/include/sim.h
@@ -0,0 +1,51 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_H
+#define SIM_H
+
+#include <stdarg.h>
+#include <linux/types.h>
+
+#include "sim-types.h"
+
+/* API called from within linux kernel. Forwards to SimImported. */
+int lib_vprintf(const char *str, va_list args);
+void *lib_malloc(unsigned long size);
+void lib_free(void *buffer);
+void *lib_memcpy(void *dst, const void *src, unsigned long size);
+void *lib_memset(void *dst, char value, unsigned long size);
+unsigned long lib_random(void);
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context),
+			    void *context);
+void lib_event_cancel(void *event);
+__u64 lib_current_ns(void);
+
+struct SimTask *lib_task_start(void (*callback) (void *), void *context);
+void lib_task_wait(void);
+void lib_task_yield(void);
+struct SimTask *lib_task_current(void);
+/* returns 1 if task was woken up, 0 if it was already running. */
+int lib_task_wakeup(struct SimTask *task);
+struct SimTask *lib_task_create(void *priv, unsigned long pid);
+void lib_task_destroy(struct SimTask *task);
+void *lib_task_get_private(struct SimTask *task);
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len);
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size);
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet);
+
+void lib_signal_raised(struct SimTask *task, int sig);
+
+void lib_poll_event(int flag, void *context);
+void lib_softirq_wakeup(void);
+void lib_update_jiffies(void);
+void *lib_dev_get_private(struct SimDevice *);
+void lib_proc_net_initialize(void);
+
+#endif /* SIM_H */
diff --git a/arch/lib/lib-device.c b/arch/lib/lib-device.c
new file mode 100644
index 0000000..1efa6460
--- /dev/null
+++ b/arch/lib/lib-device.c
@@ -0,0 +1,187 @@
+/*
+ * virtual net_device feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ethtool.h>
+
+struct SimDevice {
+	struct net_device dev;
+	void *priv;
+};
+
+static netdev_tx_t
+kernel_dev_xmit(struct sk_buff *skb,
+		struct net_device *dev)
+{
+	int err;
+
+	netif_stop_queue(dev);
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		err = skb_checksum_help(skb);
+		if (unlikely(err)) {
+			pr_err("checksum error (%d)\n", err);
+			return 0;
+		}
+	}
+
+	lib_dev_xmit((struct SimDevice *)dev, skb->data, skb->len);
+	dev_kfree_skb(skb);
+	netif_wake_queue(dev);
+	return 0;
+}
+
+static u32 always_on(struct net_device *dev)
+{
+	return 1;
+}
+
+
+static const struct ethtool_ops lib_ethtool_ops = {
+	.get_link		= always_on,
+};
+
+static const struct net_device_ops lib_dev_ops = {
+	.ndo_start_xmit		= kernel_dev_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static void lib_dev_setup(struct net_device *dev)
+{
+	dev->mtu                = (16 * 1024) + 20 + 20 + 12;
+	dev->hard_header_len    = ETH_HLEN;     /* 14   */
+	dev->addr_len           = ETH_ALEN;     /* 6    */
+	dev->tx_queue_len       = 0;
+	dev->type               = ARPHRD_ETHER;
+	dev->flags              = 0;
+	/* dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE; */
+	dev->features           = 0
+				  | NETIF_F_HIGHDMA
+				  | NETIF_F_NETNS_LOCAL;
+	/* disabled  NETIF_F_TSO NETIF_F_SG  NETIF_F_FRAGLIST NETIF_F_LLTX */
+	dev->ethtool_ops        = &lib_ethtool_ops;
+	dev->header_ops         = &eth_header_ops;
+	dev->netdev_ops         = &lib_dev_ops;
+	dev->destructor         = &free_netdev;
+}
+
+
+struct SimDevice *lib_dev_create(const char *ifname, void *priv,
+				 enum SimDevFlags flags)
+{
+	int err;
+	struct SimDevice *dev =
+		(struct SimDevice *)alloc_netdev(sizeof(struct SimDevice),
+						 ifname, NET_NAME_UNKNOWN,
+						 &lib_dev_setup);
+	ether_setup((struct net_device *)dev);
+
+	if (flags & SIM_DEV_NOARP)
+		dev->dev.flags |= IFF_NOARP;
+	if (flags & SIM_DEV_POINTTOPOINT)
+		dev->dev.flags |= IFF_POINTOPOINT;
+	if (flags & SIM_DEV_MULTICAST)
+		dev->dev.flags |= IFF_MULTICAST;
+	if (flags & SIM_DEV_BROADCAST) {
+		dev->dev.flags |= IFF_BROADCAST;
+		memset(dev->dev.broadcast, 0xff, 6);
+	}
+	dev->priv = priv;
+	err = register_netdev(&dev->dev);
+	return dev;
+}
+void lib_dev_destroy(struct SimDevice *dev)
+{
+	unregister_netdev(&dev->dev);
+	/* XXX */
+	free_netdev(&dev->dev);
+}
+void *lib_dev_get_private(struct SimDevice *dev)
+{
+	return dev->priv;
+}
+
+void lib_dev_set_mtu(struct SimDevice *dev, int mtu)
+{
+	/* called by ns-3 to synchronize the kernel mtu with */
+	/* the simulation mtu */
+	dev->dev.mtu = mtu;
+}
+
+static int lib_ndo_change_mtu(struct net_device *dev,
+			      int new_mtu)
+{
+	/* called by kernel to change the mtu when the user */
+	/* asks for it. */
+	/* XXX should forward the set call to ns-3 and wait for */
+	/* ns-3 to notify of the change in the function above */
+	/* but I am way too tired to do this now. */
+	return 0;
+}
+
+void lib_dev_set_address(struct SimDevice *dev, unsigned char buffer[6])
+{
+	/* called by ns-3 to synchronize the kernel address with */
+	/* the simulation address. */
+	struct sockaddr sa;
+
+	sa.sa_family = dev->dev.type;
+	lib_memcpy(&sa.sa_data, buffer, 6);
+	dev->dev.netdev_ops->ndo_set_mac_address(&dev->dev, &sa);
+	/* Note that we don't call   dev_set_mac_address (&dev->dev, &sa); */
+	/* because this function expects to be called from within */
+	/* the netlink layer so, it expects to hold */
+	/* the netlink lock during the execution of the associated notifiers */
+}
+static int get_hack_size(int size)
+{
+	/* Note: this hack is coming from nsc */
+	/* Bit of a hack... */
+	/* Note that the size allocated here effects the offered window
+	   somewhat. I've got this heuristic here to try and match up with
+	   what we observe on the emulation network and by looking at the
+	   driver code of the eepro100. In both cases we allocate enough
+	   space for our packet, which  is the important thing. The amount
+	   of slack at the end can make linux decide the grow the window
+	   differently. This is quite subtle, but the code in question is
+	   in the tcp_grow_window function. It checks skb->truesize, which
+	   is the size of the skbuff allocated for the incoming data
+	   packet -- what we are allocating right now! */
+	if (size < 1200)
+		return size + 36;
+	else if (size <= 1500)
+		return 1536;
+	else
+		return size + 36;
+}
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size)
+{
+	struct SimDevicePacket packet;
+	int len = get_hack_size(size);
+	struct sk_buff *skb = __dev_alloc_skb(len, __GFP_WAIT);
+
+	packet.token = skb;
+	packet.buffer = skb_put(skb, len);
+	return packet;
+}
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet)
+{
+	struct sk_buff *skb = packet.token;
+	struct net_device *dev = &device->dev;
+
+	skb->protocol = eth_type_trans(skb, dev);
+	/* Do the TCP checksum (FIXME: should be configurable) */
+	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	netif_rx(skb);
+}
diff --git a/arch/lib/lib-socket.c b/arch/lib/lib-socket.c
new file mode 100644
index 0000000..d9be5fc
--- /dev/null
+++ b/arch/lib/lib-socket.c
@@ -0,0 +1,410 @@
+/*
+ * socket feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/net.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/inet_connection_sock.h>
+
+struct SimSocket {};
+
+static struct iovec *copy_iovec(const struct iovec *input, int len)
+{
+	int size = sizeof(struct iovec) * len;
+	struct iovec *output = lib_malloc(size);
+
+	if (!output)
+		return NULL;
+	lib_memcpy(output, input, size);
+	return output;
+}
+
+int lib_sock_socket(int domain, int type, int protocol,
+		    struct SimSocket **socket)
+{
+	struct socket **kernel_socket = (struct socket **)socket;
+	int flags;
+
+	/* from net/socket.c */
+	flags = type & ~SOCK_TYPE_MASK;
+	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+		return -EINVAL;
+	type &= SOCK_TYPE_MASK;
+
+	int retval = sock_create(domain, type, protocol, kernel_socket);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	struct file *fp = lib_malloc(sizeof(struct file));
+	(*kernel_socket)->file = fp;
+	fp->f_cred = lib_malloc(sizeof(struct cred));
+	return retval;
+}
+int lib_sock_close(struct SimSocket *socket)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+
+	sock_release(kernel_socket);
+	return 0;
+}
+static size_t iov_size(const struct user_msghdr *msg)
+{
+	size_t i;
+	size_t size = 0;
+
+	for (i = 0; i < msg->msg_iovlen; i++)
+		size += msg->msg_iov[i].iov_len;
+	return size;
+}
+ssize_t lib_sock_recvmsg(struct SimSocket *socket,
+			struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct msghdr msg_sys;
+	struct cmsghdr *user_cmsgh = msg->msg_control;
+	size_t user_cmsghlen = msg->msg_controllen;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, READ,
+		msg->msg_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_recvmsg(kernel_socket, &msg_sys, iov_size(msg), flags);
+
+	msg->msg_name = msg_sys.msg_name;
+	msg->msg_namelen = msg_sys.msg_namelen;
+	msg->msg_control = user_cmsgh;
+	msg->msg_controllen = user_cmsghlen - msg_sys.msg_controllen;
+	return retval;
+}
+ssize_t lib_sock_sendmsg(struct SimSocket *socket,
+			const struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct iovec *kernel_iov = copy_iovec(msg->msg_iov, msg->msg_iovlen);
+	struct msghdr msg_sys;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, WRITE,
+		kernel_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_sendmsg(kernel_socket, &msg_sys);
+	lib_free(kernel_iov);
+	return retval;
+}
+int lib_sock_getsockname(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 0);
+
+	return retval;
+}
+int lib_sock_getpeername(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 1);
+
+	return retval;
+}
+int lib_sock_bind(struct SimSocket *socket, const struct sockaddr *name,
+		  int namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	int retval =
+		sock->ops->bind(sock, (struct sockaddr *)&address, namelen);
+	return retval;
+}
+int lib_sock_connect(struct SimSocket *socket, const struct sockaddr *name,
+		     int namelen, int flags)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	sock->file->f_flags = flags;
+	int retval = sock->ops->connect(sock, (struct sockaddr *)&address,
+					namelen, flags);
+	return retval;
+}
+int lib_sock_listen(struct SimSocket *socket, int backlog)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->listen(sock, backlog);
+
+	return retval;
+}
+int lib_sock_shutdown(struct SimSocket *socket, int how)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->shutdown(sock, how);
+
+	return retval;
+}
+int lib_sock_accept(struct SimSocket *socket, struct SimSocket **new_socket,
+		    int flags)
+{
+	struct socket *sock, *newsock;
+	int err;
+
+	sock = (struct socket *)socket;
+
+	/* the fields do not matter here. If we could, */
+	/* we would call sock_alloc but it's not exported. */
+	err = sock_create_lite(0, 0, 0, &newsock);
+	if (err < 0)
+		return err;
+	newsock->type = sock->type;
+	newsock->ops = sock->ops;
+
+	err = sock->ops->accept(sock, newsock, flags);
+	if (err < 0) {
+		sock_release(newsock);
+		return err;
+	}
+	*new_socket = (struct SimSocket *)newsock;
+	return 0;
+}
+int lib_sock_ioctl(struct SimSocket *socket, int request, char *argp)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sock *sk;
+	struct net *net;
+	int err;
+
+	sk = sock->sk;
+	net = sock_net(sk);
+
+	err = sock->ops->ioctl(sock, request, (long)argp);
+
+	/*
+	 * If this ioctl is unknown try to hand it down
+	 * to the NIC driver.
+	 */
+	if (err == -ENOIOCTLCMD)
+		err = dev_ioctl(net, request, argp);
+	return err;
+}
+int lib_sock_setsockopt(struct SimSocket *socket, int level, int optname,
+			const void *optval, int optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	char *coptval = (char *)optval;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_setsockopt(sock, level, optname, coptval, optlen);
+	else
+		err = sock->ops->setsockopt(sock, level, optname, coptval,
+					    optlen);
+	return err;
+}
+int lib_sock_getsockopt(struct SimSocket *socket, int level, int optname,
+			void *optval, int *optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_getsockopt(sock, level, optname, optval, optlen);
+	else
+		err =
+			sock->ops->getsockopt(sock, level, optname, optval,
+					      optlen);
+	return err;
+}
+
+int lib_sock_canrecv(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct inet_connection_sock *icsk;
+
+	switch (sock->sk->sk_state) {
+	case TCP_CLOSE:
+		if (SOCK_STREAM == sock->sk->sk_type)
+			return 1;
+	case TCP_ESTABLISHED:
+		return sock->sk->sk_receive_queue.qlen > 0;
+	case TCP_SYN_SENT:
+	case TCP_SYN_RECV:
+	case TCP_LAST_ACK:
+	case TCP_CLOSING:
+		return 0;
+	case TCP_FIN_WAIT1:
+	case TCP_FIN_WAIT2:
+	case TCP_TIME_WAIT:
+	case TCP_CLOSE_WAIT:
+		return 1;
+	case TCP_LISTEN:
+	{
+		icsk = inet_csk(sock->sk);
+		return !reqsk_queue_empty(&icsk->icsk_accept_queue);
+	}
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+int lib_sock_cansend(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+
+	return sock_writeable(sock->sk);
+}
+
+/**
+ * Struct used to pass pool table context between DCE and Kernel and back from
+ * Kernel to DCE
+ *
+ * When calling sock_poll we provide in ret field the wanted eventmask, and in
+ * the opaque field the DCE poll table
+ *
+ * if a corresponding event occurs later, the PollEvent will be called by kernel
+ * with the DCE poll table in context variable, then we will able to wake up the
+ * thread blocked in poll call.
+ *
+ * Back from sock_poll method the kernel change ret field with the response from
+ * poll return of the corresponding kernel socket, and in opaque field there is
+ * a reference to the kernel poll table we will use this reference to remove us
+ * from the file wait queue when ending the DCE poll call or when ending the DCE
+ * process which is currently polling.
+ *
+ */
+struct poll_table_ref {
+	int ret;
+	void *opaque;
+};
+
+/* Because the poll main loop code is in NS3/DCE we have only on entry
+   in our kernel poll table */
+struct lib_ptable_entry {
+	wait_queue_t wait;
+	wait_queue_head_t *wait_address;
+	int eventMask;  /* Poll wanted event mask. */
+	void *opaque;   /* Pointeur to DCE poll table */
+};
+
+static int lib_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)wait->private;
+
+	/* Filter only wanted events */
+	if (key && !((unsigned long)key & entry->eventMask))
+		return 0;
+
+	lib_poll_event((unsigned long)key, entry->opaque);
+	return 1;
+}
+
+static void lib_pollwait(struct file *filp, wait_queue_head_t *wait_address,
+			 poll_table *p)
+{
+	struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)
+		lib_malloc(sizeof(struct lib_ptable_entry));
+	struct poll_table_ref *fromDCE =  (struct poll_table_ref *)pwq->table;
+
+	if (!entry)
+		return;
+
+	entry->opaque = fromDCE->opaque; /* Copy DCE poll table reference */
+	entry->eventMask = fromDCE->ret; /* Copy poll mask of wanted events. */
+
+	pwq->table = (struct poll_table_page *)entry;
+
+	init_waitqueue_func_entry(&entry->wait, lib_pollwake);
+	entry->wait.private = entry;
+	entry->wait_address = wait_address;
+	add_wait_queue(wait_address, &entry->wait);
+}
+
+void dce_poll_initwait(struct poll_wqueues *pwq)
+{
+	init_poll_funcptr(&pwq->pt, lib_pollwait);
+	pwq->polling_task = current;
+	pwq->triggered = 0;
+	pwq->error = 0;
+	pwq->table = NULL;
+	pwq->inline_index = 0;
+}
+
+/* call poll on socket ... */
+void lib_sock_poll(struct SimSocket *socket, struct poll_table_ref *ret)
+{
+	struct socket *sock = (struct socket *)socket;
+	/* Provide a fake file structure */
+	struct file zero;
+	poll_table *pwait = 0;
+	struct poll_wqueues *ptable = 0;
+
+	lib_memset(&zero, 0, sizeof(struct file));
+
+	if (ret->opaque) {
+		ptable =
+			(struct poll_wqueues *)lib_malloc(sizeof(struct
+								 poll_wqueues));
+		if (!ptable)
+			return;
+
+		dce_poll_initwait(ptable);
+
+		pwait = &(ptable->pt);
+		/* Pass the DCE pool table to lib_pollwait function */
+		ptable->table = (struct poll_table_page *)ret;
+	}
+
+	ret->ret = sock->ops->poll(&zero, sock, pwait);
+	/* Pass back the kernel poll table to DCE in order to DCE to */
+	/* remove from wait queue */
+	/* using lib_sock_pollfreewait method below */
+	ret->opaque = ptable;
+}
+
+void lib_sock_pollfreewait(void *polltable)
+{
+	struct poll_wqueues *ptable = (struct poll_wqueues *)polltable;
+
+	if (ptable && ptable->table) {
+		struct lib_ptable_entry *entry =
+			(struct lib_ptable_entry *)ptable->table;
+		remove_wait_queue(entry->wait_address, &entry->wait);
+		lib_free(entry);
+	}
+	lib_free(ptable);
+}
+
+
+
+
diff --git a/arch/lib/lib.c b/arch/lib/lib.c
new file mode 100644
index 0000000..52d638e
--- /dev/null
+++ b/arch/lib/lib.c
@@ -0,0 +1,294 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/init.h>         /* initcall_t */
+#include <linux/kernel.h>       /* SYSTEM_BOOTING */
+#include <linux/sched.h>        /* struct task_struct */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <drivers/base/base.h>
+#include <linux/idr.h>
+#include <linux/rcupdate.h>
+#include "sim-init.h"
+#include "sim.h"
+
+enum system_states system_state = SYSTEM_BOOTING;
+/* glues */
+struct task_struct init_task;
+
+struct SimImported g_imported;
+
+
+#define RETURN_void(rettype, v)				     \
+	({						     \
+		(v);					     \
+		lib_softirq_wakeup();			     \
+	})
+
+#define RETURN_nvoid(rettype, v)			     \
+	({						     \
+		rettype x = (v);			     \
+		lib_softirq_wakeup();			     \
+		x;					     \
+	})
+
+#define FORWARDER1(name, type, rettype, t0)			    \
+	extern rettype name(t0);				    \
+	static rettype name ## _forwarder(t0 v0)		    \
+	{							    \
+		lib_update_jiffies();				    \
+		return RETURN_ ## type(rettype, (name(v0)));        \
+	}
+
+#define FORWARDER2(name, type, rettype, t0, t1)				\
+	extern rettype name(t0, t1);					\
+	static rettype name ## _forwarder(t0 v0, t1 v1)			\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1)));	\
+	}
+#define FORWARDER3(name, type, rettype, t0, t1, t2)			\
+	extern rettype name(t0, t1, t2);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2)		\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2)));	\
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER5(name, type, rettype, t0, t1, t2, t3, t4)		\
+	extern rettype name(t0, t1, t2, t3, t4);			\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3, t4 v4) \
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3, v4))); \
+	}
+
+FORWARDER3(lib_dev_create, nvoid, struct SimDevice *, const char *, void *,
+	   enum SimDevFlags);
+FORWARDER1(lib_dev_destroy, void, void, struct SimDevice *);
+FORWARDER2(lib_dev_set_address, void, void, struct SimDevice *,
+	   unsigned char *);
+FORWARDER2(lib_dev_set_mtu, void, void, struct SimDevice *, int);
+FORWARDER2(lib_dev_create_packet, nvoid, struct SimDevicePacket,
+	   struct SimDevice *, int);
+FORWARDER2(lib_dev_rx, void, void, struct SimDevice *, struct SimDevicePacket);
+
+FORWARDER4(lib_sock_socket, nvoid, int, int, int, int, struct SimSocket **);
+FORWARDER1(lib_sock_close, nvoid, int, struct SimSocket *);
+FORWARDER3(lib_sock_recvmsg, nvoid, ssize_t, struct SimSocket *,
+	   struct msghdr *, int);
+FORWARDER3(lib_sock_sendmsg, nvoid, ssize_t, struct SimSocket *,
+	   const struct msghdr *, int);
+FORWARDER3(lib_sock_getsockname, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_getpeername, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_bind, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int);
+FORWARDER4(lib_sock_connect, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int, int);
+FORWARDER2(lib_sock_listen, nvoid, int, struct SimSocket *, int);
+FORWARDER2(lib_sock_shutdown, nvoid, int, struct SimSocket *, int);
+FORWARDER3(lib_sock_accept, nvoid, int, struct SimSocket *,
+	   struct SimSocket **, int);
+FORWARDER3(lib_sock_ioctl, nvoid, int, struct SimSocket *, int, char *);
+FORWARDER5(lib_sock_setsockopt, nvoid, int, struct SimSocket *, int, int,
+	   const void *, int);
+FORWARDER5(lib_sock_getsockopt, nvoid, int, struct SimSocket *, int, int,
+	   void *, int *);
+
+FORWARDER2(lib_sock_poll, void, void, struct SimSocket *, void *);
+FORWARDER1(lib_sock_pollfreewait, void, void, void *);
+
+FORWARDER1(lib_sys_iterate_files, void, void, const struct SimSysIterator *);
+FORWARDER4(lib_sys_file_read, nvoid, int, const struct SimSysFile *, char *,
+	   int, int);
+FORWARDER4(lib_sys_file_write, nvoid, int, const struct SimSysFile *,
+	   const char *, int, int);
+
+struct SimKernel *g_kernel;
+
+void lib_init(struct SimExported *exported, const struct SimImported *imported,
+	      struct SimKernel *kernel)
+{
+	/* make sure we can call the callbacks */
+	g_imported = *imported;
+	g_kernel = kernel;
+	exported->task_create = lib_task_create;
+	exported->task_destroy = lib_task_destroy;
+	exported->task_get_private = lib_task_get_private;
+	exported->sock_socket = lib_sock_socket_forwarder;
+	exported->sock_close = lib_sock_close_forwarder;
+	exported->sock_recvmsg = lib_sock_recvmsg_forwarder;
+	exported->sock_sendmsg = lib_sock_sendmsg_forwarder;
+	exported->sock_getsockname = lib_sock_getsockname_forwarder;
+	exported->sock_getpeername = lib_sock_getpeername_forwarder;
+	exported->sock_bind = lib_sock_bind_forwarder;
+	exported->sock_connect = lib_sock_connect_forwarder;
+	exported->sock_listen = lib_sock_listen_forwarder;
+	exported->sock_shutdown = lib_sock_shutdown_forwarder;
+	exported->sock_accept = lib_sock_accept_forwarder;
+	exported->sock_ioctl = lib_sock_ioctl_forwarder;
+	exported->sock_setsockopt = lib_sock_setsockopt_forwarder;
+	exported->sock_getsockopt = lib_sock_getsockopt_forwarder;
+
+	exported->sock_poll = lib_sock_poll_forwarder;
+	exported->sock_pollfreewait = lib_sock_pollfreewait_forwarder;
+
+	exported->dev_create = lib_dev_create_forwarder;
+	exported->dev_destroy = lib_dev_destroy_forwarder;
+	exported->dev_get_private = lib_dev_get_private;
+	exported->dev_set_address = lib_dev_set_address_forwarder;
+	exported->dev_set_mtu = lib_dev_set_mtu_forwarder;
+	exported->dev_create_packet = lib_dev_create_packet_forwarder;
+	exported->dev_rx = lib_dev_rx_forwarder;
+
+	exported->sys_iterate_files = lib_sys_iterate_files_forwarder;
+	exported->sys_file_write = lib_sys_file_write_forwarder;
+	exported->sys_file_read = lib_sys_file_read_forwarder;
+
+	pr_notice("%s", linux_banner);
+
+	rcu_init();
+
+	/* in drivers/base/core.c (called normally by drivers/base/init.c) */
+	devices_init();
+	/* in lib/idr.c (called normally by init/main.c) */
+	idr_init_cache();
+	vfs_caches_init(totalram_pages);
+
+	lib_proc_net_initialize();
+
+	/* and, then, call the normal initcalls */
+	initcall_t *call;
+	extern initcall_t __initcall_start[], __initcall_end[];
+
+	call = __initcall_start;
+	do {
+		(*call)();
+		call++;
+	} while (call < __initcall_end);
+
+	/* finally, put the system in RUNNING state. */
+	system_state = SYSTEM_RUNNING;
+}
+
+int lib_vprintf(const char *str, va_list args)
+{
+	return g_imported.vprintf(g_kernel, str, args);
+}
+void *lib_malloc(unsigned long size)
+{
+	return g_imported.malloc(g_kernel, size);
+}
+void lib_free(void *buffer)
+{
+	return g_imported.free(g_kernel, buffer);
+}
+void *lib_memcpy(void *dst, const void *src, unsigned long size)
+{
+	return g_imported.memcpy(g_kernel, dst, src, size);
+}
+void *lib_memset(void *dst, char value, unsigned long size)
+{
+	return g_imported.memset(g_kernel, dst, value, size);
+}
+unsigned long lib_random(void)
+{
+	return g_imported.random(g_kernel);
+}
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context), void *context)
+{
+	return g_imported.event_schedule_ns(g_kernel, ns, fn, context,
+					    lib_update_jiffies);
+}
+void lib_event_cancel(void *event)
+{
+	return g_imported.event_cancel(g_kernel, event);
+}
+__u64 lib_current_ns(void)
+{
+	return g_imported.current_ns(g_kernel);
+}
+struct SimTaskTrampolineContext {
+	void (*callback)(void *);
+	void *context;
+};
+static void lib_task_start_trampoline(void *context)
+{
+	/* we use this trampoline solely for the purpose of executing
+	   lib_update_jiffies prior to calling the callback. */
+	struct SimTaskTrampolineContext *ctx = context;
+	void (*callback)(void *) = ctx->callback;
+	void *callback_context = ctx->context;
+
+	lib_free(ctx);
+	lib_update_jiffies();
+	callback(callback_context);
+}
+struct SimTask *lib_task_start(void (*callback) (void *), void *context)
+{
+	struct SimTaskTrampolineContext *ctx =
+		lib_malloc(sizeof(struct SimTaskTrampolineContext));
+
+	if (!ctx)
+		return NULL;
+	ctx->callback = callback;
+	ctx->context = context;
+	return g_imported.task_start(g_kernel, &lib_task_start_trampoline, ctx);
+}
+void lib_task_wait(void)
+{
+	rcu_sched_qs();
+	g_imported.task_wait(g_kernel);
+	lib_update_jiffies();
+}
+struct SimTask *lib_task_current(void)
+{
+	return g_imported.task_current(g_kernel);
+}
+int lib_task_wakeup(struct SimTask *task)
+{
+	return g_imported.task_wakeup(g_kernel, task);
+}
+void lib_task_yield(void)
+{
+	rcu_idle_enter();
+	g_imported.task_yield(g_kernel);
+	rcu_idle_exit();
+	lib_update_jiffies();
+}
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len)
+{
+	return g_imported.dev_xmit(g_kernel, dev, data, len);
+}
+
+void lib_signal_raised(struct SimTask *task, int sig)
+{
+	g_imported.signal_raised(g_kernel, task, sig);
+}
+
+void lib_poll_event(int flag, void *context)
+{
+	g_imported.poll_event(flag, context);
+}
diff --git a/arch/lib/lib.h b/arch/lib/lib.h
new file mode 100644
index 0000000..abf2a26
--- /dev/null
+++ b/arch/lib/lib.h
@@ -0,0 +1,21 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#ifndef LIB_H
+#define LIB_H
+
+#include <linux/sched.h>
+
+struct SimTask {
+	struct list_head head;
+	struct task_struct kernel_task;
+	void *private;
+};
+
+#endif /* LIB_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 04/10] lib: time handling (kernel glue code)
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (2 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
                       ` (7 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

timer related (internal) functions such as add_timer(),
do_gettimeofday() of kernel are trivially reimplemented
for libos. these eventually call the functions registered by lib_init()
API.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/hrtimer.c         | 122 +++++++++++++++++++++++
 arch/lib/tasklet-hrtimer.c |  57 +++++++++++
 arch/lib/time.c            | 144 +++++++++++++++++++++++++++
 arch/lib/timer.c           | 238 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 561 insertions(+)
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c

diff --git a/arch/lib/hrtimer.c b/arch/lib/hrtimer.c
new file mode 100644
index 0000000..4565b59
--- /dev/null
+++ b/arch/lib/hrtimer.c
@@ -0,0 +1,122 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/hrtimer.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ * @timer:      the timer to be initialized
+ * @clock_id:   the clock to be used
+ * @mode:       timer mode abs/rel
+ */
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+		  enum hrtimer_mode mode)
+{
+	memset(timer, 0, sizeof(*timer));
+}
+static void trampoline(void *context)
+{
+	struct hrtimer *timer = context;
+	enum hrtimer_restart restart = timer->function(timer);
+
+	if (restart == HRTIMER_RESTART) {
+		void *event =
+			lib_event_schedule_ns(ktime_to_ns(timer->_softexpires),
+					      &trampoline, timer);
+		timer->base = event;
+	} else {
+		/* mark as completed. */
+		timer->base = 0;
+	}
+}
+/**
+ * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
+ * @timer:      the timer to be added
+ * @tim:        expiry time
+ * @delta_ns:   "slack" range for the timer
+ * @mode:       expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
+ *
+ * Returns:
+ *  0 on success
+ *  1 when the timer was active
+ */
+int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			     unsigned long delta_ns,
+			     const enum hrtimer_mode mode,
+			     int wakeup)
+{
+	int ret = hrtimer_cancel(timer);
+	s64 ns = ktime_to_ns(tim);
+	void *event;
+
+	if (mode == HRTIMER_MODE_ABS)
+		ns -= lib_current_ns();
+	timer->_softexpires = ns_to_ktime(ns);
+	event = lib_event_schedule_ns(ns, &trampoline, timer);
+	timer->base = event;
+	return ret;
+}
+/**
+ * hrtimer_try_to_cancel - try to deactivate a timer
+ * @timer:      hrtimer to stop
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ * -1 when the timer is currently excuting the callback function and
+ *    cannot be stopped
+ */
+int hrtimer_try_to_cancel(struct hrtimer *timer)
+{
+	/* Note: we cannot return -1 from this function.
+	   see comment in hrtimer_cancel. */
+	if (timer->base == 0)
+		/* timer was not active yet */
+		return 1;
+	lib_event_cancel(timer->base);
+	timer->base = 0;
+	return 0;
+}
+/**
+ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
+ * @timer:      the timer to be cancelled
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ */
+int hrtimer_cancel(struct hrtimer *timer)
+{
+	/* Note: because we assume a uniprocessor non-interruptible */
+	/* system when running in the kernel, we know that the timer */
+	/* is not running when we execute this code, so, know that */
+	/* try_to_cancel cannot return -1 and we don't need to retry */
+	/* the cancel later to wait for the handler to finish. */
+	int ret = hrtimer_try_to_cancel(timer);
+
+	lib_assert(ret >= 0);
+	return ret;
+}
+int
+hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
+}
+int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			   unsigned long delta_ns, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, delta_ns, mode, 1);
+}
+
+int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+{
+	*tp = ns_to_timespec(1);
+	return 0;
+}
diff --git a/arch/lib/tasklet-hrtimer.c b/arch/lib/tasklet-hrtimer.c
new file mode 100644
index 0000000..fef4902
--- /dev/null
+++ b/arch/lib/tasklet-hrtimer.c
@@ -0,0 +1,57 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
+{
+	struct tasklet_hrtimer *ttimer =
+		container_of(timer, struct tasklet_hrtimer, timer);
+
+	tasklet_schedule(&ttimer->tasklet);
+	return HRTIMER_NORESTART;
+}
+static void __tasklet_hrtimer_trampoline(unsigned long data)
+{
+	struct tasklet_hrtimer *ttimer = (void *)data;
+	enum hrtimer_restart restart;
+
+	restart = ttimer->function(&ttimer->timer);
+	if (restart != HRTIMER_NORESTART)
+		hrtimer_restart(&ttimer->timer);
+}
+/**
+ * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
+ * @ttimer:      tasklet_hrtimer which is initialized
+ * @function:    hrtimer callback function which gets called from softirq context
+ * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
+ * @mode:        hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
+ */
+void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+			  enum hrtimer_restart (*function)(struct hrtimer *),
+			  clockid_t which_clock, enum hrtimer_mode mode)
+{
+	hrtimer_init(&ttimer->timer, which_clock, mode);
+	ttimer->timer.function = __hrtimer_tasklet_trampoline;
+	tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
+		     (unsigned long)ttimer);
+	ttimer->function = function;
+}
+
+void __tasklet_hi_schedule(struct tasklet_struct *t)
+{
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	void *event =
+		lib_event_schedule_ns(0, (void *)&t->func, (void *)t->data);
+	t->next = event;
+}
diff --git a/arch/lib/time.c b/arch/lib/time.c
new file mode 100644
index 0000000..b54be75
--- /dev/null
+++ b/arch/lib/time.c
@@ -0,0 +1,144 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/ktime.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+unsigned long volatile jiffies = INITIAL_JIFFIES;
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+struct timespec xtime;
+seqlock_t xtime_lock;
+/* accessed from wrap_clock from do_sys_settimeofday.
+   We don't call the latter so we should never access this variable. */
+struct timespec wall_to_monotonic;
+
+uint64_t ns_to_jiffies(uint64_t ns)
+{
+	do_div(ns, (1000000000 / HZ));
+	return ns;
+}
+
+void lib_update_jiffies(void)
+{
+	jiffies = ns_to_jiffies(lib_current_ns());
+	jiffies_64 = ns_to_jiffies(lib_current_ns());
+}
+
+struct timespec current_kernel_time(void)
+{
+	u64 ns = lib_current_ns();
+	struct timespec spec = ns_to_timespec(ns);
+
+	return spec;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	u64 ns = lib_current_ns();
+
+	*tv = ns_to_timeval(ns);
+}
+
+int do_adjtimex(struct timex *timex)
+{
+	lib_assert(false);
+	return -EPERM;
+}
+ktime_t ktime_get(void)
+{
+	u64 ns = lib_current_ns();
+
+	return ns_to_ktime(ns);
+}
+ktime_t ktime_get_with_offset(enum tk_offsets offs)
+{
+	/* FIXME */
+	return ktime_get();
+}
+
+/* copied from kernel/time/hrtimeer.c */
+#if BITS_PER_LONG < 64
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+u64 __ktime_divns(const ktime_t kt, s64 div)
+{
+	u64 dclc;
+	int sft = 0;
+
+	dclc = ktime_to_ns(kt);
+	/* Make sure the divisor is less than 2^32: */
+	while (div >> 32) {
+		sft++;
+		div >>= 1;
+	}
+	dclc >>= sft;
+	do_div(dclc, (unsigned long)div);
+
+	return dclc;
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+void update_xtime_cache(u64 nsec)
+{
+}
+unsigned long get_seconds(void)
+{
+	u64 ns = lib_current_ns();
+
+	do_div(ns, 1000000000);
+	return ns;
+}
+static unsigned long
+round_jiffies_common(unsigned long j,
+		     bool force_up)
+{
+	int rem;
+	unsigned long original = j;
+
+	rem = j % HZ;
+	if (rem < HZ / 4 && !force_up)  /* round down */
+		j = j - rem;
+	else                            /* round up */
+		j = j - rem + HZ;
+	if (j <= jiffies)               /* rounding ate our timeout entirely; */
+		return original;
+	return j;
+}
+unsigned long round_jiffies(unsigned long j)
+{
+	return round_jiffies_common(j, false);
+}
+unsigned long round_jiffies_relative(unsigned long j)
+{
+	unsigned long j0 = jiffies;
+
+	/* Use j0 because jiffies might change while we run */
+	return round_jiffies_common(j + j0, false) - j0;
+}
+unsigned long round_jiffies_up(unsigned long j)
+{
+	return round_jiffies_common(j, true);
+}
+static void msleep_trampoline(void *context)
+{
+	struct SimTask *task = context;
+
+	lib_task_wakeup(task);
+}
+void msleep(unsigned int msecs)
+{
+	lib_event_schedule_ns(((__u64)msecs) * 1000000, &msleep_trampoline,
+			      lib_task_current());
+	lib_task_wait();
+}
diff --git a/arch/lib/timer.c b/arch/lib/timer.c
new file mode 100644
index 0000000..87d2283
--- /dev/null
+++ b/arch/lib/timer.c
@@ -0,0 +1,238 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * init_timer_key - initialize a timer
+ * @timer: the timer to be initialized
+ * @name: name of the timer
+ * @key: lockdep class key of the fake lock used for tracking timer
+ *       sync lock dependencies
+ *
+ * init_timer_key() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void init_timer_key(struct timer_list *timer,
+		    unsigned int flags,
+		    const char *name,
+		    struct lock_class_key *key)
+{
+	/**
+	 * Note: name and key are used for debugging. We ignore them
+	 * unconditionally.
+	 * Note: we do not initialize the lockdep map either because we
+	 * don't care.
+	 * and, finally, we never care about the base field either.
+	 *
+	 * So, for now, we have a timer which is marked as "not started"
+	 * thanks to its entry.next field set to NULL (timer_pending
+	 * will return 0)
+	 */
+	timer->entry.next = NULL;
+	timer->base = 0;
+}
+
+struct list_head g_expired_events = LIST_HEAD_INIT(g_expired_events);
+struct list_head g_pending_events = LIST_HEAD_INIT(g_pending_events);
+
+static void run_timer_softirq(struct softirq_action *h)
+{
+	while (!list_empty(&g_expired_events)) {
+		struct timer_list *timer = list_first_entry(&g_expired_events,
+							    struct timer_list,
+							    entry);
+		void (*fn)(unsigned long);
+		unsigned long data;
+
+		fn = timer->function;
+		data = timer->data;
+		lib_assert(timer->base == 0);
+		if (timer->entry.prev != LIST_POISON2) {
+			list_del(&timer->entry);
+			timer->entry.next = NULL;
+			fn(data);
+		}
+	}
+}
+
+static void ensure_softirq_opened(void)
+{
+	static bool opened = false;
+
+	if (opened)
+		return;
+	opened = true;
+	open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
+}
+static void timer_trampoline(void *context)
+{
+	struct timer_list *timer;
+
+	ensure_softirq_opened();
+	timer = context;
+	timer->base = 0;
+	if (timer->entry.prev != LIST_POISON2)
+		list_del(&timer->entry);
+	list_add_tail(&timer->entry, &g_expired_events);
+	raise_softirq(TIMER_SOFTIRQ);
+}
+/**
+ * add_timer - start a timer
+ * @timer: the timer to be added
+ *
+ * The kernel will do a ->function(->data) callback from the
+ * timer interrupt at the ->expires point in the future. The
+ * current time is 'jiffies'.
+ *
+ * The timer's ->expires, ->function (and if the handler uses it, ->data)
+ * fields must be set prior calling this function.
+ *
+ * Timers with an ->expires field in the past will be executed in the next
+ * timer tick.
+ */
+void add_timer(struct timer_list *timer)
+{
+	__u64 delay_ns = 0;
+
+	lib_assert(!timer_pending(timer));
+	if (timer->expires <= jiffies)
+		delay_ns = (1000000000 / HZ); /* next tick. */
+	else
+		delay_ns =
+			((__u64)timer->expires *
+			 (1000000000 / HZ)) - lib_current_ns();
+	void *event = lib_event_schedule_ns(delay_ns, &timer_trampoline, timer);
+	/* store the external event in the base field */
+	/* to be able to retrieve it from del_timer */
+	timer->base = event;
+	/* finally, store timer in list of pending events. */
+	list_add_tail(&timer->entry, &g_pending_events);
+}
+/**
+ * del_timer - deactive a timer.
+ * @timer: the timer to be deactivated
+ *
+ * del_timer() deactivates a timer - this works on both active and inactive
+ * timers.
+ *
+ * The function returns whether it has deactivated a pending timer or not.
+ * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
+ * active timer returns 1.)
+ */
+int del_timer(struct timer_list *timer)
+{
+	int retval;
+
+	if (timer->entry.next == 0)
+		return 0;
+	if (timer->base != 0) {
+		lib_event_cancel(timer->base);
+		retval = 1;
+	} else
+		retval = 0;
+	if (timer->entry.prev != LIST_POISON2) {
+		list_del(&timer->entry);
+		timer->entry.next = NULL;
+	}
+	return retval;
+}
+
+/* ////////////////////// */
+
+void init_timer_deferrable_key(struct timer_list *timer,
+			       const char *name,
+			       struct lock_class_key *key)
+{
+	/**
+	 * From lwn.net:
+	 * Timers which are initialized in this fashion will be
+	 * recognized as deferrable by the kernel. They will not
+	 * be considered when the kernel makes its "when should
+	 * the next timer interrupt be?" decision. When the system
+	 * is busy these timers will fire at the scheduled time. When
+	 * things are idle, instead, they will simply wait until
+	 * something more important wakes up the processor.
+	 *
+	 * Note: Our implementation of deferrable timers uses
+	 * non-deferrable timers for simplicity.
+	 */
+	init_timer_key(timer, 0, name, key);
+}
+/**
+ * add_timer_on - start a timer on a particular CPU
+ * @timer: the timer to be added
+ * @cpu: the CPU to start it on
+ *
+ * This is not very scalable on SMP. Double adds are not possible.
+ */
+void add_timer_on(struct timer_list *timer, int cpu)
+{
+	/* we ignore the cpu: we have only one. */
+	add_timer(timer);
+}
+/**
+ * mod_timer - modify a timer's timeout
+ * @timer: the timer to be modified
+ * @expires: new timeout in jiffies
+ *
+ * mod_timer() is a more efficient way to update the expire field of an
+ * active timer (if the timer is inactive it will be activated)
+ *
+ * mod_timer(timer, expires) is equivalent to:
+ *
+ *     del_timer(timer); timer->expires = expires; add_timer(timer);
+ *
+ * Note that if there are multiple unserialized concurrent users of the
+ * same timer, then mod_timer() is the only safe way to modify the timeout,
+ * since add_timer() cannot modify an already running timer.
+ *
+ * The function returns whether it has modified a pending timer or not.
+ * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
+ * active timer returns 1.)
+ */
+int mod_timer(struct timer_list *timer, unsigned long expires)
+{
+	int ret;
+
+	/* common optimization stolen from kernel */
+	if (timer_pending(timer) && timer->expires == expires)
+		return 1;
+
+	ret = del_timer(timer);
+	timer->expires = expires;
+	add_timer(timer);
+	return ret;
+}
+/**
+ * mod_timer_pending - modify a pending timer's timeout
+ * @timer: the pending timer to be modified
+ * @expires: new timeout in jiffies
+ *
+ * mod_timer_pending() is the same for pending timers as mod_timer(),
+ * but will not re-activate and modify already deleted timers.
+ *
+ * It is useful for unserialized use of timers.
+ */
+int mod_timer_pending(struct timer_list *timer, unsigned long expires)
+{
+	if (timer_pending(timer))
+		return 0;
+	return mod_timer(timer, expires);
+}
+
+int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
+{
+	if (timer->expires == expires && timer_pending(timer))
+		return 1;
+
+	return mod_timer(timer, expires);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 05/10] lib: context and scheduling functions (kernel glue code) for libos
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (3 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 04/10] lib: time handling (kernel glue code) Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 06/10] lib: sysctl handling (kernel glue code) Hajime Tazaki
                       ` (6 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

contexnt primitives of kernel such as soft interupts, scheduling,
tasklet are implemented for libos. these functions eventually call the
functions registered by lib_init() API as well.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/sched.c     | 406 +++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/softirq.c   | 108 ++++++++++++++
 arch/lib/tasklet.c   |  76 ++++++++++
 arch/lib/workqueue.c | 242 ++++++++++++++++++++++++++++++
 4 files changed, 832 insertions(+)
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/workqueue.c

diff --git a/arch/lib/sched.c b/arch/lib/sched.c
new file mode 100644
index 0000000..98a568a
--- /dev/null
+++ b/arch/lib/sched.c
@@ -0,0 +1,406 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+#include <linux/hash.h>
+#include <net/net_namespace.h>
+#include "lib.h"
+#include "sim.h"
+#include "sim-assert.h"
+
+/**
+   called by wait_event macro:
+   - prepare_to_wait
+   - schedule
+   - finish_wait
+ */
+
+struct SimTask *lib_task_create(void *private, unsigned long pid)
+{
+	struct SimTask *task = lib_malloc(sizeof(struct SimTask));
+	struct cred *cred;
+	struct nsproxy *ns;
+	struct user_struct *user;
+	struct thread_info *info;
+	struct pid *kpid;
+
+	if (!task)
+		return NULL;
+	memset(task, 0, sizeof(struct SimTask));
+	cred = lib_malloc(sizeof(struct cred));
+	if (!cred)
+		return NULL;
+	/* XXX: we could optimize away this allocation by sharing it
+	   for all tasks */
+	ns = lib_malloc(sizeof(struct nsproxy));
+	if (!ns)
+		return NULL;
+	user = lib_malloc(sizeof(struct user_struct));
+	if (!user)
+		return NULL;
+	info = alloc_thread_info(&task->kernel_task);
+	if (!info)
+		return NULL;
+	kpid = lib_malloc(sizeof(struct pid));
+	if (!kpid)
+		return NULL;
+	kpid->numbers[0].nr = pid;
+	cred->fsuid = make_kuid(current_user_ns(), 0);
+	cred->fsgid = make_kgid(current_user_ns(), 0);
+	cred->user = user;
+	atomic_set(&cred->usage, 1);
+	info->task = &task->kernel_task;
+	info->preempt_count = 0;
+	info->flags = 0;
+	atomic_set(&ns->count, 1);
+	ns->uts_ns = 0;
+	ns->ipc_ns = 0;
+	ns->mnt_ns = 0;
+	ns->pid_ns_for_children = 0;
+	ns->net_ns = &init_net;
+	task->kernel_task.cred = cred;
+	task->kernel_task.pid = pid;
+	task->kernel_task.pids[PIDTYPE_PID].pid = kpid;
+	task->kernel_task.pids[PIDTYPE_PGID].pid = kpid;
+	task->kernel_task.pids[PIDTYPE_SID].pid = kpid;
+	task->kernel_task.nsproxy = ns;
+	task->kernel_task.stack = info;
+	/* this is a hack. */
+	task->kernel_task.group_leader = &task->kernel_task;
+	task->private = private;
+	return task;
+}
+void lib_task_destroy(struct SimTask *task)
+{
+	lib_free((void *)task->kernel_task.nsproxy);
+	lib_free((void *)task->kernel_task.cred);
+	lib_free((void *)task->kernel_task.cred->user);
+	free_thread_info(task->kernel_task.stack);
+	lib_free(task);
+}
+void *lib_task_get_private(struct SimTask *task)
+{
+	return task->private;
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct SimTask *task = lib_task_start((void (*)(void *))fn, arg);
+
+	return task->kernel_task.pid;
+}
+
+struct task_struct *get_current(void)
+{
+	struct SimTask *lib_task = lib_task_current();
+
+	return &lib_task->kernel_task;
+}
+
+struct thread_info *current_thread_info(void)
+{
+	return task_thread_info(get_current());
+}
+struct thread_info *alloc_thread_info(struct task_struct *task)
+{
+	return lib_malloc(sizeof(struct thread_info));
+}
+void free_thread_info(struct thread_info *ti)
+{
+	lib_free(ti);
+}
+
+
+void __put_task_struct(struct task_struct *t)
+{
+	lib_free(t);
+}
+
+void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+	list_add(&wait->task_list, &q->task_list);
+}
+void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	list_add_tail(&wait->task_list, &q->task_list);
+}
+void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	if (wait->task_list.prev != LIST_POISON2)
+		list_del(&wait->task_list);
+}
+void
+prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	wait->flags |= WQ_FLAG_EXCLUSIVE;
+	if (list_empty(&wait->task_list))
+		list_add_tail(&wait->task_list, &q->task_list);
+	set_current_state(state);
+}
+void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	unsigned long flags;
+
+	wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+	spin_lock_irqsave(&q->lock, flags);
+	if (list_empty(&wait->task_list))
+		__add_wait_queue(q, wait);
+	set_current_state(state);
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
+{
+	set_current_state(TASK_RUNNING);
+	if (!list_empty(&wait->task_list))
+		list_del_init(&wait->task_list);
+}
+int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync,
+			     void *key)
+{
+	int ret = default_wake_function(wait, mode, sync, key);
+
+	if (ret && (wait->task_list.prev != LIST_POISON2))
+		list_del_init(&wait->task_list);
+
+	return ret;
+}
+
+int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	wait->flags |= WQ_FLAG_WOKEN;
+	return default_wake_function(wait, mode, sync, key);
+}
+
+void __init_waitqueue_head(wait_queue_head_t *q, const char *name,
+			   struct lock_class_key *k)
+{
+	INIT_LIST_HEAD(&q->task_list);
+}
+/**
+ * wait_for_completion: - waits for completion of a task
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It is NOT
+ * interruptible and there is no timeout.
+ *
+ * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
+ * and interrupt capability. Also see complete().
+ */
+void wait_for_completion(struct completion *x)
+{
+	wait_for_completion_timeout(x, MAX_SCHEDULE_TIMEOUT);
+}
+unsigned long wait_for_completion_timeout(struct completion *x,
+					  unsigned long timeout)
+{
+	if (!x->done) {
+		DECLARE_WAITQUEUE(wait, current);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		wait.flags |= WQ_FLAG_EXCLUSIVE;
+		list_add_tail(&wait.task_list, &x->wait.task_list);
+		do
+			timeout = schedule_timeout(timeout);
+		while (!x->done && timeout);
+		if (wait.task_list.prev != LIST_POISON2)
+			list_del(&wait.task_list);
+
+		if (!x->done)
+			return timeout;
+	}
+	x->done--;
+	return timeout ? : 1;
+}
+
+/**
+ * __wake_up - wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ * @key: is directly passed to the wakeup function
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void __wake_up(wait_queue_head_t *q, unsigned int mode,
+	       int nr_exclusive, void *key)
+{
+	wait_queue_t *curr, *next;
+
+	list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
+		unsigned flags = curr->flags;
+
+		if (curr->func(curr, mode, 0, key) &&
+		    (flags & WQ_FLAG_EXCLUSIVE) &&
+		    !--nr_exclusive)
+			break;
+	}
+}
+void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
+			int nr_exclusive, void *key)
+{
+	__wake_up(q, mode, nr_exclusive, key);
+}
+int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
+			  void *key)
+{
+	struct task_struct *task = (struct task_struct *)curr->private;
+	struct SimTask *lib_task = container_of(task, struct SimTask,
+						kernel_task);
+
+	return lib_task_wakeup(lib_task);
+}
+__sched int bit_wait(struct wait_bit_key *word)
+{
+	if (signal_pending_state(current->state, current))
+		return 1;
+	schedule();
+	return 0;
+}
+int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *arg)
+{
+	struct wait_bit_key *key = arg;
+	struct wait_bit_queue *wait_bit
+		= container_of(wait, struct wait_bit_queue, wait);
+
+	if (wait_bit->key.flags != key->flags ||
+			wait_bit->key.bit_nr != key->bit_nr ||
+			test_bit(key->bit_nr, key->flags))
+		return 0;
+	else
+		return autoremove_wake_function(wait, mode, sync, key);
+}
+void __wake_up_bit(wait_queue_head_t *wq, void *word, int bit)
+{
+	struct wait_bit_key key = __WAIT_BIT_KEY_INITIALIZER(word, bit);
+	if (waitqueue_active(wq))
+		__wake_up(wq, TASK_NORMAL, 1, &key);
+}
+void wake_up_bit(void *word, int bit)
+{
+	/* FIXME */
+	return;
+	__wake_up_bit(bit_waitqueue(word, bit), word, bit);
+}
+wait_queue_head_t *bit_waitqueue(void *word, int bit)
+{
+	const int shift = BITS_PER_LONG == 32 ? 5 : 6;
+	const struct zone *zone = page_zone(virt_to_page(word));
+	unsigned long val = (unsigned long)word << shift | bit;
+
+	return &zone->wait_table[hash_long(val, zone->wait_table_bits)];
+}
+
+
+void schedule(void)
+{
+	lib_task_wait();
+}
+
+static void trampoline(void *context)
+{
+	struct SimTask *task = context;
+
+	lib_task_wakeup(task);
+}
+
+signed long schedule_timeout(signed long timeout)
+{
+	u64 ns;
+	struct SimTask *self;
+
+	if (timeout == MAX_SCHEDULE_TIMEOUT) {
+		lib_task_wait();
+		return MAX_SCHEDULE_TIMEOUT;
+	}
+	lib_assert(timeout >= 0);
+	ns = ((__u64)timeout) * (1000000000 / HZ);
+	self = lib_task_current();
+	lib_event_schedule_ns(ns, &trampoline, self);
+	lib_task_wait();
+	/* we know that we are always perfectly on time. */
+	return 0;
+}
+
+signed long schedule_timeout_uninterruptible(signed long timeout)
+{
+	return schedule_timeout(timeout);
+}
+signed long schedule_timeout_interruptible(signed long timeout)
+{
+	return schedule_timeout(timeout);
+}
+
+void yield(void)
+{
+	lib_task_yield();
+}
+
+void complete_all(struct completion *x)
+{
+	x->done += UINT_MAX / 2;
+	__wake_up(&x->wait, TASK_NORMAL, 0, 0);
+}
+void complete(struct completion *x)
+{
+	x->done++;
+	__wake_up(&x->wait, TASK_NORMAL, 1, 0);
+}
+
+long wait_for_completion_interruptible_timeout(
+	struct completion *x, unsigned long timeout)
+{
+	return wait_for_completion_timeout(x, timeout);
+}
+int wait_for_completion_interruptible(struct completion *x)
+{
+	wait_for_completion_timeout(x, MAX_SCHEDULE_TIMEOUT);
+	return 0;
+}
+int wake_up_process(struct task_struct *tsk)
+{
+	struct SimTask *lib_task =
+		container_of(tsk, struct SimTask, kernel_task);
+
+	return lib_task_wakeup(lib_task);
+}
+int _cond_resched(void)
+{
+	/* we never schedule to decrease latency. */
+	return 0;
+}
+int idle_cpu(int cpu)
+{
+	/* we are never idle: we call this from rcutiny.c and the answer */
+	/* does not matter, really. */
+	return 0;
+}
+
+unsigned long long __attribute__((weak)) sched_clock(void)
+{
+	return (unsigned long long)(jiffies - INITIAL_JIFFIES)
+	       * (NSEC_PER_SEC / HZ);
+}
+
+u64 local_clock(void)
+{
+	return sched_clock();
+}
+
+void __sched schedule_preempt_disabled(void)
+{
+}
+
+void resched_cpu(int cpu)
+{
+	rcu_sched_qs();
+}
diff --git a/arch/lib/softirq.c b/arch/lib/softirq.c
new file mode 100644
index 0000000..3f6363a
--- /dev/null
+++ b/arch/lib/softirq.c
@@ -0,0 +1,108 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim-init.h"
+#include "sim.h"
+#include "sim-assert.h"
+
+
+static struct softirq_action softirq_vec[NR_SOFTIRQS];
+static struct SimTask *g_softirq_task = 0;
+static int g_n_raises = 0;
+
+void lib_softirq_wakeup(void)
+{
+	g_n_raises++;
+	lib_task_wakeup(g_softirq_task);
+}
+
+static void softirq_task_function(void *context)
+{
+	while (true) {
+		do_softirq();
+		g_n_raises--;
+		if (g_n_raises == 0 || local_softirq_pending() == 0) {
+			g_n_raises = 0;
+			lib_task_wait();
+		}
+	}
+}
+
+static void ensure_task_created(void)
+{
+	if (g_softirq_task != 0)
+		return;
+	g_softirq_task = lib_task_start(&softirq_task_function, 0);
+}
+
+void open_softirq(int nr, void (*action)(struct softirq_action *))
+{
+	ensure_task_created();
+	softirq_vec[nr].action = action;
+}
+#define MAX_SOFTIRQ_RESTART 10
+
+void do_softirq(void)
+{
+	__u32 pending;
+	int max_restart = MAX_SOFTIRQ_RESTART;
+	struct softirq_action *h;
+
+	pending = local_softirq_pending();
+
+restart:
+	/* Reset the pending bitmask before enabling irqs */
+	set_softirq_pending(0);
+
+	local_irq_enable();
+
+	h = softirq_vec;
+
+	do {
+		if (pending & 1)
+			h->action(h);
+		h++;
+		pending >>= 1;
+	} while (pending);
+
+	local_irq_disable();
+
+	pending = local_softirq_pending();
+	if (pending && --max_restart)
+		goto restart;
+}
+void raise_softirq_irqoff(unsigned int nr)
+{
+	__raise_softirq_irqoff(nr);
+
+	lib_softirq_wakeup();
+}
+void __raise_softirq_irqoff(unsigned int nr)
+{
+	/* trace_softirq_raise(nr); */
+	or_softirq_pending(1UL << nr);
+}
+int __cond_resched_softirq(void)
+{
+	/* tell the caller that we did not need to re-schedule. */
+	return 0;
+}
+void raise_softirq(unsigned int nr)
+{
+	/* copy/paste from kernel/softirq.c */
+	unsigned long flags;
+
+	local_irq_save(flags);
+	raise_softirq_irqoff(nr);
+	local_irq_restore(flags);
+}
+
+void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
+{
+}
diff --git a/arch/lib/tasklet.c b/arch/lib/tasklet.c
new file mode 100644
index 0000000..6cc68f4
--- /dev/null
+++ b/arch/lib/tasklet.c
@@ -0,0 +1,76 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+void tasklet_init(struct tasklet_struct *t,
+		  void (*func)(unsigned long), unsigned long data)
+{
+	t->next = NULL;
+	t->state = 0;
+	atomic_set(&t->count, 0);
+	t->func = func;
+	t->data = data;
+}
+
+void tasklet_kill(struct tasklet_struct *t)
+{
+	/* theoretically, called from user context */
+	while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
+		do
+			lib_task_yield();
+		while (test_bit(TASKLET_STATE_SCHED, &t->state));
+	}
+	clear_bit(TASKLET_STATE_SCHED, &t->state);
+}
+struct tasklet_struct *g_sched_events = NULL;
+static void run_tasklet_softirq(struct softirq_action *h)
+{
+	/* while (!list_empty (&g_sched_events)) */
+	/*   { */
+	struct tasklet_struct *tasklet = g_sched_events;
+
+	if (atomic_read(&tasklet->count) == 0) {
+		/* this tasklet is enabled so, we run it. */
+		test_and_clear_bit(TASKLET_STATE_SCHED, &tasklet->state);
+		tasklet->func(tasklet->data);
+	}
+	/* } */
+}
+static void ensure_softirq_opened(void)
+{
+	static bool opened = false;
+
+	if (opened)
+		return;
+	opened = true;
+	open_softirq(TASKLET_SOFTIRQ, run_tasklet_softirq);
+}
+static void trampoline(void *context)
+{
+	ensure_softirq_opened();
+	struct tasklet_struct *tasklet = context;
+	/* allow the tasklet to re-schedule itself */
+	lib_assert(tasklet->next != 0);
+	tasklet->next = 0;
+	g_sched_events = tasklet;
+	raise_softirq(TASKLET_SOFTIRQ);
+}
+void __tasklet_schedule(struct tasklet_struct *t)
+{
+	void *event;
+
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	event = lib_event_schedule_ns(0, &trampoline, t);
+	t->next = event;
+}
diff --git a/arch/lib/workqueue.c b/arch/lib/workqueue.c
new file mode 100644
index 0000000..bd0e9c5
--- /dev/null
+++ b/arch/lib/workqueue.c
@@ -0,0 +1,242 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+/* copy from kernel/workqueue.c */
+typedef unsigned long mayday_mask_t;
+struct workqueue_struct {
+	unsigned int flags;                     /* W: WQ_* flags */
+	union {
+		struct cpu_workqueue_struct __percpu *pcpu;
+		struct cpu_workqueue_struct *single;
+		unsigned long v;
+	} cpu_wq;                               /* I: cwq's */
+	struct list_head list;                  /* W: list of all workqueues */
+
+	struct mutex flush_mutex;               /* protects wq flushing */
+	int work_color;                         /* F: current work color */
+	int flush_color;                        /* F: current flush color */
+	atomic_t nr_cwqs_to_flush;              /* flush in progress */
+	struct wq_flusher *first_flusher;       /* F: first flusher */
+	struct list_head flusher_queue;         /* F: flush waiters */
+	struct list_head flusher_overflow;      /* F: flush overflow list */
+
+	mayday_mask_t mayday_mask;              /* cpus requesting rescue */
+	struct worker *rescuer;                 /* I: rescue worker */
+
+	int nr_drainers;                        /* W: drain in progress */
+	int saved_max_active;                   /* W: saved cwq max_active */
+#ifdef CONFIG_LOCKDEP
+	struct lockdep_map lockdep_map;
+#endif
+	char name[];                            /* I: workqueue name */
+};
+
+struct wq_barrier {
+	struct SimTask *waiter;
+	struct workqueue_struct wq;
+};
+
+static void
+workqueue_function(void *context)
+{
+	struct workqueue_struct *wq = context;
+
+	while (true) {
+		lib_task_wait();
+		while (!list_empty(&wq->list)) {
+			struct work_struct *work =
+				list_first_entry(&wq->list, struct work_struct,
+						entry);
+			work_func_t f = work->func;
+
+			if (work->entry.prev != LIST_POISON2) {
+				list_del_init(&work->entry);
+				clear_bit(WORK_STRUCT_PENDING_BIT,
+					  work_data_bits(work));
+				f(work);
+			}
+		}
+	}
+}
+
+static struct SimTask *workqueue_task(struct workqueue_struct *wq)
+{
+	struct wq_barrier *barr = container_of(wq, struct wq_barrier, wq);
+
+	if (barr->waiter == 0)
+		barr->waiter = lib_task_start(&workqueue_function, wq);
+	return barr->waiter;
+}
+
+static int flush_entry(struct workqueue_struct *wq, struct list_head *prev)
+{
+	int active = 0;
+
+	if (!list_empty(&wq->list)) {
+		active = 1;
+		lib_task_wakeup(workqueue_task(wq));
+		/* XXX: should wait for completion? but this will block
+		   and init won't return.. */
+		/* lib_task_wait (); */
+	}
+
+	return active;
+}
+
+void delayed_work_timer_fn(unsigned long data)
+{
+	struct delayed_work *dwork = (struct delayed_work *)data;
+	struct work_struct *work = &dwork->work;
+
+	list_add_tail(&work->entry, &dwork->wq->list);
+	lib_task_wakeup(workqueue_task(dwork->wq));
+}
+
+bool queue_work_on(int cpu, struct workqueue_struct *wq,
+		   struct work_struct *work)
+{
+	int ret = 0;
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
+		list_add_tail(&work->entry, &wq->list);
+		lib_task_wakeup(workqueue_task(wq));
+		ret = 1;
+	}
+	return ret;
+}
+
+void flush_scheduled_work(void)
+{
+	flush_entry(system_wq, system_wq->list.prev);
+}
+bool flush_work(struct work_struct *work)
+{
+	return flush_entry(system_wq, &work->entry);
+}
+void flush_workqueue(struct workqueue_struct *wq)
+{
+	flush_entry(wq, wq->list.prev);
+}
+bool cancel_work_sync(struct work_struct *work)
+{
+	int retval = 0;
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)))
+		/* work was not yet queued */
+		return 0;
+	if (!list_empty(&work->entry)) {
+		/* work was queued. now unqueued. */
+		if (work->entry.prev != LIST_POISON2) {
+			list_del_init(&work->entry);
+			clear_bit(WORK_STRUCT_PENDING_BIT,
+				  work_data_bits(work));
+			retval = 1;
+		}
+	}
+	return retval;
+}
+bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+			   struct delayed_work *dwork, unsigned long delay)
+{
+	int ret = 0;
+	struct timer_list *timer = &dwork->timer;
+	struct work_struct *work = &dwork->work;
+
+	if (delay == 0)
+		return queue_work(wq, work);
+
+	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
+		lib_assert(!timer_pending(timer));
+		dwork->wq = wq;
+		/* This stores cwq for the moment, for the timer_fn */
+		timer->expires = jiffies + delay;
+		timer->data = (unsigned long)dwork;
+		timer->function = delayed_work_timer_fn;
+		add_timer(timer);
+		ret = 1;
+	}
+	return ret;
+}
+bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq,
+			 struct delayed_work *dwork, unsigned long delay)
+{
+	del_timer(&dwork->timer);
+	__clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&dwork->work));
+	return queue_delayed_work(wq, dwork, delay);
+}
+bool cancel_delayed_work(struct delayed_work *dwork)
+{
+	del_timer(&dwork->timer);
+	return cancel_work_sync(&dwork->work);
+}
+
+struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
+					       unsigned int flags,
+					       int max_active,
+					       struct lock_class_key *key,
+					       const char *lock_name, ...)
+{
+	va_list args, args1;
+	struct wq_barrier *barr;
+	struct workqueue_struct *wq;
+	size_t namelen;
+
+	/* determine namelen, allocate wq and format name */
+	va_start(args, lock_name);
+	va_copy(args1, args);
+	namelen = vsnprintf(NULL, 0, fmt, args) + 1;
+
+	barr = kzalloc(sizeof(*barr) + namelen, GFP_KERNEL);
+	if (!barr)
+		goto err;
+	barr->waiter = 0;
+	wq = &barr->wq;
+
+	vsnprintf(wq->name, namelen, fmt, args1);
+	va_end(args);
+	va_end(args1);
+
+	max_active = max_active ? : WQ_DFL_ACTIVE;
+	/* init wq */
+	wq->flags = flags;
+	wq->saved_max_active = max_active;
+	mutex_init(&wq->flush_mutex);
+	atomic_set(&wq->nr_cwqs_to_flush, 0);
+	INIT_LIST_HEAD(&wq->flusher_queue);
+	INIT_LIST_HEAD(&wq->flusher_overflow);
+
+	lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
+	INIT_LIST_HEAD(&wq->list);
+
+	/* start waiter task */
+	workqueue_task(wq);
+	return wq;
+err:
+	if (barr)
+		kfree(barr);
+	return NULL;
+}
+
+struct workqueue_struct *system_wq __read_mostly;
+struct workqueue_struct *system_power_efficient_wq __read_mostly;
+/* from linux/workqueue.h */
+#define system_nrt_wq                   __system_nrt_wq()
+
+static int __init init_workqueues(void)
+{
+	system_wq = alloc_workqueue("events", 0, 0);
+	system_power_efficient_wq = alloc_workqueue("events_power_efficient",
+						    WQ_POWER_EFFICIENT, 0);
+	return 0;
+}
+early_initcall(init_workqueues);
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 06/10] lib: sysctl handling (kernel glue code)
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (4 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 07/10] lib: other kernel glue layer code Hajime Tazaki
                       ` (5 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

This interacts with fs/proc_fs.c for sysctl-like interface registed via
lib_init() API.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/sysctl.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 270 insertions(+)
 create mode 100644 arch/lib/sysctl.c

diff --git a/arch/lib/sysctl.c b/arch/lib/sysctl.c
new file mode 100644
index 0000000..5f08f9f
--- /dev/null
+++ b/arch/lib/sysctl.c
@@ -0,0 +1,270 @@
+/*
+ * sysctl wrapper for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/mman.h>
+#include <linux/ratelimit.h>
+#include <linux/proc_fs.h>
+#include "sim-assert.h"
+#include "sim-types.h"
+
+int drop_caches_sysctl_handler(struct ctl_table *table, int write,
+			       void *buffer, size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *table, int write,
+					void *buffer, size_t *length,
+					loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int min_free_kbytes_sysctl_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *table, int write,
+					    void *buffer, size_t *length,
+					    loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_background_ratio_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *lenp,
+				   loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_background_bytes_handler(struct ctl_table *table, int write,
+				   void *buffer, size_t *lenp,
+				   loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_ratio_handler(struct ctl_table *table, int write,
+			void *buffer, size_t *lenp,
+			loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_bytes_handler(struct ctl_table *table, int write,
+			void *buffer, size_t *lenp,
+			loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int dirty_writeback_centisecs_handler(struct ctl_table *table, int write,
+				      void *buffer, size_t *length,
+				      loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int scan_unevictable_handler(struct ctl_table *table, int write,
+			     void __user *buffer,
+			     size_t *length, loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+int sched_rt_handler(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos)
+{
+	lib_assert(false);
+	return 0;
+}
+
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS;
+int sysctl_overcommit_ratio = 50;
+int sysctl_panic_on_oom = 0;
+int sysctl_oom_dump_tasks = 0;
+int sysctl_oom_kill_allocating_task = 0;
+int sysctl_nr_trim_pages = 0;
+int sysctl_drop_caches = 0;
+int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES - 1] = { 32 };
+unsigned int sysctl_sched_child_runs_first = 0;
+unsigned int sysctl_sched_compat_yield = 0;
+unsigned int sysctl_sched_rt_period = 1000000;
+int sysctl_sched_rt_runtime = 950000;
+
+int vm_highmem_is_dirtyable;
+unsigned long vm_dirty_bytes = 0;
+int vm_dirty_ratio = 20;
+int dirty_background_ratio = 10;
+unsigned int dirty_expire_interval = 30 * 100;
+unsigned int dirty_writeback_interval = 5 * 100;
+unsigned long dirty_background_bytes = 0;
+int percpu_pagelist_fraction = 0;
+int panic_timeout = 0;
+int panic_on_oops = 0;
+int printk_delay_msec = 0;
+int panic_on_warn = 0;
+DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
+
+#define RESERVED_PIDS 300
+int pid_max = PID_MAX_DEFAULT;
+int pid_max_min = RESERVED_PIDS + 1;
+int pid_max_max = PID_MAX_LIMIT;
+int min_free_kbytes = 1024;
+int max_threads = 100;
+int laptop_mode = 0;
+
+#define DEFAULT_MESSAGE_LOGLEVEL 4
+#define MINIMUM_CONSOLE_LOGLEVEL 1
+#define DEFAULT_CONSOLE_LOGLEVEL 7
+int console_printk[4] = {
+	DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
+	DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
+	MINIMUM_CONSOLE_LOGLEVEL,       /* minimum_console_loglevel */
+	DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
+};
+
+int print_fatal_signals = 0;
+unsigned int core_pipe_limit = 0;
+int core_uses_pid = 0;
+int vm_swappiness = 60;
+int nr_pdflush_threads = 0;
+unsigned long scan_unevictable_pages = 0;
+int suid_dumpable = 0;
+int page_cluster = 0;
+int block_dump = 0;
+int C_A_D = 0;
+#include <linux/nsproxy.h>
+struct nsproxy init_nsproxy;
+#include <linux/reboot.h>
+char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
+unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
+unsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */
+
+int pdflush_proc_obsolete(struct ctl_table *table, int write,
+			  void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return nr_pdflush_threads;
+}
+#include <linux/fs.h>
+
+/**
+ * Honestly, I don't understand half of that code.
+ * It was modeled after fs/proc/proc_sysctl.c proc_sys_readdir
+ *
+ * Me either ;) (Hajime, Jan 2013)
+ */
+
+/* from proc_sysctl.c (XXX) */
+extern struct ctl_table_root sysctl_table_root;
+void ctl_table_first_entry(struct ctl_dir *dir,
+		 struct ctl_table_header **phead, struct ctl_table **pentry);
+void ctl_table_next_entry(struct ctl_table_header **phead, struct ctl_table **pentry);
+struct ctl_table *ctl_table_find_entry(struct ctl_table_header **phead,
+			     struct ctl_dir *dir, const char *name,
+			     int namelen);
+struct ctl_dir *ctl_table_xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir);
+/* for init_net (XXX, should be fixed) */
+#include <net/net_namespace.h>
+
+static void iterate_table_recursive(const struct SimSysIterator *iter,
+				    struct ctl_table_header *head)
+{
+	struct ctl_table *entry;
+
+	for (entry = head->ctl_table; entry->procname; entry++) {
+		bool may_read = (head->ctl_table->mode & MAY_READ);
+		bool may_write = (head->ctl_table->mode & MAY_WRITE);
+		int flags = 0;
+
+		flags |= may_read ? SIM_SYS_FILE_READ : 0;
+		flags |= may_write ? SIM_SYS_FILE_WRITE : 0;
+		iter->report_file(iter, entry->procname, flags,
+				  (struct SimSysFile *)entry);
+	}
+}
+
+
+static void iterate_recursive(const struct SimSysIterator *iter,
+			      struct ctl_table_header *head)
+{
+	struct ctl_table_header *h = NULL;
+	struct ctl_table *entry;
+	struct ctl_dir *ctl_dir;
+
+	ctl_dir = container_of(head, struct ctl_dir, header);
+	for (ctl_table_first_entry(ctl_dir, &h, &entry); h;
+	     ctl_table_next_entry(&h, &entry)) {
+		struct ctl_dir *dir;
+		int ret;
+		const char *procname;
+
+		/* copy from sysctl_follow_link () */
+		if (S_ISLNK(entry->mode)) {
+			dir = ctl_table_xlate_dir(&init_net.sysctls, h->parent);
+			if (IS_ERR(dir)) {
+				ret = PTR_ERR(dir);
+				lib_assert(false);
+			} else {
+				procname = entry->procname;
+				h = NULL;
+				entry =
+					ctl_table_find_entry(&h, dir, procname,
+							     strlen(procname));
+				ret = -ENOENT;
+			}
+		}
+
+		if (S_ISDIR(entry->mode)) {
+			iter->report_start_dir(iter, entry->procname);
+			iterate_recursive(iter, h);
+			iter->report_end_dir(iter);
+		} else
+			iterate_table_recursive(iter, h);
+	}
+
+}
+
+
+void lib_sys_iterate_files(const struct SimSysIterator *iter)
+{
+	struct ctl_table_header *root =
+		&sysctl_table_root.default_set.dir.header;
+
+	iterate_recursive(iter, root);
+}
+
+int lib_sys_file_read(const struct SimSysFile *file, char *buffer, int size,
+		      int offset)
+{
+	struct ctl_table *table = (struct ctl_table *)file;
+	loff_t ppos = offset;
+	size_t result = size;
+	int error;
+
+	error = table->proc_handler(table, 0, buffer, &result, &ppos);
+	return result;
+}
+int lib_sys_file_write(const struct SimSysFile *file, const char *buffer,
+		       int size, int offset)
+{
+	struct ctl_table *table = (struct ctl_table *)file;
+	loff_t ppos = offset;
+	size_t result = size;
+	int error;
+
+	error = table->proc_handler(table, 1, (char *)buffer, &result, &ppos);
+	return result;
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 07/10] lib: other kernel glue layer code
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (5 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 06/10] lib: sysctl handling (kernel glue code) Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 08/10] lib: auxially files for auto-generated asm-generic files of libos Hajime Tazaki
                       ` (4 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

These files are used to provide the same function calls so that other
network stack code keeps untouched.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Christoph Paasch <christoph.paasch@gmail.com>
---
 arch/lib/capability.c |  47 +++++++++
 arch/lib/filemap.c    |  32 ++++++
 arch/lib/fs.c         |  70 +++++++++++++
 arch/lib/glue.c       | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/modules.c    |  36 +++++++
 arch/lib/pid.c        |  29 ++++++
 arch/lib/print.c      |  56 ++++++++++
 arch/lib/proc.c       |  34 ++++++
 arch/lib/random.c     |  53 ++++++++++
 arch/lib/sysfs.c      |  83 +++++++++++++++
 arch/lib/vmscan.c     |  26 +++++
 11 files changed, 749 insertions(+)
 create mode 100644 arch/lib/capability.c
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/vmscan.c

diff --git a/arch/lib/capability.c b/arch/lib/capability.c
new file mode 100644
index 0000000..7054fea
--- /dev/null
+++ b/arch/lib/capability.c
@@ -0,0 +1,47 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "linux/capability.h"
+
+struct sock;
+struct sk_buff;
+
+int file_caps_enabled = 0;
+
+bool capable(int cap)
+{
+	switch (cap) {
+	case CAP_NET_RAW:
+	case CAP_NET_BIND_SERVICE:
+	case CAP_NET_ADMIN:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int cap_netlink_recv(struct sk_buff *skb, int cap)
+{
+	return 0;
+}
+
+int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	return 0;
+}
+bool ns_capable(struct user_namespace *ns, int cap)
+{
+	return true;
+}
+bool file_ns_capable(const struct file *file, struct user_namespace *ns,
+		     int cap)
+{
+	return true;
+}
diff --git a/arch/lib/filemap.c b/arch/lib/filemap.c
new file mode 100644
index 0000000..ce424ff
--- /dev/null
+++ b/arch/lib/filemap.c
@@ -0,0 +1,32 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/fs.h>
+
+
+ssize_t generic_file_aio_read(struct kiocb *a, const struct iovec *b,
+			      unsigned long c, loff_t d)
+{
+	lib_assert(false);
+
+	return 0;
+}
+
+int generic_file_readonly_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return -ENOSYS;
+}
+
+ssize_t
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+	return 0;
+}
diff --git a/arch/lib/fs.c b/arch/lib/fs.c
new file mode 100644
index 0000000..324e10b
--- /dev/null
+++ b/arch/lib/fs.c
@@ -0,0 +1,70 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <fs/mount.h>
+
+#include "sim-assert.h"
+
+__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
+unsigned int dirtytime_expire_interval;
+
+void __init mnt_init(void)
+{
+}
+
+/* Implementation taken from vfs_kern_mount from linux/namespace.c */
+struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
+{
+	static struct mount local_mnt;
+	static int count = 0;
+	struct mount *mnt = &local_mnt;
+	struct dentry *root = 0;
+
+	/* XXX */
+	if (count != 0) return &local_mnt.mnt;
+	count++;
+
+	memset(mnt, 0, sizeof(struct mount));
+	if (!type)
+		return ERR_PTR(-ENODEV);
+	int flags = MS_KERNMOUNT;
+	char *name = (char *)type->name;
+
+	if (flags & MS_KERNMOUNT)
+		mnt->mnt.mnt_flags = MNT_INTERNAL;
+
+	root = type->mount(type, flags, name, data);
+	if (IS_ERR(root))
+		return ERR_CAST(root);
+
+	mnt->mnt.mnt_root = root;
+	mnt->mnt.mnt_sb = root->d_sb;
+	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+	mnt->mnt_parent = mnt;
+	/* DCE is monothreaded , so we do not care of lock here */
+	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
+
+	return &mnt->mnt;
+}
+void inode_wait_for_writeback(struct inode *inode)
+{
+}
+void truncate_inode_pages_final(struct address_space *mapping)
+{
+}
+int dirtytime_interval_handler(struct ctl_table *table, int write,
+			       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return -ENOSYS;
+}
+
+unsigned int nr_free_buffer_pages(void)
+{
+	return 1024;
+}
diff --git a/arch/lib/glue.c b/arch/lib/glue.c
new file mode 100644
index 0000000..928040d
--- /dev/null
+++ b/arch/lib/glue.c
@@ -0,0 +1,283 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include <linux/types.h>        /* loff_t */
+#include <linux/errno.h>        /* ESPIPE */
+#include <linux/pagemap.h>      /* PAGE_CACHE_SIZE */
+#include <linux/limits.h>       /* NAME_MAX */
+#include <linux/statfs.h>       /* struct kstatfs */
+#include <linux/bootmem.h>      /* HASHDIST_DEFAULT */
+#include <linux/utsname.h>
+#include <linux/binfmts.h>
+#include <linux/init_task.h>
+#include <linux/sched/rt.h>
+#include <linux/backing-dev.h>
+#include <stdarg.h>
+#include "sim-assert.h"
+#include "sim.h"
+#include "lib.h"
+
+
+struct pipe_buffer;
+struct file;
+struct pipe_inode_info;
+struct wait_queue_t;
+struct kernel_param;
+struct super_block;
+struct tvec_base {};
+
+/* defined in sched.c, used in net/sched/em_meta.c */
+unsigned long avenrun[3];
+/* defined in mm/page_alloc.c, used in net/xfrm/xfrm_hash.c */
+int hashdist = HASHDIST_DEFAULT;
+/* defined in mm/page_alloc.c */
+struct pglist_data __refdata contig_page_data;
+/* defined in linux/mmzone.h mm/memory.c */
+struct page *mem_map = 0;
+/* used during boot. */
+struct tvec_base boot_tvec_bases;
+/* used by sysinfo in kernel/timer.c */
+int nr_threads = 0;
+/* not very useful in mm/vmstat.c */
+atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+
+/* XXX: used in network stack ! */
+unsigned long num_physpages = 0;
+unsigned long totalram_pages = 0;
+
+/* XXX figure out initial value */
+unsigned int interrupt_pending = 0;
+static unsigned long g_irqflags = 0;
+static unsigned long local_irqflags = 0;
+int overflowgid = 0;
+int overflowuid = 0;
+int fs_overflowgid = 0;
+int fs_overflowuid = 0;
+unsigned long sysctl_overcommit_kbytes __read_mostly;
+DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly;
+const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
+
+struct backing_dev_info noop_backing_dev_info = {
+	.name		= "noop",
+	.capabilities	= 0,
+};
+
+/* from rt.c */
+int sched_rr_timeslice = RR_TIMESLICE;
+/* from main.c */
+bool initcall_debug;
+bool static_key_initialized __read_mostly = false;
+unsigned long __start_rodata, __end_rodata;
+
+unsigned long arch_local_save_flags(void)
+{
+	return local_irqflags;
+}
+void arch_local_irq_restore(unsigned long flags)
+{
+	local_irqflags = flags;
+}
+
+
+unsigned long long nr_context_switches(void)
+{
+	/* we just need to return >0 to avoid the warning
+	   in kernel/rcupdate.c */
+	return 1;
+}
+
+
+long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+		    unsigned long start, unsigned long nr_pages,
+		    int write, int force, struct page **pages,
+		    struct vm_area_struct **vmas)
+{
+	/* in practice, this function is never called. It's linked in because */
+	/* we link in get_user_pages_fast which is included only because it */
+	/* is located in mm/util.c */
+	lib_assert(false);
+	return 0;
+}
+
+
+void dump_stack(void)
+{
+	/* we assert to make sure that we catch whoever calls dump_stack */
+	lib_assert(false);
+}
+
+
+void lib_printf(const char *str, ...)
+{
+	va_list args;
+
+	va_start(args, str);
+	lib_vprintf(str, args);
+	va_end(args);
+}
+
+#include <linux/vmalloc.h>
+#include <linux/kmemleak.h>
+
+static unsigned long __meminitdata nr_kernel_pages = 8192;
+static unsigned long __meminitdata nr_all_pages = 81920;
+/*
+ * allocate a large system hash table from bootmem
+ * - it is assumed that the hash table must contain an exact power-of-2
+ *   quantity of entries
+ * - limit is the number of hash buckets, not the total allocation size
+ */
+void *__init alloc_large_system_hash(const char *tablename,
+				     unsigned long bucketsize,
+				     unsigned long numentries,
+				     int scale,
+				     int flags,
+				     unsigned int *_hash_shift,
+				     unsigned int *_hash_mask,
+				     unsigned long low_limit,
+				     unsigned long high_limit)
+{
+	unsigned long long max = high_limit;
+	unsigned long log2qty, size;
+	void *table = NULL;
+
+	/* allow the kernel cmdline to have a say */
+	if (!numentries) {
+		/* round applicable memory size up to nearest megabyte */
+		numentries = nr_kernel_pages;
+		numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
+		numentries >>= 20 - PAGE_SHIFT;
+		numentries <<= 20 - PAGE_SHIFT;
+
+		/* limit to 1 bucket per 2^scale bytes of low memory */
+		if (scale > PAGE_SHIFT)
+			numentries >>= (scale - PAGE_SHIFT);
+		else
+			numentries <<= (PAGE_SHIFT - scale);
+
+		/* Make sure we've got at least a 0-order allocation.. */
+		if (unlikely(flags & HASH_SMALL)) {
+			/* Makes no sense without HASH_EARLY */
+			WARN_ON(!(flags & HASH_EARLY));
+			if (!(numentries >> *_hash_shift)) {
+				numentries = 1UL << *_hash_shift;
+				BUG_ON(!numentries);
+			}
+		} else if (unlikely((numentries * bucketsize) < PAGE_SIZE))
+			numentries = PAGE_SIZE / bucketsize;
+	}
+	numentries = roundup_pow_of_two(numentries);
+
+	/* limit allocation size to 1/16 total memory by default */
+	if (max == 0) {
+		max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
+		do_div(max, bucketsize);
+	}
+
+	if (numentries > max)
+		numentries = max;
+
+	log2qty = ilog2(numentries);
+
+	do {
+		size = bucketsize << log2qty;
+		if (flags & HASH_EARLY)
+			table = alloc_bootmem_nopanic(size);
+		else if (hashdist)
+			table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
+		else {
+			/*
+			 * If bucketsize is not a power-of-two, we may free
+			 * some pages at the end of hash table which
+			 * alloc_pages_exact() automatically does
+			 */
+			if (get_order(size) < MAX_ORDER) {
+				table = alloc_pages_exact(size, GFP_ATOMIC);
+				kmemleak_alloc(table, size, 1, GFP_ATOMIC);
+			}
+		}
+	} while (!table && size > PAGE_SIZE && --log2qty);
+
+	if (!table)
+		panic("Failed to allocate %s hash table\n", tablename);
+
+	pr_info("%s hash table entries: %d (order: %d, %lu bytes)\n",
+	       tablename,
+	       (1U << log2qty),
+	       ilog2(size) - PAGE_SHIFT,
+	       size);
+
+	if (_hash_shift)
+		*_hash_shift = log2qty;
+	if (_hash_mask)
+		*_hash_mask = (1 << log2qty) - 1;
+
+	return table;
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+	/* This function is called from the ip layer to get information about
+	   the amount of memory in the system and make some educated guesses
+	   about some default buffer sizes. We pick a value which ensures
+	   small buffers. */
+	val->totalram = 0;
+}
+int slab_is_available(void)
+{
+	/* called from kernel/param.c. */
+	return 1;
+}
+
+/* used from kern_ptr_validate from mm/util.c which is never called */
+void *high_memory = 0;
+
+
+
+void async_synchronize_full(void)
+{
+	/* called from drivers/base/ *.c */
+	/* there is nothing to do, really. */
+}
+
+int send_sig(int signal, struct task_struct *task, int x)
+{
+	struct SimTask *lib_task = container_of(task, struct SimTask,
+						kernel_task);
+
+	lib_signal_raised((struct SimTask *)lib_task, signal);
+	/* lib_assert (false); */
+	return 0;
+}
+unsigned long get_taint(void)
+{
+	/* never tainted. */
+	return 0;
+}
+void add_taint(unsigned flag, enum lockdep_ok lockdep_ok)
+{
+}
+struct pid *cad_pid = 0;
+
+void add_device_randomness(const void *buf, unsigned int size)
+{
+}
+
+int sched_rr_handler(struct ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos)
+{
+	return 0;
+}
+
+void on_each_cpu_mask(const struct cpumask *mask,
+		      smp_call_func_t func, void *info, bool wait)
+{
+}
diff --git a/arch/lib/modules.c b/arch/lib/modules.c
new file mode 100644
index 0000000..ca43fdc
--- /dev/null
+++ b/arch/lib/modules.c
@@ -0,0 +1,36 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-assert.h"
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+
+int modules_disabled = 0;
+char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
+
+static struct module_version_attribute g_empty_attr_buffer;
+/* we make the array empty by default because, really, we don't need */
+/* to look at the builtin params */
+const struct kernel_param __start___param[] = {{0}} ;
+const struct kernel_param __stop___param[] = {{0}} ;
+const struct module_version_attribute *__start___modver[] = {
+	&g_empty_attr_buffer};
+const struct module_version_attribute *__stop___modver[] = {
+	&g_empty_attr_buffer};
+
+struct module_attribute module_uevent;
+struct ctl_table usermodehelper_table[] = {};
+
+int __request_module(bool wait, const char *fmt, ...)
+{
+	/* we really should never be trying to load modules that way. */
+	/*  lib_assert (false); */
+	return 0;
+}
diff --git a/arch/lib/pid.c b/arch/lib/pid.c
new file mode 100644
index 0000000..00cf7b6
--- /dev/null
+++ b/arch/lib/pid.c
@@ -0,0 +1,29 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/pid.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+void put_pid(struct pid *pid)
+{
+}
+pid_t pid_vnr(struct pid *pid)
+{
+	return pid_nr(pid);
+}
+struct task_struct *find_task_by_vpid(pid_t nr)
+{
+	lib_assert(false);
+	return 0;
+}
+struct pid *find_get_pid(int nr)
+{
+	lib_assert(false);
+	return 0;
+}
diff --git a/arch/lib/print.c b/arch/lib/print.c
new file mode 100644
index 0000000..09b1bb5
--- /dev/null
+++ b/arch/lib/print.c
@@ -0,0 +1,56 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <stdarg.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+int dmesg_restrict = 1;
+
+/* from lib/vsprintf.c */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
+int printk(const char *fmt, ...)
+{
+	va_list args;
+	static char buf[256];
+	int value;
+
+	va_start(args, fmt);
+	value = vsnprintf(buf, 256, printk_skip_level(fmt), args);
+	lib_printf("<%c>%s", printk_get_level(fmt), buf);
+	va_end(args);
+	return value;
+}
+void panic(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	lib_vprintf(fmt, args);
+	va_end(args);
+	lib_assert(false);
+}
+
+void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
+{
+	va_list args;
+
+	printk("%s:%d -- ", file, line);
+	va_start(args, fmt);
+	lib_vprintf(fmt, args);
+	va_end(args);
+}
+
+void warn_slowpath_null(const char *file, int line)
+{
+	printk("%s:%d -- ", file, line);
+}
+
diff --git a/arch/lib/proc.c b/arch/lib/proc.c
new file mode 100644
index 0000000..5507730
--- /dev/null
+++ b/arch/lib/proc.c
@@ -0,0 +1,34 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2014 Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/fs.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <net/net_namespace.h>
+#include "sim-types.h"
+#include "sim-assert.h"
+#include "fs/proc/internal.h"           /* XXX */
+
+struct proc_dir_entry;
+static char proc_root_data[sizeof(struct proc_dir_entry) + 4];
+
+static struct proc_dir_entry *proc_root_sim  =
+	(struct proc_dir_entry *)proc_root_data;
+
+void lib_proc_net_initialize(void)
+{
+	proc_root_sim->parent = proc_root_sim;
+	strcpy(proc_root_sim->name, "net");
+	proc_root_sim->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+	proc_root_sim->subdir = RB_ROOT;
+	init_net.proc_net = proc_root_sim;
+	init_net.proc_net_stat = proc_mkdir("stat", proc_root_sim);
+}
+
diff --git a/arch/lib/random.c b/arch/lib/random.c
new file mode 100644
index 0000000..9fbb8bf
--- /dev/null
+++ b/arch/lib/random.c
@@ -0,0 +1,53 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include <linux/random.h>
+
+u32 random32(void)
+{
+	return lib_random();
+}
+
+void get_random_bytes(void *buf, int nbytes)
+{
+	char *p = (char *)buf;
+	int i;
+
+	for (i = 0; i < nbytes; i++)
+		p[i] = lib_random();
+}
+void srandom32(u32 entropy)
+{
+}
+
+u32 prandom_u32(void)
+{
+	return lib_random();
+}
+void prandom_seed(u32 entropy)
+{
+}
+
+void prandom_bytes(void *buf, size_t bytes)
+{
+	return get_random_bytes(buf, bytes);
+}
+
+#include <linux/sysctl.h>
+
+static int nothing;
+struct ctl_table random_table[] = {
+	{
+		.procname       = "nothing",
+		.data           = &nothing,
+		.maxlen         = sizeof(int),
+		.mode           = 0444,
+		.proc_handler   = proc_dointvec,
+	}
+};
diff --git a/arch/lib/sysfs.c b/arch/lib/sysfs.c
new file mode 100644
index 0000000..2def2ca
--- /dev/null
+++ b/arch/lib/sysfs.c
@@ -0,0 +1,83 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+int sysfs_create_bin_file(struct kobject *kobj,
+			  const struct bin_attribute *attr)
+{
+	return 0;
+}
+void sysfs_remove_bin_file(struct kobject *kobj,
+			   const struct bin_attribute *attr)
+{
+}
+int sysfs_create_dir(struct kobject *kobj)
+{
+	return 0;
+}
+int sysfs_create_link(struct kobject *kobj, struct kobject *target,
+		      const char *name)
+{
+	return 0;
+}
+int sysfs_move_dir(struct kobject *kobj,
+		   struct kobject *new_parent_kobj)
+{
+	return 0;
+}
+void sysfs_remove_dir(struct kobject *kobj)
+{
+}
+void sysfs_remove_group(struct kobject *kobj,
+			const struct attribute_group *grp)
+{
+}
+int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+{
+	return 0;
+}
+int __must_check sysfs_create_group(struct kobject *kobj,
+				    const struct attribute_group *grp)
+{
+	return 0;
+}
+int sysfs_create_groups(struct kobject *kobj,
+			const struct attribute_group **groups)
+{
+	return 0;
+}
+int sysfs_schedule_callback(struct kobject *kobj,
+			    void (*func)(
+				    void *), void *data, struct module *owner)
+{
+	return 0;
+}
+void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
+		       const char *name)
+{
+}
+void sysfs_exit_ns(enum kobj_ns_type type, const void *tag)
+{
+}
+void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
+{
+}
+int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
+{
+	kobj->sd = lib_malloc(sizeof(struct kernfs_node));
+	return 0;
+}
+int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
+			 const void *ns)
+{
+	return 0;
+}
diff --git a/arch/lib/vmscan.c b/arch/lib/vmscan.c
new file mode 100644
index 0000000..3132f66
--- /dev/null
+++ b/arch/lib/vmscan.c
@@ -0,0 +1,26 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/mm.h>
+#include <linux/shrinker.h>
+
+/*
+ * Add a shrinker callback to be called from the vm
+ */
+int register_shrinker(struct shrinker *shrinker)
+{
+	return 0;
+}
+
+/*
+ * Remove one
+ */
+void unregister_shrinker(struct shrinker *shrinker)
+{
+}
+
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 08/10] lib: auxially files for auto-generated asm-generic files of libos
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (6 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 07/10] lib: other kernel glue layer code Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-19 13:28     ` [RFC PATCH v3 09/10] lib: libos build scripts and documentation Hajime Tazaki
                       ` (3 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

these files works as stubs in order to transparently run the other
kernel part (e.g., net/) on libos environment.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/include/asm/Kbuild           | 57 +++++++++++++++++++++++++++++++++++
 arch/lib/include/asm/atomic.h         | 50 ++++++++++++++++++++++++++++++
 arch/lib/include/asm/barrier.h        |  8 +++++
 arch/lib/include/asm/bitsperlong.h    | 12 ++++++++
 arch/lib/include/asm/current.h        |  7 +++++
 arch/lib/include/asm/elf.h            | 10 ++++++
 arch/lib/include/asm/hardirq.h        |  8 +++++
 arch/lib/include/asm/page.h           | 14 +++++++++
 arch/lib/include/asm/pgtable.h        | 30 ++++++++++++++++++
 arch/lib/include/asm/processor.h      | 19 ++++++++++++
 arch/lib/include/asm/ptrace.h         |  4 +++
 arch/lib/include/asm/segment.h        |  6 ++++
 arch/lib/include/asm/sembuf.h         |  4 +++
 arch/lib/include/asm/shmbuf.h         |  4 +++
 arch/lib/include/asm/shmparam.h       |  4 +++
 arch/lib/include/asm/sigcontext.h     |  6 ++++
 arch/lib/include/asm/stat.h           |  4 +++
 arch/lib/include/asm/statfs.h         |  4 +++
 arch/lib/include/asm/swab.h           |  7 +++++
 arch/lib/include/asm/thread_info.h    | 36 ++++++++++++++++++++++
 arch/lib/include/asm/uaccess.h        | 14 +++++++++
 arch/lib/include/asm/unistd.h         |  4 +++
 arch/lib/include/uapi/asm/byteorder.h |  6 ++++
 23 files changed, 318 insertions(+)
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h

diff --git a/arch/lib/include/asm/Kbuild b/arch/lib/include/asm/Kbuild
new file mode 100644
index 0000000..c647b1c
--- /dev/null
+++ b/arch/lib/include/asm/Kbuild
@@ -0,0 +1,57 @@
+generic-y += auxvec.h
+generic-y += bitops.h
+generic-y += bug.h
+generic-y += cache.h
+generic-y += cacheflush.h
+generic-y += checksum.h
+generic-y += cputime.h
+generic-y += cmpxchg.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += exec.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += io.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq.h
+generic-y += irqflags.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += linkage.h
+generic-y += local.h
+generic-y += mcs_spinlock.h
+generic-y += mman.h
+generic-y += mmu.h
+generic-y += mmu_context.h
+generic-y += module.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += preempt.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += setup.h
+generic-y += signal.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += string.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += timex.h
+generic-y += tlbflush.h
+generic-y += types.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += unaligned.h
diff --git a/arch/lib/include/asm/atomic.h b/arch/lib/include/asm/atomic.h
new file mode 100644
index 0000000..41a49285
--- /dev/null
+++ b/arch/lib/include/asm/atomic.h
@@ -0,0 +1,50 @@
+#ifndef _ASM_SIM_ATOMIC_H
+#define _ASM_SIM_ATOMIC_H
+
+#include <linux/types.h>
+
+#if !defined(CONFIG_64BIT)
+typedef struct {
+	volatile long long counter;
+} atomic64_t;
+#endif
+
+#define ATOMIC64_INIT(i) { (i) }
+
+#define atomic64_read(v)        (*(volatile long *)&(v)->counter)
+void atomic64_add(long i, atomic64_t *v);
+static inline void atomic64_sub(long i, atomic64_t *v)
+{
+	v->counter -= i;
+}
+static inline void atomic64_inc(atomic64_t *v)
+{
+	v->counter++;
+}
+int atomic64_sub_and_test(long i, atomic64_t *v);
+#define atomic64_dec(v)			atomic64_sub(1LL, (v))
+int atomic64_dec_and_test(atomic64_t *v);
+int atomic64_inc_and_test(atomic64_t *v);
+int atomic64_add_negative(long i, atomic64_t *v);
+/* long atomic64_add_return(long i, atomic64_t *v); */
+static inline long atomic64_add_return(long i, atomic64_t *v)
+{
+	v->counter += i;
+	return v->counter;
+}
+static inline void atomic64_set(atomic64_t *v, long i)
+{
+	v->counter = i;
+}
+long atomic64_sub_return(long i, atomic64_t *v);
+long atomic64_inc_return(atomic64_t *v);
+long atomic64_dec_return(atomic64_t *v);
+long atomic64_cmpxchg(atomic64_t *v, long old, long new);
+long atomic64_xchg(atomic64_t *v, long new);
+int atomic64_add_unless(atomic64_t *v, long a, long u);
+int atomic64_inc_is_not_zero(atomic64_t *v);
+#define atomic64_inc_not_zero(v) 	atomic64_add_unless((v), 1LL, 0LL)
+
+#include <asm-generic/atomic.h>
+
+#endif /* _ASM_SIM_ATOMIC_H */
diff --git a/arch/lib/include/asm/barrier.h b/arch/lib/include/asm/barrier.h
new file mode 100644
index 0000000..47adcc6
--- /dev/null
+++ b/arch/lib/include/asm/barrier.h
@@ -0,0 +1,8 @@
+#include <asm-generic/barrier.h>
+
+#undef smp_store_release
+#define smp_store_release(p, v)						\
+	do {								\
+		smp_mb();						\
+		ACCESS_ONCE(*p) = (v);					\
+	} while (0)
diff --git a/arch/lib/include/asm/bitsperlong.h b/arch/lib/include/asm/bitsperlong.h
new file mode 100644
index 0000000..c7592f9
--- /dev/null
+++ b/arch/lib/include/asm/bitsperlong.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_SIM_BITSPERLONG_H
+#define _ASM_SIM_BITSPERLONG_H
+
+#ifdef CONFIG_64BIT
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif /* CONFIG_64BIT */
+
+#define __BITS_PER_LONG BITS_PER_LONG
+
+#endif /* _ASM_SIM_BITSPERLONG_H */
diff --git a/arch/lib/include/asm/current.h b/arch/lib/include/asm/current.h
new file mode 100644
index 0000000..62489cd
--- /dev/null
+++ b/arch/lib/include/asm/current.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SIM_CURRENT_H
+#define _ASM_SIM_CURRENT_H
+
+struct task_struct *get_current(void);
+#define current get_current()
+
+#endif /* _ASM_SIM_CURRENT_H */
diff --git a/arch/lib/include/asm/elf.h b/arch/lib/include/asm/elf.h
new file mode 100644
index 0000000..a7396c9
--- /dev/null
+++ b/arch/lib/include/asm/elf.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_SIM_ELF_H
+#define _ASM_SIM_ELF_H
+
+#if defined(CONFIG_64BIT)
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
+#endif /* _ASM_SIM_ELF_H */
diff --git a/arch/lib/include/asm/hardirq.h b/arch/lib/include/asm/hardirq.h
new file mode 100644
index 0000000..47d47f9
--- /dev/null
+++ b/arch/lib/include/asm/hardirq.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_SIM_HARDIRQ_H
+#define _ASM_SIM_HARDIRQ_H
+
+extern unsigned int interrupt_pending;
+
+#define local_softirq_pending() (interrupt_pending)
+
+#endif /* _ASM_SIM_HARDIRQ_H */
diff --git a/arch/lib/include/asm/page.h b/arch/lib/include/asm/page.h
new file mode 100644
index 0000000..8c0aa74
--- /dev/null
+++ b/arch/lib/include/asm/page.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_SIM_PAGE_H
+#define _ASM_SIM_PAGE_H
+
+typedef struct {} pud_t;
+
+#define THREAD_ORDER    1
+#define THREAD_SIZE  (PAGE_SIZE << THREAD_ORDER)
+
+#define WANT_PAGE_VIRTUAL 1
+
+#include <asm-generic/page.h>
+#include <asm-generic/getorder.h>
+
+#endif /* _ASM_SIM_PAGE_H */
diff --git a/arch/lib/include/asm/pgtable.h b/arch/lib/include/asm/pgtable.h
new file mode 100644
index 0000000..ce599c8
--- /dev/null
+++ b/arch/lib/include/asm/pgtable.h
@@ -0,0 +1,30 @@
+#ifndef _ASM_SIM_PGTABLE_H
+#define _ASM_SIM_PGTABLE_H
+
+#define PAGE_KERNEL ((pgprot_t) {0 })
+
+#define arch_start_context_switch(prev) do {} while (0)
+
+#define kern_addr_valid(addr)(1)
+#define pte_file(pte)(1)
+/* Encode and de-code a swap entry */
+#define __swp_type(x)                   (((x).val >> 5) & 0x1f)
+#define __swp_offset(x)                 ((x).val >> 11)
+#define __swp_entry(type, offset) \
+	((swp_entry_t) {((type) << 5) | ((offset) << 11) })
+#define __pte_to_swp_entry(pte)         ((swp_entry_t) {pte_val((pte)) })
+#define __swp_entry_to_pte(x)           ((pte_t) {(x).val })
+#define pmd_page(pmd) (struct page *)(pmd_val(pmd) & PAGE_MASK)
+#define pgtable_cache_init()   do { } while (0)
+
+static inline int pte_swp_soft_dirty(pte_t pte)
+{
+	return 0;
+}
+
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+	return pte;
+}
+
+#endif /* _ASM_SIM_PGTABLE_H */
diff --git a/arch/lib/include/asm/processor.h b/arch/lib/include/asm/processor.h
new file mode 100644
index 0000000..b673ee0
--- /dev/null
+++ b/arch/lib/include/asm/processor.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_SIM_PROCESSOR_H
+#define _ASM_SIM_PROCESSOR_H
+
+struct thread_struct {};
+
+#define cpu_relax()
+#define cpu_relax_lowlatency() cpu_relax()
+#define KSTK_ESP(tsk)	(0)
+
+void *current_text_addr(void);
+
+#define TASK_SIZE ((~(long)0))
+
+#define thread_saved_pc(x) (unsigned long)0
+#define task_pt_regs(t) NULL
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+#endif /* _ASM_SIM_PROCESSOR_H */
diff --git a/arch/lib/include/asm/ptrace.h b/arch/lib/include/asm/ptrace.h
new file mode 100644
index 0000000..ddd9708
--- /dev/null
+++ b/arch/lib/include/asm/ptrace.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_PTRACE_H
+#define _ASM_SIM_PTRACE_H
+
+#endif /* _ASM_SIM_PTRACE_H */
diff --git a/arch/lib/include/asm/segment.h b/arch/lib/include/asm/segment.h
new file mode 100644
index 0000000..e056922
--- /dev/null
+++ b/arch/lib/include/asm/segment.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SIM_SEGMENT_H
+#define _ASM_SIM_SEGMENT_H
+
+typedef struct { int seg; } mm_segment_t;
+
+#endif /* _ASM_SIM_SEGMENT_H */
diff --git a/arch/lib/include/asm/sembuf.h b/arch/lib/include/asm/sembuf.h
new file mode 100644
index 0000000..d64927b
--- /dev/null
+++ b/arch/lib/include/asm/sembuf.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SEMBUF_H
+#define _ASM_SIM_SEMBUF_H
+
+#endif /* _ASM_SIM_SEMBUF_H */
diff --git a/arch/lib/include/asm/shmbuf.h b/arch/lib/include/asm/shmbuf.h
new file mode 100644
index 0000000..42d0a71
--- /dev/null
+++ b/arch/lib/include/asm/shmbuf.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SHMBUF_H
+#define _ASM_SIM_SHMBUF_H
+
+#endif /* _ASM_SIM_SHMBUF_H */
diff --git a/arch/lib/include/asm/shmparam.h b/arch/lib/include/asm/shmparam.h
new file mode 100644
index 0000000..3410f1b
--- /dev/null
+++ b/arch/lib/include/asm/shmparam.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_SHMPARAM_H
+#define _ASM_SIM_SHMPARAM_H
+
+#endif /* _ASM_SIM_SHMPARAM_H */
diff --git a/arch/lib/include/asm/sigcontext.h b/arch/lib/include/asm/sigcontext.h
new file mode 100644
index 0000000..230b4b5
--- /dev/null
+++ b/arch/lib/include/asm/sigcontext.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SIM_SIGCONTEXT_H
+#define _ASM_SIM_SIGCONTEXT_H
+
+struct sigcontext {};
+
+#endif /* _ASM_SIM_SIGCONTEXT_H */
diff --git a/arch/lib/include/asm/stat.h b/arch/lib/include/asm/stat.h
new file mode 100644
index 0000000..80fa2cb
--- /dev/null
+++ b/arch/lib/include/asm/stat.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_STAT_H
+#define _ASM_SIM_STAT_H
+
+#endif /* _ASM_SIM_STAT_H */
diff --git a/arch/lib/include/asm/statfs.h b/arch/lib/include/asm/statfs.h
new file mode 100644
index 0000000..881ce51
--- /dev/null
+++ b/arch/lib/include/asm/statfs.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_STATFS_H
+#define _ASM_SIM_STATFS_H
+
+#endif /* _ASM_SIM_STATFS_H */
diff --git a/arch/lib/include/asm/swab.h b/arch/lib/include/asm/swab.h
new file mode 100644
index 0000000..d81376a
--- /dev/null
+++ b/arch/lib/include/asm/swab.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SIM_SWAB_H
+#define _ASM_SIM_SWAB_H
+
+#include <linux/types.h>
+
+
+#endif /* _ASM_SIM_SWAB_H */
diff --git a/arch/lib/include/asm/thread_info.h b/arch/lib/include/asm/thread_info.h
new file mode 100644
index 0000000..ec316c6
--- /dev/null
+++ b/arch/lib/include/asm/thread_info.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_SIM_THREAD_INFO_H
+#define _ASM_SIM_THREAD_INFO_H
+
+#define TIF_NEED_RESCHED 1
+#define TIF_SIGPENDING 2
+#define TIF_MEMDIE 5
+
+struct thread_info {
+	__u32 flags;
+	int preempt_count;
+	struct task_struct *task;
+	struct restart_block restart_block;
+};
+
+struct thread_info *current_thread_info(void);
+struct thread_info *alloc_thread_info(struct task_struct *task);
+void free_thread_info(struct thread_info *ti);
+
+#define TS_RESTORE_SIGMASK      0x0008  /* restore signal mask in do_signal() */
+#define HAVE_SET_RESTORE_SIGMASK        1
+static inline void set_restore_sigmask(void)
+{
+}
+static inline void clear_restore_sigmask(void)
+{
+}
+static inline bool test_restore_sigmask(void)
+{
+	return true;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+	return true;
+}
+
+#endif /* _ASM_SIM_THREAD_INFO_H */
diff --git a/arch/lib/include/asm/uaccess.h b/arch/lib/include/asm/uaccess.h
new file mode 100644
index 0000000..74f973b
--- /dev/null
+++ b/arch/lib/include/asm/uaccess.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_SIM_UACCESS_H
+#define _ASM_SIM_UACCESS_H
+
+#define KERNEL_DS ((mm_segment_t) {0 })
+#define USER_DS ((mm_segment_t) {0 })
+#define get_fs() KERNEL_DS
+#define get_ds() USER_DS
+#define set_fs(x) do {} while ((x.seg) != (x.seg))
+
+#define __access_ok(addr, size) (1)
+
+#include <asm-generic/uaccess.h>
+
+#endif /* _ASM_SIM_UACCESS_H */
diff --git a/arch/lib/include/asm/unistd.h b/arch/lib/include/asm/unistd.h
new file mode 100644
index 0000000..6b482b4
--- /dev/null
+++ b/arch/lib/include/asm/unistd.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SIM_UNISTD_H
+#define _ASM_SIM_UNISTD_H
+
+#endif /* _ASM_SIM_UNISTD_H */
diff --git a/arch/lib/include/uapi/asm/byteorder.h b/arch/lib/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..b13a7a8
--- /dev/null
+++ b/arch/lib/include/uapi/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_BYTEORDER_H
+#define _ASM_X86_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_X86_BYTEORDER_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 09/10] lib: libos build scripts and documentation
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (7 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 08/10] lib: auxially files for auto-generated asm-generic files of libos Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-20 20:43       ` Paul Bolle
  2015-04-19 13:28     ` [RFC PATCH v3 10/10] lib: tools used for test scripts Hajime Tazaki
                       ` (2 subsequent siblings)
  11 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

document and build scripts for libos architecture.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 Documentation/virtual/libos-howto.txt | 144 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   8 +
 arch/lib/Kconfig                      | 124 +++++++
 arch/lib/Makefile                     | 251 +++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/processor.mk                 |   7 +
 9 files changed, 1291 insertions(+)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/defconfig
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/processor.mk

diff --git a/Documentation/virtual/libos-howto.txt b/Documentation/virtual/libos-howto.txt
new file mode 100644
index 0000000..fbf7946
--- /dev/null
+++ b/Documentation/virtual/libos-howto.txt
@@ -0,0 +1,144 @@
+Library operating system (libos) version of Linux
+=================================================
+
+* Overview
+
+New hardware independent architecture 'arch/lib', configured by
+CONFIG_LIB gives you two features.
+
+- network stack in userspace (NUSE)
+  NUSE will give you a personalized network stack for each application
+  without replacing host operating system.
+
+- network simulator integration, which is called Direct Code Execution (DCE)
+  DCE will give us a network simulation environment with Linux network stack
+  to investigate the detail behavior protocol implementation with a flexible
+  network configuration. This is also useful for the testing environment.
+
+(- more abstracted implementation of underlying platform will be a future
+   direction (e.g., rump hypercall))
+
+In both features, Linux kernel network stack is running on top of
+userspace application with a linked or dynamically loaded library.
+
+They have their own, isolated network stack from host operating system
+so they are configured different IP addresses as other virtualization
+methods do.
+
+
+* How different with others ?
+
+- User-mode Linux (UML)
+
+UML is a way to execute Linux kernel code as a userspace
+application. It is completely isolated from host kernel but can host
+arbitrary userspace applications on top of UML.
+
+- namespace / container
+
+Container technologies with namespace brings a process-level isolation
+to host multiple network entities but shares the kernel among
+processes, which prevents to introduce new features implemented in
+kernel space.
+
+
+* How to build it ?
+
+configuration of arch/lib follows a standard configuration of kernel.
+
+ make defconfig ARCH=lib
+
+or
+
+ make menuconfig ARCH=lib
+
+then you can build a set of libraries for libos.
+
+ make library ARCH=lib
+
+This will give you a shared library file liblinux-$(KERNELVERSION).so
+in the top directory.
+
+* Hello world
+
+you may first need to configure a configuration file, named
+'nuse.conf' so that the library version of network stack can know what
+kind of IP configuration should be used. There is an example file
+at arch/lib/nuse.conf.sample: you may copy and modify it for your purpose.
+
+ sudo NUSECONF=nuse.conf ./nuse ping www.google.com
+
+
+
+* Example use cases
+- regression test with Direct Code Execution (DCE)
+
+'make test' by DCE gives a test platform for networking code, with the
+help of network simulator facilities like link delay/bandwidth/drop
+configurations, large network topology with userspace routing protocol
+daemons, etc.
+
+An interesting feature is the determinism of any test executions. A
+test script always gives same results in every execution if there is
+no modification on test target code.
+
+For the first step, you need to obtain network simulator
+environment. 'make testbin' does all the stuff for the preparation.
+
+% make testbin -C tools/testing/libos
+
+Then, you can 'make test' for your code.
+
+% make test ARCH=lib
+
+ PASS: TestSuite netlink-socket
+ PASS: TestSuite process-manager
+ PASS: TestSuite dce-cradle
+ PASS: TestSuite dce-mptcp
+ PASS: TestSuite dce-umip
+ PASS: TestSuite dce-quagga
+ PASS: Example dce-tcp-simple
+ PASS: Example dce-udp-simple
+
+
+- userspace network stack (NUSE)
+
+an application can use its own network stack, distinct from host network stack
+in order to personalize any network feature to the application specific one.
+The 'nuse' wrapper script, based on LD_PRELOAD technique, carefully replaces
+socket API and redirects system calls to the network stack library, provided by
+this framework.
+
+the network stack can be used with any kind of raw-socket like
+technologies such as Intel DPDK, netmap, etc.
+
+
+
+* Files / External Repository
+
+The kernel source tree (i.e., arch/lib) only contains a shared part of
+applications (NUSE/DCE). Pure userspace part is managed at a different
+repository, called Linux-libos-tools: it is automatically downloaded
+during make library.
+
+ https://github.com/libos-nuse/linux-libos-tools
+
+
+* More information
+- libos-nuse@googlegroups.com (LibOS in general and NUSE related questions)
+- ns-3-users@googlegroups.com (ns-3 related questions)
+- articles, slides
+ Experimentation Tools for Networking Research (Lacage, 2010)
+   http://cutebugs.net/files/thesis.pdf
+ Direct code execution: revisiting library OS architecture for reproducible
+  network experiments (Tazaki et al., 2013)
+   http://dx.doi.org/10.1145/2535372.2535374
+ Library Operating System with Mainline Linux Network Stack (Tazaki et al., 2015)
+   https://www.netdev01.org/docs/netdev01-tazaki-libos.pdf (slides)
+
+
+* Authors
+ Mathieu Lacage <mathieu.lacage@gmail.com>
+ Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ Frederic Urbani <frederic.urbani@gmail.com>
+ Ryo Nakamura <upa@haeena.net>
diff --git a/MAINTAINERS b/MAINTAINERS
index 3589d67..ae88290 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5699,6 +5699,15 @@ M:	Sasha Levin <sasha.levin@oracle.com>
 S:	Maintained
 F:	tools/lib/lockdep/
 
+LIBRARY OS (LIBOS)
+M:	Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+L:	libos-nuse@googlegroups.com
+W:	http://libos-nuse.github.io/
+S:	Maintained
+F:	Documentation/virtual/libos-howto.txt
+F:	arch/lib/
+F:	tools/testing/libos/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:	Paul Mackerras <paulus@au.ibm.com>
 W:	http://www.ibm.com/linux/ltc/projects/ppc
diff --git a/arch/lib/.gitignore b/arch/lib/.gitignore
new file mode 100644
index 0000000..9f48573
--- /dev/null
+++ b/arch/lib/.gitignore
@@ -0,0 +1,8 @@
+linker.lds
+autoconf.h
+objs.mk
+timeconst.h
+hz.bc
+crc32table.h
+*.d
+tools
diff --git a/arch/lib/Kconfig b/arch/lib/Kconfig
new file mode 100644
index 0000000..3dfa269
--- /dev/null
+++ b/arch/lib/Kconfig
@@ -0,0 +1,124 @@
+menuconfig LIB
+       bool "LibOS-specific options"
+       def_bool n
+       select PROC_FS
+       select PROC_SYSCTL
+       select SYSCTL
+       select SYSFS
+       help
+          The 'lib' architecture is a library (user-mode) version of
+          the linux kernel that includes only its network stack and is
+	  used within the userspace application, and ns-3 simulator.
+	  For more information, about ns-3, see http://www.nsnam.org.
+
+config EXPERIMENTAL
+	def_bool y
+
+config MMU
+        def_bool n
+config FPU
+        def_bool n
+config SMP
+        def_bool n
+
+config ARCH
+	string
+	option env="ARCH"
+
+config KTIME_SCALAR
+       def_bool y
+
+config MODULES
+       def_bool y
+       option modules
+
+config GENERIC_CSUM
+	def_bool y
+
+config GENERIC_BUG
+	def_bool y
+	depends on BUG
+config PRINTK
+       def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+	def_bool y
+
+config GENERIC_HWEIGHT
+       def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config NO_HZ
+	def_bool y
+
+config BASE_FULL
+       def_bool n
+
+config SELECT_MEMORY_MODEL
+       def_bool n
+
+config FLAT_NODE_MEM_MAP
+       def_bool n
+
+config PAGEFLAGS_EXTENDED
+       def_bool n
+
+config VIRT_TO_BUS
+       def_bool n
+
+config HAS_DMA
+       def_bool n
+
+config HZ
+        int
+        default 250
+
+config TINY_RCU
+       def_bool y
+
+config HZ_250
+       def_bool y
+
+config BASE_SMALL
+       int
+       default 1
+
+config SPLIT_PTLOCK_CPUS
+       int
+       default 1
+
+config FLATMEM
+       def_bool y
+
+config SYSCTL
+       def_bool y
+
+config PROC_FS
+       def_bool y
+
+config SYSFS
+       def_bool y
+
+config PROC_SYSCTL
+       def_bool y
+
+config NETDEVICES
+       def_bool y
+
+config SLIB
+       def_bool y
+
+source "net/Kconfig"
+
+source "drivers/base/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+
diff --git a/arch/lib/Makefile b/arch/lib/Makefile
new file mode 100644
index 0000000..d8a0bf9
--- /dev/null
+++ b/arch/lib/Makefile
@@ -0,0 +1,251 @@
+ARCH_DIR := arch/lib
+SRCDIR=$(dir $(firstword $(MAKEFILE_LIST)))
+DCE_TESTDIR=$(srctree)/tools/testing/libos/
+KBUILD_KCONFIG := arch/$(ARCH)/Kconfig
+
+CC = gcc
+GCCVERSIONGTEQ48 := $(shell expr `gcc -dumpversion` \>= 4.8)
+ifeq "$(GCCVERSIONGTEQ48)" "1"
+   NO_TREE_LOOP_OPT += -fno-tree-loop-distribute-patterns
+endif
+
+
+-include $(ARCH_DIR)/objs.mk
+-include $(srctree)/.config
+include $(srctree)/scripts/Kbuild.include
+include $(ARCH_DIR)/processor.mk
+
+# targets
+LIBOS_TOOLS=$(ARCH_DIR)/tools
+LIBOS_GIT_REPO=git://github.com/libos-nuse/linux-libos-tools
+KERNEL_LIB=liblinux-$(KERNELVERSION).so
+
+ALL_OBJS=$(OBJS) $(KERNEL_LIB) $(modules) $(all-obj-for-clean)
+
+# auto generated files
+AUTOGENS=$(CRC32TABLE) $(COMPILE_H) $(BOUNDS_H) $(ARCH_DIR)/timeconst.h $(ARCH_DIR)/linker.lds
+COMPILE_H=$(srctree)/include/generated/compile.h
+BOUNDS_H=$(srctree)/include/generated/bounds.h
+
+# from lib/Makefile
+CRC32TABLE = $(ARCH_DIR)/crc32table.h
+hostprogs-y	:= $(srctree)/lib/gen_crc32table
+clean-files	:= crc32table.h
+
+# sources and objects
+LIB_SRC=\
+lib.c lib-device.c lib-socket.c random.c softirq.c time.c \
+timer.c hrtimer.c sched.c workqueue.c \
+print.c tasklet.c tasklet-hrtimer.c \
+glue.c fs.c sysctl.c proc.c sysfs.c \
+capability.c pid.c modules.c filemap.c vmscan.c
+
+LIB_OBJ=$(addprefix $(ARCH_DIR)/,$(addsuffix .o,$(basename $(LIB_SRC))))
+LIB_DEPS=$(addprefix $(ARCH_DIR)/.,$(addsuffix .o.cmd,$(basename $(LIB_SRC))))
+-include $(LIB_DEPS)
+
+DEPENDS=$(addprefix $(ARCH_DIR)/.,\
+	$(addsuffix .d,$(basename $(LIB_SRC)))\
+	)
+
+# options
+COV?=no
+cov_yes=-fprofile-arcs -ftest-coverage
+cov_no=
+covl_yes=-fprofile-arcs
+covl_no=
+OPT?=yes
+opt_yes=-O3 -fomit-frame-pointer $(NO_TREE_LOOP_OPT)
+opt_no=-O0
+PIC?=yes
+pic_yes=-fpic -DPIC
+pic_no=-mcmodel=large
+PIC_CFLAGS=$(pic_$(PIC))
+
+# flags
+CFLAGS_USPACE= \
+ -Wp,-MD,$(depfile) $(opt_$(OPT)) -g3 -Wall -Wstrict-prototypes -Wno-trigraphs \
+ -fno-inline -fno-strict-aliasing -fno-common \
+ -fno-delete-null-pointer-checks -fno-builtin \
+ -fno-stack-protector -Wno-unused -Wno-pointer-sign \
+ $(PIC_CFLAGS) -D_DEBUG $(cov_$(COV)) -I$(ARCH_DIR)/include
+
+CFLAGS+= \
+ $(CFLAGS_USPACE) -nostdinc -D__KERNEL__ -iwithprefix $(srctree)/include \
+ -DKBUILD_BASENAME=\"clnt\" -DKBUILD_MODNAME=\"nsc\" -DMODVERSIONS \
+ -DEXPORT_SYMTAB \
+ -U__FreeBSD__ -D__linux__=1 -Dlinux=1 -D__linux=1 \
+ -DCONFIG_DEFAULT_HOSTNAME=\"lib\" \
+ -I$(ARCH_DIR)/include/generated/uapi \
+ -I$(ARCH_DIR)/include/generated \
+ -I$(srctree)/include -I$(ARCH_DIR)/include/uapi \
+ -I$(srctree)/include/uapi -I$(srctree)/include/generated/uapi \
+ -include $(srctree)/include/linux/kconfig.h \
+ -I$(ARCH_DIR) -I.
+
+ifeq ($(PROCESSOR_SIZE),64)
+CFLAGS+= -DCONFIG_64BIT
+endif
+
+LDFLAGS += -shared -nodefaultlibs -g3 -Wl,-O1 -Wl,-T$(ARCH_DIR)/linker.lds $(covl_$(COV))
+
+# targets
+
+modules:=
+all-obj-for-clean:=
+
+all: library modules
+
+# note: the directory order below matters to ensure that we match the kernel order
+dirs=kernel/ kernel/time/ kernel/rcu/ kernel/locking/ kernel/bpf/ mm/ fs/ fs/proc/ crypto/ lib/ drivers/base/ drivers/net/ net/ init/
+empty:=
+space:= $(empty) $(empty)
+colon:= :
+comma= ,
+kernel/_to_keep=notifier.o params.o sysctl.o \
+rwsem.o semaphore.o kfifo.o cred.o user.o groups.o ksysfs.o
+kernel/time/_to_keep=time.o
+kernel/rcu_to_keep=rcu/srcu.o rcu/pdate.o rcu/tiny.o
+kernel/locking_to_keep=locking/mutex.o
+kernel/bpf_to_keep=bpf/core.o
+mm/_to_keep=util.o list_lru.o slib.o
+crypto/_to_keep=aead.o ahash.o shash.o api.o algapi.o cipher.o compress.o proc.o \
+crc32c_generic.o
+drivers/base/_to_keep=class.o core.o bus.o dd.o driver.o devres.o module.o map.o
+drivers/net/_to_keep=loopback.o
+lib/_to_keep=klist.o kobject.o kref.o hweight.o int_sqrt.o checksum.o \
+find_last_bit.o find_next_bit.o bitmap.o nlattr.o idr.o libcrc32c.o \
+ctype.o string.o kasprintf.o rbtree.o sha1.o textsearch.o vsprintf.o \
+rwsem-spinlock.o scatterlist.o ratelimit.o hexdump.o dec_and_lock.o \
+div64.o dynamic_queue_limits.o md5.o kstrtox.o iovec.o lockref.o crc32.o \
+rhashtable.o iov_iter.o cmdline.o kobject_uevent.o
+fs/_to_keep=read_write.o libfs.o namei.o filesystems.o file.o file_table.o \
+dcache.o inode.o pipe.o char_dev.o splice.o no-block.o seq_file.o super.o \
+fcntl.o coredump.o
+fs/proc/_to_keep=proc_sysctl.o proc_net.o root.o generic.o inode.o
+init/_to_keep=version.o
+
+quiet_cmd_objsmk = OBJS-MK   $@
+      cmd_objsmk = \
+	for i in 1; do \
+	$(foreach d,$(dirs), \
+           $(MAKE) -i -s -f $< srcdir=$(srctree)/$(d) \
+	    objdir=$(srctree)/$(d) \
+            config=$(srctree)/.config \
+	    to_keep=$(subst $(space),$(colon),$($(d)_to_keep)) print;) \
+	done > $@
+
+$(ARCH_DIR)/objs.mk: $(ARCH_DIR)/Makefile.print $(srctree)/.config $(ARCH_DIR)/Makefile
+	+$(call if_changed,objsmk)
+
+quiet_cmd_timeconst = GEN     $@
+      cmd_timeconst = echo "hz=$(CONFIG_HZ)" > $(ARCH_DIR)/hz.bc ; \
+                      bc $(ARCH_DIR)/hz.bc kernel/time/timeconst.bc > $@
+$(ARCH_DIR)/timeconst.h: $(srctree)/.config
+	$(call if_changed,timeconst)
+
+quiet_cmd_linker = GEN     $@
+      cmd_linker = ld -shared --verbose | ./$^ > $@
+$(ARCH_DIR)/linker.lds: $(ARCH_DIR)/generate-linker-script.py
+	$(call if_changed,linker)
+
+quiet_cmd_crc32src = GEN     $@
+      cmd_crc32src = $(MAKE) -f $(srctree)/Makefile silentoldconfig ; \
+                     cc $^ -o $@
+$(srctree)/lib/gen_crc32table: $(srctree)/lib/gen_crc32table.c
+	$(call if_changed,crc32src)
+
+quiet_cmd_crc32 = GEN     $@
+      cmd_crc32 = $< > $@
+
+$(CRC32TABLE): $(srctree)/lib/gen_crc32table
+	$(call if_changed,crc32)
+
+# copied from init/Makefile
+       chk_compile.h = :
+ quiet_chk_compile.h = echo '  CHK     $@'
+silent_chk_compile.h = :
+$(COMPILE_H): include/generated/utsrelease.h asm-generic $(version_h)
+	@$($(quiet)chk_compile.h)
+	+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
+	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
+
+# crafted from $(srctree)/Kbuild
+quiet_cmd_lib_bounds = GEN     $@
+define cmd_lib_bounds
+	(set -e; \
+	 echo "#ifndef GENERATED_BOUNDS_H"; \
+	 echo "#define GENERATED_BOUNDS_H"; \
+	 echo ""; \
+	 echo "#define NR_PAGEFLAGS (__NR_PAGEFLAGS)"; \
+	 echo "#define MAX_NR_ZONES (__MAX_NR_ZONES)"; \
+	 echo ""; \
+	 echo "#endif /* GENERATED_BOUNDS_H */") > $@
+endef
+
+$(BOUNDS_H):
+	$(Q)mkdir -p $(dir $@)
+	$(call cmd,lib_bounds)
+
+
+KERNEL_BUILTIN=$(addprefix $(srctree)/,$(addsuffix builtin.o,$(dirs)))
+OBJS=$(LIB_OBJ) $(foreach builtin,$(KERNEL_BUILTIN),$(if $($(builtin)),$($(builtin))))
+export OBJS KERNEL_LIB COV covl_yes covl_no
+
+quiet_cmd_cc = CC      $@
+      cmd_cc = 	mkdir -p $(dir $@);	\
+		$(CC) $(CFLAGS) -c $< -o $@
+quiet_cmd_linkko = KO   $@
+      cmd_linkko = $(CC) -shared -o $@ -nostdlib $^
+quiet_cmd_builtin = BUILTIN   $@
+      cmd_builtin = mkdir -p $(dir $(srctree)/$@); rm -f $(srctree)/$@; \
+		    if test -n "$($(srctree)/$@)"; then for f in $($(srctree)/$@); \
+		    do $(AR) Tcru $@ $$f; done; else $(AR) Tcru $@; fi
+
+%/builtin.o:
+	$(call if_changed,builtin)
+%.ko:%.o
+	$(call if_changed,linkko)
+%.o:%.c
+	$(call if_changed_dep,cc)
+
+library: $(KERNEL_LIB) $(LIBOS_TOOLS)
+modules: $(modules)
+
+$(LIBOS_TOOLS): $(KERNEL_LIB) Makefile FORCE
+	$(Q) if [ ! -d "$@" ]; then \
+		git clone $(LIBOS_GIT_REPO) $@ ;\
+	fi
+	$(Q) $(MAKE) -C $(LIBOS_TOOLS)
+
+install: modules library
+
+install-dir:
+
+$(KERNEL_LIB): $(ARCH_DIR)/objs.mk $(AUTOGENS) $(OBJS)
+	$(call if_changed,linklib)
+
+quiet_cmd_linklib = LIB     $@
+      cmd_linklib = $(CC) -Wl,--whole-archive $(OBJS) $(LDFLAGS) -o $@; \
+		    ln -s -f $(KERNEL_LIB) liblinux.so
+
+quiet_cmd_clean = CLEAN   $@
+      cmd_clean = for f in $(foreach m,$(modules),$($(m))) ; do rm -f $$f 2>/dev/null; done ; \
+		  for f in $(ALL_OBJS); do rm -f $$f; done 2>/dev/null ;\
+		  rm -rf $(AUTOGENS) $(ARCH_DIR)/objs.mk 2>/dev/null ;\
+		  if [ -d $(LIBOS_TOOLS) ]; then $(MAKE) -C $(LIBOS_TOOLS) clean ; fi
+
+archclean:
+	$(call if_changed,clean)
+
+.%.d:%.c $(srctree)/.config
+	$(Q) set -e; $(CC) -MM -MT $(<:.c=.o) $(CFLAGS) $< > $@
+
+deplib: $(DEPENDS)
+	-include $(DEPENDS)
+
+test:
+	$(Q) $(MAKE) -C $(DCE_TESTDIR)/
+
+.PHONY : clean deplib
+
diff --git a/arch/lib/Makefile.print b/arch/lib/Makefile.print
new file mode 100644
index 0000000..40e6db0
--- /dev/null
+++ b/arch/lib/Makefile.print
@@ -0,0 +1,45 @@
+# inherit $(objdir) $(config) $(srcdir) $(to_keep) from command-line
+
+include $(config)
+include $(srcdir)Makefile
+
+# fix minor nits for make version dependencies
+ifeq (3.82,$(firstword $(sort $(MAKE_VERSION) 3.82)))
+  SEPARATOR=
+else
+  SEPARATOR=/
+endif
+
+to_keep_list=$(subst :, ,$(to_keep))
+obj-y += $(lib-y)
+obj-m += $(lib-m)
+subdirs := $(filter %/, $(obj-y) $(obj-m))
+subdirs-y := $(filter %/, $(obj-y))
+subdirs-m := $(filter %/, $(obj-m))
+tmp1-obj-y=$(patsubst %/,%/builtin.o,$(obj-y))
+tmp1-obj-m=$(filter-out $(subdirs-m),$(obj-m))
+tmp2-obj-y=$(foreach m,$(tmp1-obj-y), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
+tmp2-obj-m=$(foreach m,$(tmp1-obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
+tmp3-obj-y=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-y)),$(tmp2-obj-y))
+tmp3-obj-m=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-m)),$(tmp2-obj-m))
+final-obj-y=$(tmp3-obj-y)
+final-obj-m=$(tmp3-obj-m)
+
+print: $(final-obj-m) $(subdirs)
+	@if test $(if $(final-obj-y),1); then \
+	  echo -n $(objdir)builtin.o; echo -n "="; echo $(addprefix $(objdir),$(final-obj-y)); \
+	  echo -n $(objdir)builtin.o; echo -n ": "; echo $(addprefix $(objdir),$(final-obj-y)); \
+          echo -n "-include "; echo $(addprefix $(objdir).,$(addsuffix ".cmd", $(final-obj-y))); \
+	  echo -n "all-obj-for-clean+="; echo $(addprefix $(objdir),$(final-obj-y)) $(objdir)builtin.o; \
+	fi
+$(final-obj-m):
+	@echo -n "modules+="; echo $(addprefix $(objdir),$(@:.o=.ko))
+	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n ": "
+	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
+	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n "="
+	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
+$(subdirs):
+	@$(MAKE) -s -f $(firstword $(MAKEFILE_LIST)) objdir=$(objdir)$@$(SEPARATOR) config=$(config) srcdir=$(srcdir)$@$(SEPARATOR) to_keep=$(to_keep) print 2>/dev/null
+
+.PHONY : core
+.NOTPARALLEL : print $(subdirs) $(final-obj-m)
diff --git a/arch/lib/defconfig b/arch/lib/defconfig
new file mode 100644
index 0000000..9307e6f
--- /dev/null
+++ b/arch/lib/defconfig
@@ -0,0 +1,653 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux Kernel Configuration
+#
+CONFIG_LIB=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+# CONFIG_SMP is not set
+CONFIG_KTIME_SCALAR=y
+CONFIG_MODULES=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_PRINTK=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_NO_HZ=y
+# CONFIG_BASE_FULL is not set
+# CONFIG_SELECT_MEMORY_MODEL is not set
+# CONFIG_FLAT_NODE_MEM_MAP is not set
+# CONFIG_PAGEFLAGS_EXTENDED is not set
+# CONFIG_VIRT_TO_BUS is not set
+# CONFIG_HAS_DMA is not set
+CONFIG_HZ=250
+CONFIG_TINY_RCU=y
+CONFIG_HZ_250=y
+CONFIG_BASE_SMALL=1
+CONFIG_SPLIT_PTLOCK_CPUS=1
+CONFIG_FLATMEM=y
+CONFIG_SYSCTL=y
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=y
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_NET_UDP_TUNNEL=m
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_GENEVE is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=y
+CONFIG_TCP_CONG_HSTCP=y
+CONFIG_TCP_CONG_HYBLA=y
+CONFIG_TCP_CONG_VEGAS=y
+CONFIG_TCP_CONG_SCALABLE=y
+CONFIG_TCP_CONG_LP=y
+CONFIG_TCP_CONG_VENO=y
+CONFIG_TCP_CONG_YEAH=y
+CONFIG_TCP_CONG_ILLINOIS=y
+CONFIG_TCP_CONG_DCTCP=y
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_HYBLA is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_VENO is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_DCTCP is not set
+CONFIG_DEFAULT_RENO=y
+CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=y
+# CONFIG_IPV6_GRE is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=m
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_ACCT=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_LOG_COMMON=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_DCCP=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+CONFIG_NF_NAT_PROTO_SCTP=y
+CONFIG_NF_NAT_AMANDA=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_NF_NAT_TFTP is not set
+CONFIG_NF_NAT_REDIRECT=y
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_EXTHDR=y
+CONFIG_NFT_META=y
+CONFIG_NFT_CT=y
+CONFIG_NFT_RBTREE=y
+CONFIG_NFT_HASH=y
+CONFIG_NFT_COUNTER=y
+CONFIG_NFT_LOG=y
+CONFIG_NFT_LIMIT=y
+CONFIG_NFT_MASQ=y
+# CONFIG_NFT_REDIR is not set
+CONFIG_NFT_NAT=y
+# CONFIG_NFT_QUEUE is not set
+# CONFIG_NFT_REJECT is not set
+# CONFIG_NFT_REJECT_INET is not set
+# CONFIG_NFT_COMPAT is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+# CONFIG_NETFILTER_XT_SET is not set
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_NETMAP=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_RATEEST=y
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=y
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_L2TP=m
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+CONFIG_IP_SET=y
+CONFIG_IP_SET_MAX=256
+# CONFIG_IP_SET_BITMAP_IP is not set
+# CONFIG_IP_SET_BITMAP_IPMAC is not set
+# CONFIG_IP_SET_BITMAP_PORT is not set
+# CONFIG_IP_SET_HASH_IP is not set
+# CONFIG_IP_SET_HASH_IPMARK is not set
+# CONFIG_IP_SET_HASH_IPPORT is not set
+# CONFIG_IP_SET_HASH_IPPORTIP is not set
+# CONFIG_IP_SET_HASH_IPPORTNET is not set
+# CONFIG_IP_SET_HASH_MAC is not set
+# CONFIG_IP_SET_HASH_NETPORTNET is not set
+# CONFIG_IP_SET_HASH_NET is not set
+# CONFIG_IP_SET_HASH_NETNET is not set
+# CONFIG_IP_SET_HASH_NETPORT is not set
+# CONFIG_IP_SET_HASH_NETIFACE is not set
+# CONFIG_IP_SET_LIST_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_LOG_ARP is not set
+CONFIG_NF_LOG_IPV4=y
+CONFIG_NF_TABLES_IPV4=y
+CONFIG_NFT_CHAIN_ROUTE_IPV4=y
+# CONFIG_NF_REJECT_IPV4 is not set
+# CONFIG_NFT_REJECT_IPV4 is not set
+# CONFIG_NF_TABLES_ARP is not set
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_FILTER is not set
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_TABLES_IPV6=y
+# CONFIG_NFT_CHAIN_ROUTE_IPV6 is not set
+# CONFIG_NF_REJECT_IPV6 is not set
+# CONFIG_NFT_REJECT_IPV6 is not set
+CONFIG_NF_LOG_IPV6=y
+# CONFIG_NF_NAT_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+# CONFIG_NF_TABLES_BRIDGE is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=y
+CONFIG_INET_DCCP_DIAG=y
+
+#
+# DCCP CCIDs Configuration
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_SCTP=y
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE=y
+# CONFIG_SCTP_COOKIE_HMAC_MD5 is not set
+# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_L2TP=m
+# CONFIG_L2TP_V3 is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_VLAN_8021Q_MVRP is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+CONFIG_IPX_INTERN=y
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_PHONET=m
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_SJA1000=m
+# CONFIG_CAN_SJA1000_ISA is not set
+CONFIG_CAN_SJA1000_PLATFORM=m
+# CONFIG_CAN_C_CAN is not set
+# CONFIG_CAN_M_CAN is not set
+# CONFIG_CAN_CC770 is not set
+# CONFIG_CAN_SOFTING is not set
+CONFIG_CAN_DEBUG_DEVICES=y
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+
+#
+# Dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_BT=m
+CONFIG_BT_BREDR=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_LE=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+# CONFIG_NET_9P is not set
+CONFIG_CAIF=m
+CONFIG_CAIF_DEBUG=y
+CONFIG_CAIF_NETDEV=m
+# CONFIG_CAIF_USB is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_MCRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST_COMMON=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_DRBG_MENU is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
diff --git a/arch/lib/generate-linker-script.py b/arch/lib/generate-linker-script.py
new file mode 100755
index 0000000..db3d7f8
--- /dev/null
+++ b/arch/lib/generate-linker-script.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+import re
+
+def linker_script(reading, writing):
+    delim = re.compile('^==')
+    end_of_ro = re.compile('^ *.gcc_except_table[^:]*:[ ]*ONLY_IF_RW')
+    skipping = True
+    for line in reading.readlines():
+        if delim.search (line) is not None:
+            if skipping:
+                skipping = False
+                continue
+            else:
+                skipping = True
+        if skipping:
+            continue
+        m = end_of_ro.search(line)
+        if m is not None:
+            skipping = False
+            initcall = """
+  /* taken from kernel script*/
+    . = ALIGN (CONSTANT (MAXPAGESIZE));
+    .initcall.init : AT(ADDR(.initcall.init)) {
+     __initcall_start = .;
+     *(.initcallearly.init)
+     *(.initcall0.init)
+     *(.initcall0s.init)
+     *(.initcall1.init)
+     *(.initcall1s.init)
+     *(.initcall2.init)
+     *(.initcall2s.init)
+     *(.initcall3.init)
+     *(.initcall3s.init)
+     *(.initcall4.init)
+     *(.initcall4s.init)
+     *(.initcall5.init)
+     *(.initcall5s.init)
+     *(.initcall6.init)
+     *(.initcall6s.init)
+     *(.initcall7.init)
+     *(.initcall7s.init)
+     __initcall_end = .;
+    }
+"""
+            writing.write (initcall)
+        writing.write(line)
+
+import sys
+linker_script (sys.stdin, sys.stdout)
diff --git a/arch/lib/processor.mk b/arch/lib/processor.mk
new file mode 100644
index 0000000..7331528
--- /dev/null
+++ b/arch/lib/processor.mk
@@ -0,0 +1,7 @@
+PROCESSOR=$(shell uname -m)
+PROCESSOR_x86_64=64
+PROCESSOR_i686=32
+PROCESSOR_i586=32
+PROCESSOR_i386=32
+PROCESSOR_i486=32
+PROCESSOR_SIZE=$(PROCESSOR_$(PROCESSOR))
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [RFC PATCH v3 10/10] lib: tools used for test scripts
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (8 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 09/10] lib: libos build scripts and documentation Hajime Tazaki
@ 2015-04-19 13:28     ` Hajime Tazaki
  2015-04-24  7:40     ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Richard Weinberger
  2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-19 13:28 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

These auxiliary files are used for testing and debugging of net/ code
with libos. a simple test is implemented with make test ARCH=lib.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 tools/testing/libos/.gitignore   |  6 +++++
 tools/testing/libos/Makefile     | 38 +++++++++++++++++++++++++++
 tools/testing/libos/README       | 15 +++++++++++
 tools/testing/libos/bisect.sh    | 10 +++++++
 tools/testing/libos/dce-test.sh  | 23 ++++++++++++++++
 tools/testing/libos/nuse-test.sh | 57 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 149 insertions(+)
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

diff --git a/tools/testing/libos/.gitignore b/tools/testing/libos/.gitignore
new file mode 100644
index 0000000..57a74a0
--- /dev/null
+++ b/tools/testing/libos/.gitignore
@@ -0,0 +1,6 @@
+*.pcap
+files-*
+bake
+buildtop
+core
+exitprocs
diff --git a/tools/testing/libos/Makefile b/tools/testing/libos/Makefile
new file mode 100644
index 0000000..3da25429
--- /dev/null
+++ b/tools/testing/libos/Makefile
@@ -0,0 +1,38 @@
+ADD_PARAM?=
+
+all: test
+
+bake:
+	hg clone http://code.nsnam.org/bake
+
+check_pkgs:
+	@./bake/bake.py check | grep Bazaar | grep OK || (echo "bzr is missing" && ./bake/bake.py check)
+	@./bake/bake.py check | grep autoreconf | grep OK || (echo "autotools is missing" && ./bake/bake.py check && exit 1)
+
+testbin: bake check_pkgs
+	@cp ../../../arch/lib/tools/bakeconf-linux.xml bake/bakeconf.xml
+	@mkdir -p buildtop/build/bin_dce
+	cd buildtop ; \
+	../bake/bake.py configure -e dce-linux-inkernel $(BAKECONF_PARAMS)
+	cd buildtop ; \
+	../bake/bake.py show --enabledTree | grep -v  -E "pygoocanvas|graphviz|python-dev" | grep Missing && (echo "required packages are missing") || echo ""
+	cd buildtop ; \
+	../bake/bake.py download ; \
+	../bake/bake.py update ; \
+	../bake/bake.py build
+
+test:
+	@./dce-test.sh ADD_PARAM=$(ADD_PARAM)
+
+test-valgrind:
+	@./dce-test.sh -g ADD_PARAM=$(ADD_PARAM)
+
+test-fault-injection:
+	@./dce-test.sh -f ADD_PARAM=$(ADD_PARAM)
+
+clean:
+#	@rm -rf buildtop
+	@rm -f *.pcap
+	@rm -rf files-*
+	@rm -f exitprocs
+	@rm -f core
diff --git a/tools/testing/libos/README b/tools/testing/libos/README
new file mode 100644
index 0000000..51ac5a5
--- /dev/null
+++ b/tools/testing/libos/README
@@ -0,0 +1,15 @@
+
+- bisect.sh
+a sample script to bisect an issue of network stack code with the help
+of LibOS (and ns-3 network simulator). This was used to detect the issue
+for the following patch.
+
+http://patchwork.ozlabs.org/patch/436351/
+
+- dce-test.sh
+a test script invoked by 'make test ARCH=lib'. The contents of test
+scenario are implemented as test suites of ns-3 network simulator.
+
+- nuse-test.sh
+a simple test script for Network Stack in Userspace (NUSE).
+
diff --git a/tools/testing/libos/bisect.sh b/tools/testing/libos/bisect.sh
new file mode 100755
index 0000000..9377ac3
--- /dev/null
+++ b/tools/testing/libos/bisect.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+git merge origin/nuse --no-commit
+make clean ARCH=lib
+make library ARCH=lib OPT=no
+make test ARCH=lib ADD_PARAM=" -s dce-umip"
+RET=$?
+git reset --hard
+
+exit $RET
diff --git a/tools/testing/libos/dce-test.sh b/tools/testing/libos/dce-test.sh
new file mode 100755
index 0000000..e81e2d8
--- /dev/null
+++ b/tools/testing/libos/dce-test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+#set -x
+export LD_LOG=symbol-fail
+#VERBOSE="-v"
+VALGRIND=""
+FAULT_INJECTION=""
+
+if [ "$1" = "-g" ] ; then
+ VALGRIND="-g"
+# Not implemneted yet.
+#elif [ "$1" = "-f" ] ; then
+# FAULT_INJECTION="-f"
+fi
+
+# FIXME
+#export NS_ATTRIBUTE_DEFAULT='ns3::DceManagerHelper::LoaderFactory=ns3::\
+#DlmLoaderFactory[];ns3::TaskManager::FiberManagerType=UcontextFiberManager'
+
+cd buildtop/source/ns-3-dce
+LD_LIBRARY_PATH=${srctree} ./test.py -n ${VALGRIND} ${FAULT_INJECTION}\
+	   ${VERBOSE} ${ADD_PARAM}
diff --git a/tools/testing/libos/nuse-test.sh b/tools/testing/libos/nuse-test.sh
new file mode 100755
index 0000000..198e7e4
--- /dev/null
+++ b/tools/testing/libos/nuse-test.sh
@@ -0,0 +1,57 @@
+#!/bin/bash -e
+
+LIBOS_TOOLS=arch/lib/tools
+
+IFNAME=`ip route |grep default | awk '{print $5}'`
+GW=`ip route |grep default | awk '{print $3}'`
+#XXX
+IPADDR=`echo $GW | sed -r "s/([0-9]+\.[0-9]+\.[0-9]+\.)([0-9]+)$/\1\`expr \2 + 10\`/"`
+
+# ip route
+# ip address
+# ip link
+
+NUSE_CONF=/tmp/nuse.conf
+
+cat > ${NUSE_CONF} << ENDCONF
+
+interface ${IFNAME}
+	address ${IPADDR}
+	netmask 255.255.255.0
+	macaddr 00:01:01:01:01:02
+	viftype RAW
+
+route
+	network 0.0.0.0
+	netmask 0.0.0.0
+	gateway ${GW}
+
+ENDCONF
+
+cd ${LIBOS_TOOLS}
+sudo NUSECONF=${NUSE_CONF} ./nuse ping 127.0.0.1 -c 2
+
+# rump test
+sudo NUSECONF=${NUSE_CONF} ./nuse sleep 5 &
+
+sleep 2
+PID_SLEEP=`/bin/ls -ltr /tmp/rump-server-nuse.* | tail -1 | awk '{print $9}' | sed -e "s/.*rump-server-nuse\.//g" | sed "s/=//"`
+RUMP_URL=unix:///tmp/rump-server-nuse.$PID_SLEEP
+# ls -ltr /tmp/*
+
+sudo chmod 777 /tmp/rump-server-nuse.$PID_SLEEP
+LD_PRELOAD=./libnuse-hijack.so  RUMPHIJACK=socket=all \
+    RUMP_SERVER=$RUMP_URL ip addr show
+
+wait %1
+
+if [ "$1" == "--extended" ] ; then
+sudo NUSECONF=${NUSE_CONF} ./nuse ping ${GW} -c 2
+sudo NUSECONF=${NUSE_CONF} ./nuse iperf -c ${GW} -p 2000 -t 3
+sudo NUSECONF=${NUSE_CONF} ./nuse iperf -c ${GW} -p 8 -u -t 3
+sudo NUSECONF=${NUSE_CONF} ./nuse dig www.google.com
+sudo NUSECONF=${NUSE_CONF} ./nuse host www.google.com
+sudo NUSECONF=${NUSE_CONF} ./nuse nslookup www.google.com
+#sudo NUSECONF=${NUSE_CONF} ./nuse nc www.google.com 80
+sudo NUSECONF=${NUSE_CONF} ./nuse wget www.google.com -O -
+fi
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v3 09/10] lib: libos build scripts and documentation
  2015-04-19 13:28     ` [RFC PATCH v3 09/10] lib: libos build scripts and documentation Hajime Tazaki
@ 2015-04-20 20:43       ` Paul Bolle
  2015-04-22  5:33         ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Paul Bolle @ 2015-04-20 20:43 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

Some random observations while I'm still trying to wrap my head around
all this (which might take quite some time).

On Sun, 2015-04-19 at 22:28 +0900, Hajime Tazaki wrote:
> --- /dev/null
> +++ b/arch/lib/Kconfig
> @@ -0,0 +1,124 @@
> +menuconfig LIB
> +       bool "LibOS-specific options"
> +       def_bool n

This is the start of the Kconfig parse for lib. (That would basically
still be true even if you didn't set KBUILD_KCONFIG, see below.) So why
not do something like all arches do:

config LIB
	def_bool y
	select [...]

Ie, why would someone want to build for ARCH=lib and still not set LIB?

> +       select PROC_FS
> +       select PROC_SYSCTL
> +       select SYSCTL
> +       select SYSFS
> +       help
> +          The 'lib' architecture is a library (user-mode) version of
> +          the linux kernel that includes only its network stack and is
> +	  used within the userspace application, and ns-3 simulator.
> +	  For more information, about ns-3, see http://www.nsnam.org.
> +
> +config EXPERIMENTAL
> +	def_bool y

Unneeded: removed treewide in, I think, 2014.

> +config MMU
> +        def_bool n

Add empty line.

> +config FPU
> +        def_bool n

Ditto.

> +config SMP
> +        def_bool n
> +
> +config ARCH
> +	string
> +	option env="ARCH"
> +
> +config KTIME_SCALAR
> +       def_bool y

This one is unused.

> +config MODULES
> +       def_bool y
> +       option modules
> +
> +config GENERIC_CSUM
> +	def_bool y
> +
> +config GENERIC_BUG
> +	def_bool y
> +	depends on BUG

Add empty line here.

> +config PRINTK
> +       def_bool y
> +
> +config RWSEM_GENERIC_SPINLOCK
> +	def_bool y
> +
> +config GENERIC_FIND_NEXT_BIT
> +	def_bool y

This one is unused too.

> +config GENERIC_HWEIGHT
> +       def_bool y
> +
> +config TRACE_IRQFLAGS_SUPPORT
> +	def_bool y
> +
> +config NO_HZ
> +	def_bool y
> +
> +config BASE_FULL
> +       def_bool n
> +
> +config SELECT_MEMORY_MODEL
> +       def_bool n
> +
> +config FLAT_NODE_MEM_MAP
> +       def_bool n
> +
> +config PAGEFLAGS_EXTENDED
> +       def_bool n
> +
> +config VIRT_TO_BUS
> +       def_bool n
> +
> +config HAS_DMA
> +       def_bool n
> +
> +config HZ
> +        int
> +        default 250
> +
> +config TINY_RCU
> +       def_bool y
> +
> +config HZ_250
> +       def_bool y
> +
> +config BASE_SMALL
> +       int
> +       default 1
> +
> +config SPLIT_PTLOCK_CPUS
> +       int
> +       default 1
> +
> +config FLATMEM
> +       def_bool y
> +
> +config SYSCTL
> +       def_bool y
> +
> +config PROC_FS
> +       def_bool y
> +
> +config SYSFS
> +       def_bool y
> +
> +config PROC_SYSCTL
> +       def_bool y
> +
> +config NETDEVICES
> +       def_bool y
> +
> +config SLIB
> +       def_bool y

You've also added SLIB to init/Kconfig in 02/10. But "make ARCH=lib
*config" will never visit init/Kconfig, will it? And, apparently, none
of SL[AOU]B are wanted for lib. So I think the entry for config SLIB in
that file can be dropped (as other arches will never see it because it
depends on LIB).

(Note that I haven't actually looked into all the Kconfig entries added
above. Perhaps I might do that. But I'm pretty sure most of the time all
I can say is: "I have no idea why this entry defaults to $VALUE".)

> +source "net/Kconfig"
> +
> +source "drivers/base/Kconfig"
> +
> +source "crypto/Kconfig"
> +
> +source "lib/Kconfig"
> +
> +

Trailing empty lines.

> diff --git a/arch/lib/Makefile b/arch/lib/Makefile
> new file mode 100644
> index 0000000..d8a0bf9
> --- /dev/null
> +++ b/arch/lib/Makefile
> @@ -0,0 +1,251 @@
> +ARCH_DIR := arch/lib
> +SRCDIR=$(dir $(firstword $(MAKEFILE_LIST)))

Do you use SRCDIR?

> +DCE_TESTDIR=$(srctree)/tools/testing/libos/
> +KBUILD_KCONFIG := arch/$(ARCH)/Kconfig

I think you copied this from arch/um/Makefile. But arch/um/ is, well,
special. Why should lib not start the kconfig parse in the file named
Kconfig? And if you want to start in arch/lib/Kconfig, it would be nice
to add a mainmenu (just like arch/x86/um/Kconfig does).

(I don't read Makefilese well enough to understand the rest of this
file. I think it's scary.)

> +
> +CC = gcc
> +GCCVERSIONGTEQ48 := $(shell expr `gcc -dumpversion` \>= 4.8)
> +ifeq "$(GCCVERSIONGTEQ48)" "1"
> +   NO_TREE_LOOP_OPT += -fno-tree-loop-distribute-patterns
> +endif
> +
> +
> +-include $(ARCH_DIR)/objs.mk
> +-include $(srctree)/.config
> +include $(srctree)/scripts/Kbuild.include
> +include $(ARCH_DIR)/processor.mk
> +
> +# targets
> +LIBOS_TOOLS=$(ARCH_DIR)/tools
> +LIBOS_GIT_REPO=git://github.com/libos-nuse/linux-libos-tools
> +KERNEL_LIB=liblinux-$(KERNELVERSION).so
> +
> +ALL_OBJS=$(OBJS) $(KERNEL_LIB) $(modules) $(all-obj-for-clean)
> +
> +# auto generated files
> +AUTOGENS=$(CRC32TABLE) $(COMPILE_H) $(BOUNDS_H) $(ARCH_DIR)/timeconst.h $(ARCH_DIR)/linker.lds
> +COMPILE_H=$(srctree)/include/generated/compile.h
> +BOUNDS_H=$(srctree)/include/generated/bounds.h
> +
> +# from lib/Makefile
> +CRC32TABLE = $(ARCH_DIR)/crc32table.h
> +hostprogs-y	:= $(srctree)/lib/gen_crc32table
> +clean-files	:= crc32table.h
> +
> +# sources and objects
> +LIB_SRC=\
> +lib.c lib-device.c lib-socket.c random.c softirq.c time.c \
> +timer.c hrtimer.c sched.c workqueue.c \
> +print.c tasklet.c tasklet-hrtimer.c \
> +glue.c fs.c sysctl.c proc.c sysfs.c \
> +capability.c pid.c modules.c filemap.c vmscan.c
> +
> +LIB_OBJ=$(addprefix $(ARCH_DIR)/,$(addsuffix .o,$(basename $(LIB_SRC))))
> +LIB_DEPS=$(addprefix $(ARCH_DIR)/.,$(addsuffix .o.cmd,$(basename $(LIB_SRC))))
> +-include $(LIB_DEPS)
> +
> +DEPENDS=$(addprefix $(ARCH_DIR)/.,\
> +	$(addsuffix .d,$(basename $(LIB_SRC)))\
> +	)
> +
> +# options
> +COV?=no
> +cov_yes=-fprofile-arcs -ftest-coverage
> +cov_no=
> +covl_yes=-fprofile-arcs
> +covl_no=
> +OPT?=yes
> +opt_yes=-O3 -fomit-frame-pointer $(NO_TREE_LOOP_OPT)
> +opt_no=-O0
> +PIC?=yes
> +pic_yes=-fpic -DPIC
> +pic_no=-mcmodel=large
> +PIC_CFLAGS=$(pic_$(PIC))
> +
> +# flags
> +CFLAGS_USPACE= \
> + -Wp,-MD,$(depfile) $(opt_$(OPT)) -g3 -Wall -Wstrict-prototypes -Wno-trigraphs \
> + -fno-inline -fno-strict-aliasing -fno-common \
> + -fno-delete-null-pointer-checks -fno-builtin \
> + -fno-stack-protector -Wno-unused -Wno-pointer-sign \
> + $(PIC_CFLAGS) -D_DEBUG $(cov_$(COV)) -I$(ARCH_DIR)/include
> +
> +CFLAGS+= \
> + $(CFLAGS_USPACE) -nostdinc -D__KERNEL__ -iwithprefix $(srctree)/include \
> + -DKBUILD_BASENAME=\"clnt\" -DKBUILD_MODNAME=\"nsc\" -DMODVERSIONS \
> + -DEXPORT_SYMTAB \
> + -U__FreeBSD__ -D__linux__=1 -Dlinux=1 -D__linux=1 \
> + -DCONFIG_DEFAULT_HOSTNAME=\"lib\" \
> + -I$(ARCH_DIR)/include/generated/uapi \
> + -I$(ARCH_DIR)/include/generated \
> + -I$(srctree)/include -I$(ARCH_DIR)/include/uapi \
> + -I$(srctree)/include/uapi -I$(srctree)/include/generated/uapi \
> + -include $(srctree)/include/linux/kconfig.h \
> + -I$(ARCH_DIR) -I.
> +
> +ifeq ($(PROCESSOR_SIZE),64)
> +CFLAGS+= -DCONFIG_64BIT
> +endif
> +
> +LDFLAGS += -shared -nodefaultlibs -g3 -Wl,-O1 -Wl,-T$(ARCH_DIR)/linker.lds $(covl_$(COV))
> +
> +# targets
> +
> +modules:=
> +all-obj-for-clean:=
> +
> +all: library modules
> +
> +# note: the directory order below matters to ensure that we match the kernel order
> +dirs=kernel/ kernel/time/ kernel/rcu/ kernel/locking/ kernel/bpf/ mm/ fs/ fs/proc/ crypto/ lib/ drivers/base/ drivers/net/ net/ init/
> +empty:=
> +space:= $(empty) $(empty)
> +colon:= :
> +comma= ,
> +kernel/_to_keep=notifier.o params.o sysctl.o \
> +rwsem.o semaphore.o kfifo.o cred.o user.o groups.o ksysfs.o
> +kernel/time/_to_keep=time.o
> +kernel/rcu_to_keep=rcu/srcu.o rcu/pdate.o rcu/tiny.o
> +kernel/locking_to_keep=locking/mutex.o
> +kernel/bpf_to_keep=bpf/core.o
> +mm/_to_keep=util.o list_lru.o slib.o
> +crypto/_to_keep=aead.o ahash.o shash.o api.o algapi.o cipher.o compress.o proc.o \
> +crc32c_generic.o
> +drivers/base/_to_keep=class.o core.o bus.o dd.o driver.o devres.o module.o map.o
> +drivers/net/_to_keep=loopback.o
> +lib/_to_keep=klist.o kobject.o kref.o hweight.o int_sqrt.o checksum.o \
> +find_last_bit.o find_next_bit.o bitmap.o nlattr.o idr.o libcrc32c.o \
> +ctype.o string.o kasprintf.o rbtree.o sha1.o textsearch.o vsprintf.o \
> +rwsem-spinlock.o scatterlist.o ratelimit.o hexdump.o dec_and_lock.o \
> +div64.o dynamic_queue_limits.o md5.o kstrtox.o iovec.o lockref.o crc32.o \
> +rhashtable.o iov_iter.o cmdline.o kobject_uevent.o
> +fs/_to_keep=read_write.o libfs.o namei.o filesystems.o file.o file_table.o \
> +dcache.o inode.o pipe.o char_dev.o splice.o no-block.o seq_file.o super.o \
> +fcntl.o coredump.o
> +fs/proc/_to_keep=proc_sysctl.o proc_net.o root.o generic.o inode.o
> +init/_to_keep=version.o
> +
> +quiet_cmd_objsmk = OBJS-MK   $@
> +      cmd_objsmk = \
> +	for i in 1; do \
> +	$(foreach d,$(dirs), \
> +           $(MAKE) -i -s -f $< srcdir=$(srctree)/$(d) \
> +	    objdir=$(srctree)/$(d) \
> +            config=$(srctree)/.config \
> +	    to_keep=$(subst $(space),$(colon),$($(d)_to_keep)) print;) \
> +	done > $@
> +
> +$(ARCH_DIR)/objs.mk: $(ARCH_DIR)/Makefile.print $(srctree)/.config $(ARCH_DIR)/Makefile
> +	+$(call if_changed,objsmk)
> +
> +quiet_cmd_timeconst = GEN     $@
> +      cmd_timeconst = echo "hz=$(CONFIG_HZ)" > $(ARCH_DIR)/hz.bc ; \
> +                      bc $(ARCH_DIR)/hz.bc kernel/time/timeconst.bc > $@
> +$(ARCH_DIR)/timeconst.h: $(srctree)/.config
> +	$(call if_changed,timeconst)
> +
> +quiet_cmd_linker = GEN     $@
> +      cmd_linker = ld -shared --verbose | ./$^ > $@
> +$(ARCH_DIR)/linker.lds: $(ARCH_DIR)/generate-linker-script.py
> +	$(call if_changed,linker)
> +
> +quiet_cmd_crc32src = GEN     $@
> +      cmd_crc32src = $(MAKE) -f $(srctree)/Makefile silentoldconfig ; \
> +                     cc $^ -o $@
> +$(srctree)/lib/gen_crc32table: $(srctree)/lib/gen_crc32table.c
> +	$(call if_changed,crc32src)
> +
> +quiet_cmd_crc32 = GEN     $@
> +      cmd_crc32 = $< > $@
> +
> +$(CRC32TABLE): $(srctree)/lib/gen_crc32table
> +	$(call if_changed,crc32)
> +
> +# copied from init/Makefile
> +       chk_compile.h = :
> + quiet_chk_compile.h = echo '  CHK     $@'
> +silent_chk_compile.h = :
> +$(COMPILE_H): include/generated/utsrelease.h asm-generic $(version_h)
> +	@$($(quiet)chk_compile.h)
> +	+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
> +	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
> +
> +# crafted from $(srctree)/Kbuild
> +quiet_cmd_lib_bounds = GEN     $@
> +define cmd_lib_bounds
> +	(set -e; \
> +	 echo "#ifndef GENERATED_BOUNDS_H"; \
> +	 echo "#define GENERATED_BOUNDS_H"; \
> +	 echo ""; \
> +	 echo "#define NR_PAGEFLAGS (__NR_PAGEFLAGS)"; \
> +	 echo "#define MAX_NR_ZONES (__MAX_NR_ZONES)"; \
> +	 echo ""; \
> +	 echo "#endif /* GENERATED_BOUNDS_H */") > $@
> +endef
> +
> +$(BOUNDS_H):
> +	$(Q)mkdir -p $(dir $@)
> +	$(call cmd,lib_bounds)
> +
> +
> +KERNEL_BUILTIN=$(addprefix $(srctree)/,$(addsuffix builtin.o,$(dirs)))
> +OBJS=$(LIB_OBJ) $(foreach builtin,$(KERNEL_BUILTIN),$(if $($(builtin)),$($(builtin))))
> +export OBJS KERNEL_LIB COV covl_yes covl_no
> +
> +quiet_cmd_cc = CC      $@
> +      cmd_cc = 	mkdir -p $(dir $@);	\
> +		$(CC) $(CFLAGS) -c $< -o $@
> +quiet_cmd_linkko = KO   $@
> +      cmd_linkko = $(CC) -shared -o $@ -nostdlib $^
> +quiet_cmd_builtin = BUILTIN   $@
> +      cmd_builtin = mkdir -p $(dir $(srctree)/$@); rm -f $(srctree)/$@; \
> +		    if test -n "$($(srctree)/$@)"; then for f in $($(srctree)/$@); \
> +		    do $(AR) Tcru $@ $$f; done; else $(AR) Tcru $@; fi
> +
> +%/builtin.o:
> +	$(call if_changed,builtin)
> +%.ko:%.o
> +	$(call if_changed,linkko)
> +%.o:%.c
> +	$(call if_changed_dep,cc)
> +
> +library: $(KERNEL_LIB) $(LIBOS_TOOLS)
> +modules: $(modules)
> +
> +$(LIBOS_TOOLS): $(KERNEL_LIB) Makefile FORCE
> +	$(Q) if [ ! -d "$@" ]; then \
> +		git clone $(LIBOS_GIT_REPO) $@ ;\
> +	fi
> +	$(Q) $(MAKE) -C $(LIBOS_TOOLS)
> +
> +install: modules library
> +
> +install-dir:
> +
> +$(KERNEL_LIB): $(ARCH_DIR)/objs.mk $(AUTOGENS) $(OBJS)
> +	$(call if_changed,linklib)
> +
> +quiet_cmd_linklib = LIB     $@
> +      cmd_linklib = $(CC) -Wl,--whole-archive $(OBJS) $(LDFLAGS) -o $@; \
> +		    ln -s -f $(KERNEL_LIB) liblinux.so
> +
> +quiet_cmd_clean = CLEAN   $@
> +      cmd_clean = for f in $(foreach m,$(modules),$($(m))) ; do rm -f $$f 2>/dev/null; done ; \
> +		  for f in $(ALL_OBJS); do rm -f $$f; done 2>/dev/null ;\
> +		  rm -rf $(AUTOGENS) $(ARCH_DIR)/objs.mk 2>/dev/null ;\
> +		  if [ -d $(LIBOS_TOOLS) ]; then $(MAKE) -C $(LIBOS_TOOLS) clean ; fi
> +
> +archclean:
> +	$(call if_changed,clean)
> +
> +.%.d:%.c $(srctree)/.config
> +	$(Q) set -e; $(CC) -MM -MT $(<:.c=.o) $(CFLAGS) $< > $@
> +
> +deplib: $(DEPENDS)
> +	-include $(DEPENDS)
> +
> +test:
> +	$(Q) $(MAKE) -C $(DCE_TESTDIR)/
> +
> +.PHONY : clean deplib
> +
> diff --git a/arch/lib/Makefile.print b/arch/lib/Makefile.print
> new file mode 100644
> index 0000000..40e6db0
> --- /dev/null
> +++ b/arch/lib/Makefile.print
> @@ -0,0 +1,45 @@
> +# inherit $(objdir) $(config) $(srcdir) $(to_keep) from command-line
> +
> +include $(config)
> +include $(srcdir)Makefile
> +
> +# fix minor nits for make version dependencies
> +ifeq (3.82,$(firstword $(sort $(MAKE_VERSION) 3.82)))
> +  SEPARATOR=
> +else
> +  SEPARATOR=/
> +endif
> +
> +to_keep_list=$(subst :, ,$(to_keep))
> +obj-y += $(lib-y)
> +obj-m += $(lib-m)
> +subdirs := $(filter %/, $(obj-y) $(obj-m))
> +subdirs-y := $(filter %/, $(obj-y))
> +subdirs-m := $(filter %/, $(obj-m))
> +tmp1-obj-y=$(patsubst %/,%/builtin.o,$(obj-y))
> +tmp1-obj-m=$(filter-out $(subdirs-m),$(obj-m))
> +tmp2-obj-y=$(foreach m,$(tmp1-obj-y), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
> +tmp2-obj-m=$(foreach m,$(tmp1-obj-m), $(if $($(m:.o=-objs)),$($(m:.o=-objs)),$(if $($(m:.o=-y)),$($(m:.o=-y)),$(m))))
> +tmp3-obj-y=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-y)),$(tmp2-obj-y))
> +tmp3-obj-m=$(if $(to_keep_list),$(filter $(to_keep_list),$(tmp2-obj-m)),$(tmp2-obj-m))
> +final-obj-y=$(tmp3-obj-y)
> +final-obj-m=$(tmp3-obj-m)
> +
> +print: $(final-obj-m) $(subdirs)
> +	@if test $(if $(final-obj-y),1); then \
> +	  echo -n $(objdir)builtin.o; echo -n "="; echo $(addprefix $(objdir),$(final-obj-y)); \
> +	  echo -n $(objdir)builtin.o; echo -n ": "; echo $(addprefix $(objdir),$(final-obj-y)); \
> +          echo -n "-include "; echo $(addprefix $(objdir).,$(addsuffix ".cmd", $(final-obj-y))); \
> +	  echo -n "all-obj-for-clean+="; echo $(addprefix $(objdir),$(final-obj-y)) $(objdir)builtin.o; \
> +	fi
> +$(final-obj-m):
> +	@echo -n "modules+="; echo $(addprefix $(objdir),$(@:.o=.ko))
> +	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n ": "
> +	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
> +	@echo -n $(addprefix $(objdir),$(@:.o=.ko)); echo -n "="
> +	@echo $(addprefix $(objdir),$(if $($(@:.o=-objs)),$($(@:.o=-objs)),$@))
> +$(subdirs):
> +	@$(MAKE) -s -f $(firstword $(MAKEFILE_LIST)) objdir=$(objdir)$@$(SEPARATOR) config=$(config) srcdir=$(srcdir)$@$(SEPARATOR) to_keep=$(to_keep) print 2>/dev/null

When I did
    make ARCH=lib menuconfig

I saw (among other things):
    arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `lzo/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `lz4/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `lz4/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
    arch/lib/Makefile.print:41: target `slip/' given more than once in the same rule.

I have no idea why. Unclean tree?

> +.PHONY : core
> +.NOTPARALLEL : print $(subdirs) $(final-obj-m)

> --- /dev/null
> +++ b/arch/lib/processor.mk
> @@ -0,0 +1,7 @@
> +PROCESSOR=$(shell uname -m)
> +PROCESSOR_x86_64=64
> +PROCESSOR_i686=32
> +PROCESSOR_i586=32
> +PROCESSOR_i386=32
> +PROCESSOR_i486=32
> +PROCESSOR_SIZE=$(PROCESSOR_$(PROCESSOR))

The rest of the tree appears to use BITS instead of PROCESSOR_SIZE. And
I do hope there's a cleaner way for lib to set PROCESSOR_SIZE than this.

Thanks,


Paul Bolle


^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v3 09/10] lib: libos build scripts and documentation
  2015-04-20 20:43       ` Paul Bolle
@ 2015-04-22  5:33         ` Hajime Tazaki
  0 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-22  5:33 UTC (permalink / raw)
  To: pebolle
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, richard,
	rusty, upa, christoph.paasch, mathieu.lacage, libos-nuse


Hi Paul,

many thanks for your review. 

all the fixes will be on next patchset.
my comments are below.

At Mon, 20 Apr 2015 22:43:07 +0200,
Paul Bolle wrote:
> 
> Some random observations while I'm still trying to wrap my head around
> all this (which might take quite some time).
> 
> On Sun, 2015-04-19 at 22:28 +0900, Hajime Tazaki wrote:
> > --- /dev/null
> > +++ b/arch/lib/Kconfig
> > @@ -0,0 +1,124 @@
> > +menuconfig LIB
> > +       bool "LibOS-specific options"
> > +       def_bool n
> 
> This is the start of the Kconfig parse for lib. (That would basically
> still be true even if you didn't set KBUILD_KCONFIG, see below.) So why
> not do something like all arches do:
> 
> config LIB
> 	def_bool y
> 	select [...]
> 
> Ie, why would someone want to build for ARCH=lib and still not set LIB?

agreed. fixed.

> > +config EXPERIMENTAL
> > +	def_bool y
> 
> Unneeded: removed treewide in, I think, 2014.

thanks. fixed.

> > +config MMU
> > +        def_bool n
> 
> Add empty line.
> 
> > +config FPU
> > +        def_bool n
> 
> Ditto.

both are fixed.

> > +config KTIME_SCALAR
> > +       def_bool y
> 
> This one is unused.

deleted.

> > +config GENERIC_BUG
> > +	def_bool y
> > +	depends on BUG
> 
> Add empty line here.

fixed.

> > +config GENERIC_FIND_NEXT_BIT
> > +	def_bool y
> 
> This one is unused too.

deleted.

> > +config SLIB
> > +       def_bool y
> 
> You've also added SLIB to init/Kconfig in 02/10. But "make ARCH=lib
> *config" will never visit init/Kconfig, will it? And, apparently, none
> of SL[AOU]B are wanted for lib. So I think the entry for config SLIB in
> that file can be dropped (as other arches will never see it because it
> depends on LIB).
> 
> (Note that I haven't actually looked into all the Kconfig entries added
> above. Perhaps I might do that. But I'm pretty sure most of the time all
> I can say is: "I have no idea why this entry defaults to $VALUE".)

I intended to SLIB be a generic one, not only for the
arch/lib, as we discussed during v2 patch. 

but, you're right: for the moment, no one uses SLIB, we
don't visit init/Kconfig, I dropped config SLIB entry from
init/Kconfig.

> > +source "net/Kconfig"
> > +
> > +source "drivers/base/Kconfig"
> > +
> > +source "crypto/Kconfig"
> > +
> > +source "lib/Kconfig"
> > +
> > +
> 
> Trailing empty lines.

deleted. thanks.

> > diff --git a/arch/lib/Makefile b/arch/lib/Makefile
> > new file mode 100644
> > index 0000000..d8a0bf9
> > --- /dev/null
> > +++ b/arch/lib/Makefile
> > @@ -0,0 +1,251 @@
> > +ARCH_DIR := arch/lib
> > +SRCDIR=$(dir $(firstword $(MAKEFILE_LIST)))
> 
> Do you use SRCDIR?

no. deleted the line.

> > +DCE_TESTDIR=$(srctree)/tools/testing/libos/
> > +KBUILD_KCONFIG := arch/$(ARCH)/Kconfig
> 
> I think you copied this from arch/um/Makefile. But arch/um/ is, well,
> special. Why should lib not start the kconfig parse in the file named
> Kconfig? And if you want to start in arch/lib/Kconfig, it would be nice
> to add a mainmenu (just like arch/x86/um/Kconfig does).

right now, 'lib' only wants to eat arch/lib/Kconfig so that
build and link its wanted files instead of configurable one.

so I beilive arch/lib is also special as arch/um is.

I added a mainmenu btw. thanks.

> (I don't read Makefilese well enough to understand the rest of this
> file. I think it's scary.)

indeed. thank you again to review the cryptic files..

> When I did
>     make ARCH=lib menuconfig
> 
> I saw (among other things):
>     arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
>     arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
>     arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
>     arch/lib/Makefile.print:41: target `trace/' given more than once in the same rule.
>     arch/lib/Makefile.print:41: target `lzo/' given more than once in the same rule.
(snip)
>     arch/lib/Makefile.print:41: target `ppp/' given more than once in the same rule.
>     arch/lib/Makefile.print:41: target `slip/' given more than once in the same rule.
> 
> I have no idea why. Unclean tree?

this was due to inappropriate handling of the internal
directory listing procedure. fixed.

> > +.PHONY : core
> > +.NOTPARALLEL : print $(subdirs) $(final-obj-m)
> 
> > --- /dev/null
> > +++ b/arch/lib/processor.mk
> > @@ -0,0 +1,7 @@
> > +PROCESSOR=$(shell uname -m)
> > +PROCESSOR_x86_64=64
> > +PROCESSOR_i686=32
> > +PROCESSOR_i586=32
> > +PROCESSOR_i386=32
> > +PROCESSOR_i486=32
> > +PROCESSOR_SIZE=$(PROCESSOR_$(PROCESSOR))
> 
> The rest of the tree appears to use BITS instead of PROCESSOR_SIZE. And
> I do hope there's a cleaner way for lib to set PROCESSOR_SIZE than this.

the variable PROCESSOR_SIZE is only used by
arch/lib/Makefile, with the following lines.

> +ifeq ($(PROCESSOR_SIZE),64)
> +CFLAGS+= -DCONFIG_64BIT
> +endif

Thus it eventually uses CONFIG_64BIT.

I think a cleaner way is to follow the way of arch/um, like
below: I deleted processor.mk and PROCESSOR_SIZE variable.

ifeq ($(SUBARCH),x86)
  ifeq ($(shell uname -m),x86_64)
	CFLAGS+= -DCONFIG_64BIT
endif

though it's not able to cross-compile yet.

again, thank you so much.
I'll be back very soon (v4 patch).

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS)
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (9 preceding siblings ...)
  2015-04-19 13:28     ` [RFC PATCH v3 10/10] lib: tools used for test scripts Hajime Tazaki
@ 2015-04-24  7:40     ` Richard Weinberger
  2015-04-24  8:22       ` Hajime Tazaki
  2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
  11 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-04-24  7:40 UTC (permalink / raw)
  To: Hajime Tazaki, linux-arch
  Cc: Arnd Bergmann, Jonathan Corbet, Christoph Lameter, Jekka Enberg,
	Javid Rientjes, Joonsoo Kim, Jndrew Morton, linux-kernel,
	linux-doc, netdev, linux-mm, Jeff Dike, Rusty Russell,
	Ryo Nakamura, Christoph Paasch, Mathieu Lacage, libos-nuse

Hi!

Am 19.04.2015 um 15:28 schrieb Hajime Tazaki:
> changes from v2:
> - Patch 02/11 ("slab: add private memory allocator header for arch/lib")
> * add new allocator named SLIB (Library Allocator): Patch 04/11 is integrated
>   to 02 (commented by Christoph Lameter)
> - Overall
> * rewrite commit log messages
> 
> changes from v1:
> - Patch 01/11 ("sysctl: make some functions unstatic to access by arch/lib"):
> * add prefix ctl_table_ to newly publiced functions (commented by Joe Perches)
> - Patch 08/11 ("lib: other kernel glue layer code"):
> * significantly reduce glue codes (stubs) (commented by Richard Weinberger)
> - Others
> * adapt to linux-4.0.0
> * detect make dependency by Kbuild .cmd files

I still fail to build it. :-(

for-asm-upstream-v3 on top of Linus' tree gives:

rw@sandpuppy:~/linux (libos $)> make library ARCH=lib
  OBJS-MK   arch/lib/objs.mk
arch/lib/Makefile.print:41: target 'lzo/' given more than once in the same rule.
make[2]: Nothing to be done for '.config'.
scripts/kconfig/conf  --silentoldconfig arch/lib/Kconfig
  CHK     include/config/kernel.release
  CHK     include/generated/utsrelease.h
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/compile.h
  GEN     arch/lib/timeconst.h
  GEN     arch/lib/linker.lds
  CC      arch/lib/lib.o
  CC      arch/lib/lib-device.o
  CC      arch/lib/lib-socket.o
  CC      arch/lib/random.o
  CC      arch/lib/softirq.o
  CC      arch/lib/time.o
  CC      arch/lib/timer.o
  CC      arch/lib/hrtimer.o
  CC      arch/lib/sched.o
  CC      arch/lib/workqueue.o
  CC      arch/lib/print.o
  CC      arch/lib/tasklet.o
  CC      arch/lib/tasklet-hrtimer.o
  CC      arch/lib/glue.o
  CC      arch/lib/fs.o
  CC      arch/lib/sysctl.o
  CC      arch/lib/proc.o
  CC      arch/lib/sysfs.o
  CC      arch/lib/capability.o
arch/lib/capability.c:16:6: error: redefinition of ‘capable’
 bool capable(int cap)
      ^
In file included from arch/lib/capability.c:9:0:
./include/linux/capability.h:236:20: note: previous definition of ‘capable’ was here
 static inline bool capable(int cap)
                    ^
arch/lib/capability.c:39:6: error: redefinition of ‘ns_capable’
 bool ns_capable(struct user_namespace *ns, int cap)
      ^
In file included from arch/lib/capability.c:9:0:
./include/linux/capability.h:240:20: note: previous definition of ‘ns_capable’ was here
 static inline bool ns_capable(struct user_namespace *ns, int cap)
                    ^
arch/lib/Makefile:210: recipe for target 'arch/lib/capability.o' failed
make: *** [arch/lib/capability.o] Error 1

And on top of v4.0 it fails too:

rw@sandpuppy:~/linux (libos-v4.0 $)> make library ARCH=lib
  OBJS-MK   arch/lib/objs.mk
arch/lib/Makefile.print:41: target 'lzo/' given more than once in the same rule.
make[2]: Nothing to be done for '.config'.
scripts/kconfig/conf --silentoldconfig arch/lib/Kconfig
  CHK     include/config/kernel.release
  CHK     include/generated/utsrelease.h
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/compile.h
  GEN     arch/lib/timeconst.h
  GEN     arch/lib/linker.lds
  CC      arch/lib/lib.o
  CC      arch/lib/lib-device.o
  CC      arch/lib/lib-socket.o
arch/lib/lib-socket.c: In function ‘lib_sock_sendmsg’:
arch/lib/lib-socket.c:114:2: error: too few arguments to function ‘sock_sendmsg’
  retval = sock_sendmsg(kernel_socket, &msg_sys);
  ^
In file included from arch/lib/lib-socket.c:12:0:
./include/linux/net.h:216:5: note: declared here
 int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len);
     ^
arch/lib/Makefile:210: recipe for target 'arch/lib/lib-socket.o' failed
make: *** [arch/lib/lib-socket.o] Error 1

You *really* need to shape up wrt the build process.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS)
  2015-04-24  7:40     ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Richard Weinberger
@ 2015-04-24  8:22       ` Hajime Tazaki
  2015-04-24  8:59         ` Richard Weinberger
  0 siblings, 1 reply; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-24  8:22 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	upa, christoph.paasch, mathieu.lacage, libos-nuse


Hi Richard,

At Fri, 24 Apr 2015 09:40:32 +0200,
Richard Weinberger wrote:
> 
> Hi!
> 
> Am 19.04.2015 um 15:28 schrieb Hajime Tazaki:
> > changes from v2:
> > - Patch 02/11 ("slab: add private memory allocator header for arch/lib")
> > * add new allocator named SLIB (Library Allocator): Patch 04/11 is integrated
> >   to 02 (commented by Christoph Lameter)
> > - Overall
> > * rewrite commit log messages
> > 
> > changes from v1:
> > - Patch 01/11 ("sysctl: make some functions unstatic to access by arch/lib"):
> > * add prefix ctl_table_ to newly publiced functions (commented by Joe Perches)
> > - Patch 08/11 ("lib: other kernel glue layer code"):
> > * significantly reduce glue codes (stubs) (commented by Richard Weinberger)
> > - Others
> > * adapt to linux-4.0.0
> > * detect make dependency by Kbuild .cmd files
> 
> I still fail to build it. :-(
> 
> for-asm-upstream-v3 on top of Linus' tree gives:
(snip)
> arch/lib/Makefile:210: recipe for target 'arch/lib/capability.o' failed
> make: *** [arch/lib/capability.o] Error 1

I'm also aware of and already fixed this issue for pre-v4
patch of libos.

> And on top of v4.0 it fails too:
(snip)
> In file included from arch/lib/lib-socket.c:12:0:
> ./include/linux/net.h:216:5: note: declared here
>  int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len);
>      ^
> arch/lib/Makefile:210: recipe for target 'arch/lib/lib-socket.o' failed
> make: *** [arch/lib/lib-socket.o] Error 1

since tag v4.0 to libos v3 patch, there is an update on the
sock_sendmsg(): v3 patch already followed the change. that's
why the patch can't build on top of v4.0.

> You *really* need to shape up wrt the build process.

at the moment, the implementation of libos can't automate to
follow such changes in the build process. but good news is
it's a trivial task to follow up the latest function.

my observation on this manual follow up since around 3.7
kernel (2.5 yrs ago) is that these changes mostly happened
during merge-window of each new version, and the fix only
takes a couple of hours at maximum.

I think I can survive with these changes but I'd like to ask
broader opinions.


one more question:

I'd really like to have a suggestion on which tree I should
base for libos tree.

I'm proposing a patchset to arnd/asm-generic tree (which I
believe the base tree for new arch/), while the patchset is
tested with davem/net-next tree because right now libos is
only for net/.

shall I propose a patchset based on Linus' tree instead ?

thank you for your feedback.

-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS)
  2015-04-24  8:22       ` Hajime Tazaki
@ 2015-04-24  8:59         ` Richard Weinberger
  2015-04-24  9:50           ` Hajime Tazaki
  0 siblings, 1 reply; 117+ messages in thread
From: Richard Weinberger @ 2015-04-24  8:59 UTC (permalink / raw)
  To: Hajime Tazaki
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	upa, christoph.paasch, mathieu.lacage, libos-nuse

Hi!

Am 24.04.2015 um 10:22 schrieb Hajime Tazaki:
>> You *really* need to shape up wrt the build process.
> 
> at the moment, the implementation of libos can't automate to
> follow such changes in the build process. but good news is
> it's a trivial task to follow up the latest function.
> 
> my observation on this manual follow up since around 3.7
> kernel (2.5 yrs ago) is that these changes mostly happened
> during merge-window of each new version, and the fix only
> takes a couple of hours at maximum.
> 
> I think I can survive with these changes but I'd like to ask
> broader opinions.
> 
> 
> one more question:
> 
> I'd really like to have a suggestion on which tree I should
> base for libos tree.
> 
> I'm proposing a patchset to arnd/asm-generic tree (which I
> believe the base tree for new arch/), while the patchset is
> tested with davem/net-next tree because right now libos is
> only for net/.
> 
> shall I propose a patchset based on Linus' tree instead ?

I'd suggest the following:
Maintain LibOS in your git tree and follow Linus' tree.
Make sure that all kernel releases build and work.

This way you can experiment with automation and other
stuff. If it works well you can ask for mainline inclusion
after a few kernel releases.

Your git history will show how much maintenance burden
LibOS has and how much with every merge window breaks and
needs manual fixup.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 117+ messages in thread

* Re: [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS)
  2015-04-24  8:59         ` Richard Weinberger
@ 2015-04-24  9:50           ` Hajime Tazaki
  0 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-24  9:50 UTC (permalink / raw)
  To: richard
  Cc: linux-arch, arnd, corbet, cl, penberg, rientjes, iamjoonsoo.kim,
	akpm, linux-kernel, linux-doc, netdev, linux-mm, jdike, rusty,
	upa, christoph.paasch, mathieu.lacage, libos-nuse


At Fri, 24 Apr 2015 10:59:21 +0200,
Richard Weinberger wrote:
> Am 24.04.2015 um 10:22 schrieb Hajime Tazaki:
> >> You *really* need to shape up wrt the build process.
> > 
> > at the moment, the implementation of libos can't automate to
> > follow such changes in the build process. but good news is
> > it's a trivial task to follow up the latest function.
> > 
> > my observation on this manual follow up since around 3.7
> > kernel (2.5 yrs ago) is that these changes mostly happened
> > during merge-window of each new version, and the fix only
> > takes a couple of hours at maximum.
> > 
> > I think I can survive with these changes but I'd like to ask
> > broader opinions.
> > 
> > 
> > one more question:
> > 
> > I'd really like to have a suggestion on which tree I should
> > base for libos tree.
> > 
> > I'm proposing a patchset to arnd/asm-generic tree (which I
> > believe the base tree for new arch/), while the patchset is
> > tested with davem/net-next tree because right now libos is
> > only for net/.
> > 
> > shall I propose a patchset based on Linus' tree instead ?
> 
> I'd suggest the following:
> Maintain LibOS in your git tree and follow Linus' tree.

I see. will do it from next patch version.

> Make sure that all kernel releases build and work.
> 
> This way you can experiment with automation and other
> stuff. If it works well you can ask for mainline inclusion
> after a few kernel releases.
> 
> Your git history will show how much maintenance burden
> LibOS has and how much with every merge window breaks and
> needs manual fixup.

I believe this experiment is what we have been doing in the
past a couple of years (it's been tested with net-next tree,
not Linus tree though).

and the experiment is working well (as I stated in the
previous email) and that's why I'm here to propose this
patchset.

you can also see the git history: it also includes libos
specific commits of course.

https://github.com/libos-nuse/net-next-nuse/commits/nuse?author=thehajime



-- Hajime

^ permalink raw reply	[flat|nested] 117+ messages in thread

* [PATCH v4 00/10] an introduction of Linux library operating system (LibOS)
  2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
                       ` (10 preceding siblings ...)
  2015-04-24  7:40     ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Richard Weinberger
@ 2015-04-27  3:00     ` Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
                         ` (11 more replies)
  11 siblings, 12 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-27  3:00 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

This is the 4th version of Linux LibOS patchset which reflects a
couple of comments received from people.

changes from v3:
- Patch 09/10 ("lib: libos build scripts and documentation")
1) Remove RFC (now it's a proposal)
2) build environment cleanup (commented by Paul Bolle)
- Overall
3) change based tree from arnd/asm-generic to torvalds/linux.git
   (commented by Richard Weinberger)
4) rebased to Linux 4.1-rc1 (b787f68c36d49bb1d9236f403813641efa74a031)
5) change the title of cover letter a bit

changes from v2:
- Patch 02/11 ("slab: add private memory allocator header for arch/lib")
1) add new allocator named SLIB (Library Allocator): Patch 04/11 is integrated
   to 02 (commented by Christoph Lameter)
- Overall
2) rewrite commit log messages

changes from v1:
- Patch 01/11 ("sysctl: make some functions unstatic to access by arch/lib"):
1) add prefix ctl_table_ to newly publiced functions (commented by Joe Perches)
- Patch 08/11 ("lib: other kernel glue layer code"):
2) significantly reduce glue codes (stubs) (commented by Richard Weinberger)
- Others
3) adapt to linux-4.0.0
4) detect make dependency by Kbuild .cmd files

patchset history
-----------------
[v3] : https://lkml.org/lkml/2015/4/19/63
[v2] : https://lkml.org/lkml/2015/4/17/140
[v1] : https://lkml.org/lkml/2015/3/24/254

This is an introduction of Linux library operating system (LibOS).

Our objective is to build the kernel network stack as a shared library
that can be linked to by userspace programs to provide network stack
personalization and testing facilities, and allow researchers to more
easily simulate complex network topologies of linux routers/hosts.

Although the architecture itself can virtualize various things, the
current design only focuses on the network stack. You can benefit
network stack feature such as TCP, UDP, SCTP, DCCP (IPv4 and IPv6),
Mobie IPv6, Multipath TCP (IPv4/IPv6, out-of-tree at the present
moment), and netlink with various userspace applications (quagga,
iproute2, iperf, wget, and thttpd).

== What is LibOS ? ==

The library exposes an entry point as API, which is lib_init(), in
order to connect userspace applications to the (userspace-version)
kernel network stack. The clock source, virtual struct net_device, and
scheduler are provided by caller while kernel resource like system
calls is provided by callee.

Once the LibOS is initialized via the API, userspace applications with
POSIX socket can use the system calls defined in LibOS by replacing
from the original socket-related symbols to the LibOS-specific
one. Then application can benefit the network stack of LibOS without
involving the host network stack.

Currently, there are two users of LibOS: Network Stack in Userspace
(NUSE) and ns-3 network simulatior with Direct Code Execution
(DCE). These codes are managed at an external repository(*1).


== How to use it ? ==

to build the library,
% make {defconfig,menuconfig} ARCH=lib

then, build it.
% make library ARCH=lib

You will see liblinux-$(KERNELVERSION).so in the top directory.

== More information ==

The crucial difference between UML (user-mode linux) and this approach
is that we allow multiple network stack instances to co-exist within a
single process with dlmopen(3) like linking for easy debugging.


These patches are also available on this branch:

git://github.com/libos-nuse/net-next-nuse.git for-linus-upstream-libos-v4

(based on the commit b787f68c36d49bb1d9236f403813641efa74a031 of torvalds/linux.git)


For further information, here is a slideset presented at the last
netdev0.1 conference.

http://www.slideshare.net/hajimetazaki/library-operating-system-for-linux-netdev01

I would appreciate any kind of your feedback regarding to upstream
this feature.

*1 https://github.com/libos-nuse/linux-libos-tools

Hajime Tazaki (10):
  sysctl: make some functions unstatic to access by arch/lib
  slab: add SLIB (Library memory allocator) for  arch/lib
  lib: public headers and API implementations for userspace programs
  lib: time handling (kernel glue code)
  lib: context and scheduling functions (kernel glue code) for libos
  lib: sysctl handling (kernel glue code)
  lib: other kernel glue layer code
  lib: auxially files for auto-generated asm-generic files of libos
  lib: libos build scripts and documentation
  lib: tools used for test scripts

 Documentation/virtual/libos-howto.txt | 144 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   3 +
 arch/lib/Kconfig                      | 124 +++++++
 arch/lib/Makefile                     | 224 ++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/capability.c                 |  25 ++
 arch/lib/defconfig                    | 653 ++++++++++++++++++++++++++++++++++
 arch/lib/filemap.c                    |  32 ++
 arch/lib/fs.c                         |  70 ++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/glue.c                       | 289 +++++++++++++++
 arch/lib/hrtimer.c                    | 122 +++++++
 arch/lib/include/asm/Kbuild           |  57 +++
 arch/lib/include/asm/atomic.h         |  50 +++
 arch/lib/include/asm/barrier.h        |   8 +
 arch/lib/include/asm/bitsperlong.h    |  16 +
 arch/lib/include/asm/current.h        |   7 +
 arch/lib/include/asm/elf.h            |  10 +
 arch/lib/include/asm/hardirq.h        |   8 +
 arch/lib/include/asm/page.h           |  14 +
 arch/lib/include/asm/pgtable.h        |  30 ++
 arch/lib/include/asm/processor.h      |  19 +
 arch/lib/include/asm/ptrace.h         |   4 +
 arch/lib/include/asm/segment.h        |   6 +
 arch/lib/include/asm/sembuf.h         |   4 +
 arch/lib/include/asm/shmbuf.h         |   4 +
 arch/lib/include/asm/shmparam.h       |   4 +
 arch/lib/include/asm/sigcontext.h     |   6 +
 arch/lib/include/asm/stat.h           |   4 +
 arch/lib/include/asm/statfs.h         |   4 +
 arch/lib/include/asm/swab.h           |   7 +
 arch/lib/include/asm/thread_info.h    |  36 ++
 arch/lib/include/asm/uaccess.h        |  14 +
 arch/lib/include/asm/unistd.h         |   4 +
 arch/lib/include/sim-assert.h         |  23 ++
 arch/lib/include/sim-init.h           | 134 +++++++
 arch/lib/include/sim-printf.h         |  13 +
 arch/lib/include/sim-types.h          |  53 +++
 arch/lib/include/sim.h                |  51 +++
 arch/lib/include/uapi/asm/byteorder.h |   6 +
 arch/lib/lib-device.c                 | 187 ++++++++++
 arch/lib/lib-socket.c                 | 410 +++++++++++++++++++++
 arch/lib/lib.c                        | 294 +++++++++++++++
 arch/lib/lib.h                        |  21 ++
 arch/lib/modules.c                    |  36 ++
 arch/lib/pid.c                        |  29 ++
 arch/lib/print.c                      |  56 +++
 arch/lib/proc.c                       |  34 ++
 arch/lib/random.c                     |  53 +++
 arch/lib/sched.c                      | 406 +++++++++++++++++++++
 arch/lib/softirq.c                    | 108 ++++++
 arch/lib/sysctl.c                     | 270 ++++++++++++++
 arch/lib/sysfs.c                      |  83 +++++
 arch/lib/tasklet-hrtimer.c            |  57 +++
 arch/lib/tasklet.c                    |  76 ++++
 arch/lib/time.c                       | 144 ++++++++
 arch/lib/timer.c                      | 238 +++++++++++++
 arch/lib/vmscan.c                     |  26 ++
 arch/lib/workqueue.c                  | 242 +++++++++++++
 fs/proc/proc_sysctl.c                 |  36 +-
 include/linux/slab.h                  |   6 +-
 include/linux/slib_def.h              |  21 ++
 mm/Makefile                           |   1 +
 mm/slab.h                             |   4 +
 mm/slib.c                             | 205 +++++++++++
 tools/testing/libos/.gitignore        |   6 +
 tools/testing/libos/Makefile          |  38 ++
 tools/testing/libos/README            |  15 +
 tools/testing/libos/bisect.sh         |  10 +
 tools/testing/libos/dce-test.sh       |  23 ++
 tools/testing/libos/nuse-test.sh      |  57 +++
 72 files changed, 5560 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/virtual/libos-howto.txt
 create mode 100644 arch/lib/.gitignore
 create mode 100644 arch/lib/Kconfig
 create mode 100644 arch/lib/Makefile
 create mode 100644 arch/lib/Makefile.print
 create mode 100644 arch/lib/capability.c
 create mode 100644 arch/lib/defconfig
 create mode 100644 arch/lib/filemap.c
 create mode 100644 arch/lib/fs.c
 create mode 100755 arch/lib/generate-linker-script.py
 create mode 100644 arch/lib/glue.c
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/include/asm/Kbuild
 create mode 100644 arch/lib/include/asm/atomic.h
 create mode 100644 arch/lib/include/asm/barrier.h
 create mode 100644 arch/lib/include/asm/bitsperlong.h
 create mode 100644 arch/lib/include/asm/current.h
 create mode 100644 arch/lib/include/asm/elf.h
 create mode 100644 arch/lib/include/asm/hardirq.h
 create mode 100644 arch/lib/include/asm/page.h
 create mode 100644 arch/lib/include/asm/pgtable.h
 create mode 100644 arch/lib/include/asm/processor.h
 create mode 100644 arch/lib/include/asm/ptrace.h
 create mode 100644 arch/lib/include/asm/segment.h
 create mode 100644 arch/lib/include/asm/sembuf.h
 create mode 100644 arch/lib/include/asm/shmbuf.h
 create mode 100644 arch/lib/include/asm/shmparam.h
 create mode 100644 arch/lib/include/asm/sigcontext.h
 create mode 100644 arch/lib/include/asm/stat.h
 create mode 100644 arch/lib/include/asm/statfs.h
 create mode 100644 arch/lib/include/asm/swab.h
 create mode 100644 arch/lib/include/asm/thread_info.h
 create mode 100644 arch/lib/include/asm/uaccess.h
 create mode 100644 arch/lib/include/asm/unistd.h
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/include/uapi/asm/byteorder.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h
 create mode 100644 arch/lib/modules.c
 create mode 100644 arch/lib/pid.c
 create mode 100644 arch/lib/print.c
 create mode 100644 arch/lib/proc.c
 create mode 100644 arch/lib/random.c
 create mode 100644 arch/lib/sched.c
 create mode 100644 arch/lib/softirq.c
 create mode 100644 arch/lib/sysctl.c
 create mode 100644 arch/lib/sysfs.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/tasklet.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c
 create mode 100644 arch/lib/vmscan.c
 create mode 100644 arch/lib/workqueue.c
 create mode 100644 include/linux/slib_def.h
 create mode 100644 mm/slib.c
 create mode 100644 tools/testing/libos/.gitignore
 create mode 100644 tools/testing/libos/Makefile
 create mode 100644 tools/testing/libos/README
 create mode 100755 tools/testing/libos/bisect.sh
 create mode 100755 tools/testing/libos/dce-test.sh
 create mode 100755 tools/testing/libos/nuse-test.sh

-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [PATCH v4 01/10] sysctl: make some functions unstatic to access by arch/lib
  2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
@ 2015-04-27  3:00       ` Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
                         ` (10 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-27  3:00 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

libos (arch/lib) emulates a sysctl-like interface by a function call of
userspace by enumerating sysctl tree from sysctl_table_root. It requires
to be publicly accessible to this symbol and related functions.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 fs/proc/proc_sysctl.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index fea2561..7c5924c 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -35,7 +35,7 @@ static struct ctl_table root_table[] = {
 	},
 	{ }
 };
-static struct ctl_table_root sysctl_table_root = {
+struct ctl_table_root sysctl_table_root = {
 	.default_set.dir.header = {
 		{{.count = 1,
 		  .nreg = 1,
@@ -77,8 +77,9 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
 }
 
 /* Called under sysctl_lock */
-static struct ctl_table *find_entry(struct ctl_table_header **phead,
-	struct ctl_dir *dir, const char *name, int namelen)
+struct ctl_table *ctl_table_find_entry(struct ctl_table_header **phead,
+				       struct ctl_dir *dir, const char *name,
+				       int namelen)
 {
 	struct ctl_table_header *head;
 	struct ctl_table *entry;
@@ -300,7 +301,7 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
 	struct ctl_table *entry;
 
 	spin_lock(&sysctl_lock);
-	entry = find_entry(&head, dir, name, namelen);
+	entry = ctl_table_find_entry(&head, dir, name, namelen);
 	if (entry && use_table(head))
 		*phead = head;
 	else
@@ -321,7 +322,7 @@ static struct ctl_node *first_usable_entry(struct rb_node *node)
 	return NULL;
 }
 
-static void first_entry(struct ctl_dir *dir,
+void ctl_table_first_entry(struct ctl_dir *dir,
 	struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = NULL;
@@ -339,7 +340,7 @@ static void first_entry(struct ctl_dir *dir,
 	*pentry = entry;
 }
 
-static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
+void ctl_table_next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
 {
 	struct ctl_table_header *head = *phead;
 	struct ctl_table *entry = *pentry;
@@ -670,7 +671,8 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
 
 	pos = 2;
 
-	for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
+	for (ctl_table_first_entry(ctl_dir, &h, &entry); h;
+	     ctl_table_next_entry(&h, &entry)) {
 		if (!scan(h, entry, &pos, file, ctx)) {
 			sysctl_head_finish(h);
 			break;
@@ -828,7 +830,7 @@ static struct ctl_dir *find_subdir(struct ctl_dir *dir,
 	struct ctl_table_header *head;
 	struct ctl_table *entry;
 
-	entry = find_entry(&head, dir, name, namelen);
+	entry = ctl_table_find_entry(&head, dir, name, namelen);
 	if (!entry)
 		return ERR_PTR(-ENOENT);
 	if (!S_ISDIR(entry->mode))
@@ -924,13 +926,13 @@ failed:
 	return subdir;
 }
 
-static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
+struct ctl_dir *ctl_table_xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
 {
 	struct ctl_dir *parent;
 	const char *procname;
 	if (!dir->header.parent)
 		return &set->dir;
-	parent = xlate_dir(set, dir->header.parent);
+	parent = ctl_table_xlate_dir(set, dir->header.parent);
 	if (IS_ERR(parent))
 		return parent;
 	procname = dir->header.ctl_table[0].procname;
@@ -951,13 +953,13 @@ static int sysctl_follow_link(struct ctl_table_header **phead,
 	spin_lock(&sysctl_lock);
 	root = (*pentry)->data;
 	set = lookup_header_set(root, namespaces);
-	dir = xlate_dir(set, (*phead)->parent);
+	dir = ctl_table_xlate_dir(set, (*phead)->parent);
 	if (IS_ERR(dir))
 		ret = PTR_ERR(dir);
 	else {
 		const char *procname = (*pentry)->procname;
 		head = NULL;
-		entry = find_entry(&head, dir, procname, strlen(procname));
+		entry = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		ret = -ENOENT;
 		if (entry && use_table(head)) {
 			unuse_table(*phead);
@@ -1069,7 +1071,7 @@ static bool get_links(struct ctl_dir *dir,
 	/* Are there links available for every entry in table? */
 	for (entry = table; entry->procname; entry++) {
 		const char *procname = entry->procname;
-		link = find_entry(&head, dir, procname, strlen(procname));
+		link = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		if (!link)
 			return false;
 		if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
@@ -1082,7 +1084,7 @@ static bool get_links(struct ctl_dir *dir,
 	/* The checks passed.  Increase the registration count on the links */
 	for (entry = table; entry->procname; entry++) {
 		const char *procname = entry->procname;
-		link = find_entry(&head, dir, procname, strlen(procname));
+		link = ctl_table_find_entry(&head, dir, procname, strlen(procname));
 		head->nreg++;
 	}
 	return true;
@@ -1098,7 +1100,7 @@ static int insert_links(struct ctl_table_header *head)
 	if (head->set == root_set)
 		return 0;
 
-	core_parent = xlate_dir(root_set, head->parent);
+	core_parent = ctl_table_xlate_dir(root_set, head->parent);
 	if (IS_ERR(core_parent))
 		return 0;
 
@@ -1479,7 +1481,7 @@ static void put_links(struct ctl_table_header *header)
 	if (header->set == root_set)
 		return;
 
-	core_parent = xlate_dir(root_set, parent);
+	core_parent = ctl_table_xlate_dir(root_set, parent);
 	if (IS_ERR(core_parent))
 		return;
 
@@ -1488,7 +1490,7 @@ static void put_links(struct ctl_table_header *header)
 		struct ctl_table *link;
 		const char *name = entry->procname;
 
-		link = find_entry(&link_head, core_parent, name, strlen(name));
+		link = ctl_table_find_entry(&link_head, core_parent, name, strlen(name));
 		if (link &&
 		    ((S_ISDIR(link->mode) && S_ISDIR(entry->mode)) ||
 		     (S_ISLNK(link->mode) && (link->data == root)))) {
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [PATCH v4 02/10] slab: add SLIB (Library memory allocator) for  arch/lib
  2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
@ 2015-04-27  3:00       ` Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
                         ` (9 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-27  3:00 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

add SLIB allocator for arch/lib (CONFIG_LIB) to wrap kmalloc and co.
This will bring user's own allocator of libos: malloc(3) etc.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 include/linux/slab.h     |   6 +-
 include/linux/slib_def.h |  21 +++++
 mm/Makefile              |   1 +
 mm/slab.h                |   4 +
 mm/slib.c                | 205 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 236 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/slib_def.h
 create mode 100644 mm/slib.c

diff --git a/include/linux/slab.h b/include/linux/slab.h
index ffd24c8..0288cf8 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -191,7 +191,7 @@ size_t ksize(const void *);
 #endif
 #endif
 
-#ifdef CONFIG_SLOB
+#if defined(CONFIG_SLOB) || defined(CONFIG_SLIB)
 /*
  * SLOB passes all requests larger than one page to the page allocator.
  * No kmalloc array is necessary since objects of different sizes can
@@ -356,6 +356,9 @@ kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
 }
 #endif
 
+#ifdef CONFIG_SLIB
+#include <linux/slib_def.h>
+#else
 static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
 {
 	unsigned int order = get_order(size);
@@ -434,6 +437,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 	}
 	return __kmalloc(size, flags);
 }
+#endif /* CONFIG_SLIB */
 
 /*
  * Determine size used for the nth kmalloc cache.
diff --git a/include/linux/slib_def.h b/include/linux/slib_def.h
new file mode 100644
index 0000000..d9fe7d5
--- /dev/null
+++ b/include/linux/slib_def.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_SLLB_DEF_H
+#define _LINUX_SLLB_DEF_H
+
+
+struct kmem_cache {
+	unsigned int object_size;
+	const char *name;
+	size_t size;
+	size_t align;
+	unsigned long flags;
+	void (*ctor)(void *);
+};
+
+void *__kmalloc(size_t size, gfp_t flags);
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
+static __always_inline void *kmalloc(size_t size, gfp_t flags)
+{
+	return __kmalloc(size, flags);
+}
+
+#endif /* _LINUX_SLLB_DEF_H */
diff --git a/mm/Makefile b/mm/Makefile
index 98c4eae..7d8314f 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
 obj-$(CONFIG_SLOB) += slob.o
+obj-$(CONFIG_SLIB) += slib.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_KSM) += ksm.o
 obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
diff --git a/mm/slab.h b/mm/slab.h
index 4c3ac12..2ea37c9 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -37,6 +37,10 @@ struct kmem_cache {
 #include <linux/slub_def.h>
 #endif
 
+#ifdef CONFIG_SLIB
+#include <linux/slib_def.h>
+#endif
+
 #include <linux/memcontrol.h>
 
 /*
diff --git a/mm/slib.c b/mm/slib.c
new file mode 100644
index 0000000..37596862
--- /dev/null
+++ b/mm/slib.c
@@ -0,0 +1,205 @@
+/*
+ * Library Slab Allocator (SLIB)
+ *
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include "sim.h"
+#include "sim-assert.h"
+#include <linux/page-flags.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/slib_def.h>
+
+/* glues */
+struct kmem_cache *files_cachep;
+
+void kfree(const void *p)
+{
+	unsigned long start;
+
+	if (p == 0)
+		return;
+	start = (unsigned long)p;
+	start -= sizeof(size_t);
+	lib_free((void *)start);
+}
+size_t ksize(const void *p)
+{
+	size_t *psize = (size_t *)p;
+
+	psize--;
+	return *psize;
+}
+void *__kmalloc(size_t size, gfp_t flags)
+{
+	void *p = lib_malloc(size + sizeof(size));
+	unsigned long start;
+
+	if (!p)
+		return NULL;
+
+	if (p != 0 && (flags & __GFP_ZERO))
+		lib_memset(p, 0, size + sizeof(size));
+	lib_memcpy(p, &size, sizeof(size));
+	start = (unsigned long)p;
+	return (void *)(start + sizeof(size));
+}
+
+void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
+{
+	return kmalloc(size, flags);
+}
+
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+	void *ret;
+
+	if (!new_size) {
+		kfree(p);
+		return ZERO_SIZE_PTR;
+	}
+
+	ret = __kmalloc(new_size, flags);
+	if (ret && p != ret)
+		kfree(p);
+
+	return ret;
+}
+
+struct kmem_cache *
+kmem_cache_create(const char *name, size_t size, size_t align,
+		  unsigned long flags, void (*ctor)(void *))
+{
+	struct kmem_cache *cache = kmalloc(sizeof(struct kmem_cache), flags);
+
+	if (!cache)
+		return NULL;
+	cache->name = name;
+	cache->size = size;
+	cache->align = align;
+	cache->flags = flags;
+	cache->ctor = ctor;
+	return cache;
+}
+void kmem_cache_destroy(struct kmem_cache *cache)
+{
+	kfree(cache);
+}
+int kmem_cache_shrink(struct kmem_cache *cache)
+{
+	return 1;
+}
+const char *kmem_cache_name(struct kmem_cache *cache)
+{
+	return cache->name;
+}
+void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+	void *p = kmalloc(cache->size, flags);
+
+	if (p == 0)
+		return NULL;
+	if (cache->ctor)
+		(cache->ctor)(p);
+	return p;
+
+}
+void kmem_cache_free(struct kmem_cache *cache, void *p)
+{
+	kfree(p);
+}
+
+struct page *
+__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
+		       struct zonelist *zonelist, nodemask_t *nodemask)
+{
+	void *p;
+	struct page *page;
+	unsigned long pointer;
+
+	/* typically, called from networking code by alloc_page or */
+	/* directly with an order = 0. */
+	if (order)
+		return NULL;
+	p = lib_malloc(sizeof(struct page) + (1 << PAGE_SHIFT));
+	page = (struct page *)p;
+
+	atomic_set(&page->_count, 1);
+	page->flags = 0;
+	pointer = (unsigned long)page;
+	pointer += sizeof(struct page);
+	page->virtual = (void *)pointer;
+	return page;
+}
+void __free_pages(struct page *page, unsigned int order)
+{
+	/* typically, called from networking code by __free_page */
+	lib_assert(order == 0);
+	lib_free(page);
+}
+
+void put_page(struct page *page)
+{
+	if (atomic_dec_and_test(&page->_count))
+		lib_free(page);
+}
+unsigned long get_zeroed_page(gfp_t gfp_mask)
+{
+	return __get_free_pages(gfp_mask | __GFP_ZERO, 0);
+}
+
+void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
+{
+	return alloc_pages(gfp_mask, get_order(size));
+}
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+{
+	int size = (1 << order) * PAGE_SIZE;
+	void *p = kmalloc(size, gfp_mask);
+
+	return (unsigned long)p;
+}
+void free_pages(unsigned long addr, unsigned int order)
+{
+	if (addr != 0)
+		kfree((void *)addr);
+}
+
+void *vmalloc(unsigned long size)
+{
+	return lib_malloc(size);
+}
+void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return kmalloc(size, gfp_mask);
+}
+void vfree(const void *addr)
+{
+	lib_free((void *)addr);
+}
+void *vmalloc_node(unsigned long size, int node)
+{
+	return lib_malloc(size);
+}
+void vmalloc_sync_all(void)
+{
+}
+void *__alloc_percpu(size_t size, size_t align)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+void free_percpu(void __percpu *ptr)
+{
+	kfree(ptr);
+}
+void *__alloc_bootmem_nopanic(unsigned long size,
+			      unsigned long align,
+			      unsigned long goal)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [PATCH v4 03/10] lib: public headers and API implementations for userspace programs
  2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
@ 2015-04-27  3:00       ` Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 04/10] lib: time handling (kernel glue code) Hajime Tazaki
                         ` (8 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-27  3:00 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

userspace programs which uses libos access via a public API, lib_init(),
with passed arguments struct SimImported and struct SimExported.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 arch/lib/include/sim-assert.h |  23 +++
 arch/lib/include/sim-init.h   | 134 ++++++++++++++
 arch/lib/include/sim-printf.h |  13 ++
 arch/lib/include/sim-types.h  |  53 ++++++
 arch/lib/include/sim.h        |  51 ++++++
 arch/lib/lib-device.c         | 187 +++++++++++++++++++
 arch/lib/lib-socket.c         | 410 ++++++++++++++++++++++++++++++++++++++++++
 arch/lib/lib.c                | 294 ++++++++++++++++++++++++++++++
 arch/lib/lib.h                |  21 +++
 9 files changed, 1186 insertions(+)
 create mode 100644 arch/lib/include/sim-assert.h
 create mode 100644 arch/lib/include/sim-init.h
 create mode 100644 arch/lib/include/sim-printf.h
 create mode 100644 arch/lib/include/sim-types.h
 create mode 100644 arch/lib/include/sim.h
 create mode 100644 arch/lib/lib-device.c
 create mode 100644 arch/lib/lib-socket.c
 create mode 100644 arch/lib/lib.c
 create mode 100644 arch/lib/lib.h

diff --git a/arch/lib/include/sim-assert.h b/arch/lib/include/sim-assert.h
new file mode 100644
index 0000000..974122c
--- /dev/null
+++ b/arch/lib/include/sim-assert.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_ASSERT_H
+#define SIM_ASSERT_H
+
+#include "sim-printf.h"
+
+#define lib_assert(v) {							\
+		while (!(v)) {						\
+			lib_printf("Assert failed %s:%u \"" #v "\"\n",	\
+				__FILE__, __LINE__);			\
+			char *p = 0;					\
+			*p = 1;						\
+		}							\
+	}
+
+
+#endif /* SIM_ASSERT_H */
diff --git a/arch/lib/include/sim-init.h b/arch/lib/include/sim-init.h
new file mode 100644
index 0000000..e871a59
--- /dev/null
+++ b/arch/lib/include/sim-init.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_INIT_H
+#define SIM_INIT_H
+
+#include <linux/socket.h>
+#include "sim-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
+
+struct SimExported {
+	struct SimTask *(*task_create)(void *priv, unsigned long pid);
+	void (*task_destroy)(struct SimTask *task);
+	void *(*task_get_private)(struct SimTask *task);
+
+	int (*sock_socket)(int domain, int type, int protocol,
+			struct SimSocket **socket);
+	int (*sock_close)(struct SimSocket *socket);
+	ssize_t (*sock_recvmsg)(struct SimSocket *socket, struct msghdr *msg,
+				int flags);
+	ssize_t (*sock_sendmsg)(struct SimSocket *socket,
+				const struct msghdr *msg, int flags);
+	int (*sock_getsockname)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_getpeername)(struct SimSocket *socket,
+				struct sockaddr *name, int *namelen);
+	int (*sock_bind)(struct SimSocket *socket, const struct sockaddr *name,
+			int namelen);
+	int (*sock_connect)(struct SimSocket *socket,
+			const struct sockaddr *name, int namelen,
+			int flags);
+	int (*sock_listen)(struct SimSocket *socket, int backlog);
+	int (*sock_shutdown)(struct SimSocket *socket, int how);
+	int (*sock_accept)(struct SimSocket *socket,
+			struct SimSocket **newSocket, int flags);
+	int (*sock_ioctl)(struct SimSocket *socket, int request, char *argp);
+	int (*sock_setsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			const void *optval, int optlen);
+	int (*sock_getsockopt)(struct SimSocket *socket, int level,
+			int optname,
+			void *optval, int *optlen);
+
+	void (*sock_poll)(struct SimSocket *socket, void *ret);
+	void (*sock_pollfreewait)(void *polltable);
+
+	struct SimDevice *(*dev_create)(const char *ifname, void *priv,
+					enum SimDevFlags flags);
+	void (*dev_destroy)(struct SimDevice *dev);
+	void *(*dev_get_private)(struct SimDevice *task);
+	void (*dev_set_address)(struct SimDevice *dev,
+				unsigned char buffer[6]);
+	void (*dev_set_mtu)(struct SimDevice *dev, int mtu);
+	struct SimDevicePacket (*dev_create_packet)(struct SimDevice *dev,
+						int size);
+	void (*dev_rx)(struct SimDevice *dev, struct SimDevicePacket packet);
+
+	void (*sys_iterate_files)(const struct SimSysIterator *iter);
+	int (*sys_file_read)(const struct SimSysFile *file, char *buffer,
+			int size, int offset);
+	int (*sys_file_write)(const struct SimSysFile *file,
+			const char *buffer, int size, int offset);
+};
+
+struct SimImported {
+	int (*vprintf)(struct SimKernel *kernel, const char *str,
+		va_list args);
+	void *(*malloc)(struct SimKernel *kernel, unsigned long size);
+	void (*free)(struct SimKernel *kernel, void *buffer);
+	void *(*memcpy)(struct SimKernel *kernel, void *dst, const void *src,
+			unsigned long size);
+	void *(*memset)(struct SimKernel *kernel, void *dst, char value,
+			unsigned long size);
+	int (*atexit)(struct SimKernel *kernel, void (*function)(void));
+	int (*access)(struct SimKernel *kernel, const char *pathname,
+		int mode);
+	char *(*getenv)(struct SimKernel *kernel, const char *name);
+	int (*mkdir)(struct SimKernel *kernel, const char *pathname,
+		mode_t mode);
+	int (*open)(struct SimKernel *kernel, const char *pathname, int flags);
+	int (*__fxstat)(struct SimKernel *kernel, int ver, int fd, void *buf);
+	int (*fseek)(struct SimKernel *kernel, FILE *stream, long offset,
+		int whence);
+	void (*setbuf)(struct SimKernel *kernel, FILE *stream, char *buf);
+	FILE *(*fdopen)(struct SimKernel *kernel, int fd, const char *mode);
+	long (*ftell)(struct SimKernel *kernel, FILE *stream);
+	int (*fclose)(struct SimKernel *kernel, FILE *fp);
+	size_t (*fread)(struct SimKernel *kernel, void *ptr, size_t size,
+			size_t nmemb, FILE *stream);
+	size_t (*fwrite)(struct SimKernel *kernel, const void *ptr, size_t size,
+			 size_t nmemb, FILE *stream);
+
+	unsigned long (*random)(struct SimKernel *kernel);
+	void *(*event_schedule_ns)(struct SimKernel *kernel, __u64 ns,
+				void (*fn)(void *context), void *context,
+				void (*pre_fn)(void));
+	void (*event_cancel)(struct SimKernel *kernel, void *event);
+	__u64 (*current_ns)(struct SimKernel *kernel);
+
+	struct SimTask *(*task_start)(struct SimKernel *kernel,
+				void (*callback)(void *),
+				void *context);
+	void (*task_wait)(struct SimKernel *kernel);
+	struct SimTask *(*task_current)(struct SimKernel *kernel);
+	int (*task_wakeup)(struct SimKernel *kernel, struct SimTask *task);
+	void (*task_yield)(struct SimKernel *kernel);
+
+	void (*dev_xmit)(struct SimKernel *kernel, struct SimDevice *dev,
+			unsigned char *data, int len);
+	void (*signal_raised)(struct SimKernel *kernel, struct SimTask *task,
+			int sig);
+	void (*poll_event)(int flag, void *context);
+};
+
+typedef void (*SimInit)(struct SimExported *, const struct SimImported *,
+			struct SimKernel *kernel);
+void sim_init(struct SimExported *exported, const struct SimImported *imported,
+	struct SimKernel *kernel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_INIT_H */
diff --git a/arch/lib/include/sim-printf.h b/arch/lib/include/sim-printf.h
new file mode 100644
index 0000000..2bf8245
--- /dev/null
+++ b/arch/lib/include/sim-printf.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_PRINTF_H
+#define SIM_PRINTF_H
+
+void lib_printf(const char *str, ...);
+
+#endif /* SIM_PRINTF_H */
diff --git a/arch/lib/include/sim-types.h b/arch/lib/include/sim-types.h
new file mode 100644
index 0000000..d50b99b
--- /dev/null
+++ b/arch/lib/include/sim-types.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_TYPES_H
+#define SIM_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBOS_API_VERSION     2
+
+struct SimTask;
+struct SimDevice;
+struct SimSocket;
+struct SimKernel;
+struct SimSysFile;
+
+enum SimDevFlags {
+	SIM_DEV_NOARP         = (1 << 0),
+	SIM_DEV_POINTTOPOINT  = (1 << 1),
+	SIM_DEV_MULTICAST     = (1 << 2),
+	SIM_DEV_BROADCAST     = (1 << 3),
+};
+
+struct SimDevicePacket {
+	void *buffer;
+	void *token;
+};
+
+enum SimSysFileFlags {
+	SIM_SYS_FILE_READ  = 1 << 0,
+	SIM_SYS_FILE_WRITE = 1 << 1,
+};
+
+struct SimSysIterator {
+	void (*report_start_dir)(const struct SimSysIterator *iter,
+				const char *dirname);
+	void (*report_end_dir)(const struct SimSysIterator *iter);
+	void (*report_file)(const struct SimSysIterator *iter,
+			const char *filename,
+			int flags, struct SimSysFile *file);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SIM_TYPES_H */
diff --git a/arch/lib/include/sim.h b/arch/lib/include/sim.h
new file mode 100644
index 0000000..b30d7e8
--- /dev/null
+++ b/arch/lib/include/sim.h
@@ -0,0 +1,51 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#ifndef SIM_H
+#define SIM_H
+
+#include <stdarg.h>
+#include <linux/types.h>
+
+#include "sim-types.h"
+
+/* API called from within linux kernel. Forwards to SimImported. */
+int lib_vprintf(const char *str, va_list args);
+void *lib_malloc(unsigned long size);
+void lib_free(void *buffer);
+void *lib_memcpy(void *dst, const void *src, unsigned long size);
+void *lib_memset(void *dst, char value, unsigned long size);
+unsigned long lib_random(void);
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context),
+			    void *context);
+void lib_event_cancel(void *event);
+__u64 lib_current_ns(void);
+
+struct SimTask *lib_task_start(void (*callback) (void *), void *context);
+void lib_task_wait(void);
+void lib_task_yield(void);
+struct SimTask *lib_task_current(void);
+/* returns 1 if task was woken up, 0 if it was already running. */
+int lib_task_wakeup(struct SimTask *task);
+struct SimTask *lib_task_create(void *priv, unsigned long pid);
+void lib_task_destroy(struct SimTask *task);
+void *lib_task_get_private(struct SimTask *task);
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len);
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size);
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet);
+
+void lib_signal_raised(struct SimTask *task, int sig);
+
+void lib_poll_event(int flag, void *context);
+void lib_softirq_wakeup(void);
+void lib_update_jiffies(void);
+void *lib_dev_get_private(struct SimDevice *);
+void lib_proc_net_initialize(void);
+
+#endif /* SIM_H */
diff --git a/arch/lib/lib-device.c b/arch/lib/lib-device.c
new file mode 100644
index 0000000..1efa6460
--- /dev/null
+++ b/arch/lib/lib-device.c
@@ -0,0 +1,187 @@
+/*
+ * virtual net_device feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ethtool.h>
+
+struct SimDevice {
+	struct net_device dev;
+	void *priv;
+};
+
+static netdev_tx_t
+kernel_dev_xmit(struct sk_buff *skb,
+		struct net_device *dev)
+{
+	int err;
+
+	netif_stop_queue(dev);
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		err = skb_checksum_help(skb);
+		if (unlikely(err)) {
+			pr_err("checksum error (%d)\n", err);
+			return 0;
+		}
+	}
+
+	lib_dev_xmit((struct SimDevice *)dev, skb->data, skb->len);
+	dev_kfree_skb(skb);
+	netif_wake_queue(dev);
+	return 0;
+}
+
+static u32 always_on(struct net_device *dev)
+{
+	return 1;
+}
+
+
+static const struct ethtool_ops lib_ethtool_ops = {
+	.get_link		= always_on,
+};
+
+static const struct net_device_ops lib_dev_ops = {
+	.ndo_start_xmit		= kernel_dev_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static void lib_dev_setup(struct net_device *dev)
+{
+	dev->mtu                = (16 * 1024) + 20 + 20 + 12;
+	dev->hard_header_len    = ETH_HLEN;     /* 14   */
+	dev->addr_len           = ETH_ALEN;     /* 6    */
+	dev->tx_queue_len       = 0;
+	dev->type               = ARPHRD_ETHER;
+	dev->flags              = 0;
+	/* dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE; */
+	dev->features           = 0
+				  | NETIF_F_HIGHDMA
+				  | NETIF_F_NETNS_LOCAL;
+	/* disabled  NETIF_F_TSO NETIF_F_SG  NETIF_F_FRAGLIST NETIF_F_LLTX */
+	dev->ethtool_ops        = &lib_ethtool_ops;
+	dev->header_ops         = &eth_header_ops;
+	dev->netdev_ops         = &lib_dev_ops;
+	dev->destructor         = &free_netdev;
+}
+
+
+struct SimDevice *lib_dev_create(const char *ifname, void *priv,
+				 enum SimDevFlags flags)
+{
+	int err;
+	struct SimDevice *dev =
+		(struct SimDevice *)alloc_netdev(sizeof(struct SimDevice),
+						 ifname, NET_NAME_UNKNOWN,
+						 &lib_dev_setup);
+	ether_setup((struct net_device *)dev);
+
+	if (flags & SIM_DEV_NOARP)
+		dev->dev.flags |= IFF_NOARP;
+	if (flags & SIM_DEV_POINTTOPOINT)
+		dev->dev.flags |= IFF_POINTOPOINT;
+	if (flags & SIM_DEV_MULTICAST)
+		dev->dev.flags |= IFF_MULTICAST;
+	if (flags & SIM_DEV_BROADCAST) {
+		dev->dev.flags |= IFF_BROADCAST;
+		memset(dev->dev.broadcast, 0xff, 6);
+	}
+	dev->priv = priv;
+	err = register_netdev(&dev->dev);
+	return dev;
+}
+void lib_dev_destroy(struct SimDevice *dev)
+{
+	unregister_netdev(&dev->dev);
+	/* XXX */
+	free_netdev(&dev->dev);
+}
+void *lib_dev_get_private(struct SimDevice *dev)
+{
+	return dev->priv;
+}
+
+void lib_dev_set_mtu(struct SimDevice *dev, int mtu)
+{
+	/* called by ns-3 to synchronize the kernel mtu with */
+	/* the simulation mtu */
+	dev->dev.mtu = mtu;
+}
+
+static int lib_ndo_change_mtu(struct net_device *dev,
+			      int new_mtu)
+{
+	/* called by kernel to change the mtu when the user */
+	/* asks for it. */
+	/* XXX should forward the set call to ns-3 and wait for */
+	/* ns-3 to notify of the change in the function above */
+	/* but I am way too tired to do this now. */
+	return 0;
+}
+
+void lib_dev_set_address(struct SimDevice *dev, unsigned char buffer[6])
+{
+	/* called by ns-3 to synchronize the kernel address with */
+	/* the simulation address. */
+	struct sockaddr sa;
+
+	sa.sa_family = dev->dev.type;
+	lib_memcpy(&sa.sa_data, buffer, 6);
+	dev->dev.netdev_ops->ndo_set_mac_address(&dev->dev, &sa);
+	/* Note that we don't call   dev_set_mac_address (&dev->dev, &sa); */
+	/* because this function expects to be called from within */
+	/* the netlink layer so, it expects to hold */
+	/* the netlink lock during the execution of the associated notifiers */
+}
+static int get_hack_size(int size)
+{
+	/* Note: this hack is coming from nsc */
+	/* Bit of a hack... */
+	/* Note that the size allocated here effects the offered window
+	   somewhat. I've got this heuristic here to try and match up with
+	   what we observe on the emulation network and by looking at the
+	   driver code of the eepro100. In both cases we allocate enough
+	   space for our packet, which  is the important thing. The amount
+	   of slack at the end can make linux decide the grow the window
+	   differently. This is quite subtle, but the code in question is
+	   in the tcp_grow_window function. It checks skb->truesize, which
+	   is the size of the skbuff allocated for the incoming data
+	   packet -- what we are allocating right now! */
+	if (size < 1200)
+		return size + 36;
+	else if (size <= 1500)
+		return 1536;
+	else
+		return size + 36;
+}
+struct SimDevicePacket lib_dev_create_packet(struct SimDevice *dev, int size)
+{
+	struct SimDevicePacket packet;
+	int len = get_hack_size(size);
+	struct sk_buff *skb = __dev_alloc_skb(len, __GFP_WAIT);
+
+	packet.token = skb;
+	packet.buffer = skb_put(skb, len);
+	return packet;
+}
+void lib_dev_rx(struct SimDevice *device, struct SimDevicePacket packet)
+{
+	struct sk_buff *skb = packet.token;
+	struct net_device *dev = &device->dev;
+
+	skb->protocol = eth_type_trans(skb, dev);
+	/* Do the TCP checksum (FIXME: should be configurable) */
+	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	netif_rx(skb);
+}
diff --git a/arch/lib/lib-socket.c b/arch/lib/lib-socket.c
new file mode 100644
index 0000000..d9be5fc
--- /dev/null
+++ b/arch/lib/lib-socket.c
@@ -0,0 +1,410 @@
+/*
+ * socket feature for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#include "sim-init.h"
+#include "sim.h"
+#include <linux/net.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/inet_connection_sock.h>
+
+struct SimSocket {};
+
+static struct iovec *copy_iovec(const struct iovec *input, int len)
+{
+	int size = sizeof(struct iovec) * len;
+	struct iovec *output = lib_malloc(size);
+
+	if (!output)
+		return NULL;
+	lib_memcpy(output, input, size);
+	return output;
+}
+
+int lib_sock_socket(int domain, int type, int protocol,
+		    struct SimSocket **socket)
+{
+	struct socket **kernel_socket = (struct socket **)socket;
+	int flags;
+
+	/* from net/socket.c */
+	flags = type & ~SOCK_TYPE_MASK;
+	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+		return -EINVAL;
+	type &= SOCK_TYPE_MASK;
+
+	int retval = sock_create(domain, type, protocol, kernel_socket);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	struct file *fp = lib_malloc(sizeof(struct file));
+	(*kernel_socket)->file = fp;
+	fp->f_cred = lib_malloc(sizeof(struct cred));
+	return retval;
+}
+int lib_sock_close(struct SimSocket *socket)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+
+	sock_release(kernel_socket);
+	return 0;
+}
+static size_t iov_size(const struct user_msghdr *msg)
+{
+	size_t i;
+	size_t size = 0;
+
+	for (i = 0; i < msg->msg_iovlen; i++)
+		size += msg->msg_iov[i].iov_len;
+	return size;
+}
+ssize_t lib_sock_recvmsg(struct SimSocket *socket,
+			struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct msghdr msg_sys;
+	struct cmsghdr *user_cmsgh = msg->msg_control;
+	size_t user_cmsghlen = msg->msg_controllen;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, READ,
+		msg->msg_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_recvmsg(kernel_socket, &msg_sys, iov_size(msg), flags);
+
+	msg->msg_name = msg_sys.msg_name;
+	msg->msg_namelen = msg_sys.msg_namelen;
+	msg->msg_control = user_cmsgh;
+	msg->msg_controllen = user_cmsghlen - msg_sys.msg_controllen;
+	return retval;
+}
+ssize_t lib_sock_sendmsg(struct SimSocket *socket,
+			const struct user_msghdr *msg,
+			int flags)
+{
+	struct socket *kernel_socket = (struct socket *)socket;
+	struct iovec *kernel_iov = copy_iovec(msg->msg_iov, msg->msg_iovlen);
+	struct msghdr msg_sys;
+	int retval;
+
+	msg_sys.msg_name = msg->msg_name;
+	msg_sys.msg_namelen = msg->msg_namelen;
+	msg_sys.msg_control = msg->msg_control;
+	msg_sys.msg_controllen = msg->msg_controllen;
+	msg_sys.msg_flags = flags;
+
+	iov_iter_init(&msg_sys.msg_iter, WRITE,
+		kernel_iov, msg->msg_iovlen, iov_size(msg));
+
+	retval = sock_sendmsg(kernel_socket, &msg_sys);
+	lib_free(kernel_iov);
+	return retval;
+}
+int lib_sock_getsockname(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 0);
+
+	return retval;
+}
+int lib_sock_getpeername(struct SimSocket *socket, struct sockaddr *name,
+			 int *namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->getname(sock, name, namelen, 1);
+
+	return retval;
+}
+int lib_sock_bind(struct SimSocket *socket, const struct sockaddr *name,
+		  int namelen)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	int retval =
+		sock->ops->bind(sock, (struct sockaddr *)&address, namelen);
+	return retval;
+}
+int lib_sock_connect(struct SimSocket *socket, const struct sockaddr *name,
+		     int namelen, int flags)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sockaddr_storage address;
+
+	memcpy(&address, name, namelen);
+	/* XXX: SCTP code never look at flags args, but file flags instead. */
+	sock->file->f_flags = flags;
+	int retval = sock->ops->connect(sock, (struct sockaddr *)&address,
+					namelen, flags);
+	return retval;
+}
+int lib_sock_listen(struct SimSocket *socket, int backlog)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->listen(sock, backlog);
+
+	return retval;
+}
+int lib_sock_shutdown(struct SimSocket *socket, int how)
+{
+	struct socket *sock = (struct socket *)socket;
+	int retval = sock->ops->shutdown(sock, how);
+
+	return retval;
+}
+int lib_sock_accept(struct SimSocket *socket, struct SimSocket **new_socket,
+		    int flags)
+{
+	struct socket *sock, *newsock;
+	int err;
+
+	sock = (struct socket *)socket;
+
+	/* the fields do not matter here. If we could, */
+	/* we would call sock_alloc but it's not exported. */
+	err = sock_create_lite(0, 0, 0, &newsock);
+	if (err < 0)
+		return err;
+	newsock->type = sock->type;
+	newsock->ops = sock->ops;
+
+	err = sock->ops->accept(sock, newsock, flags);
+	if (err < 0) {
+		sock_release(newsock);
+		return err;
+	}
+	*new_socket = (struct SimSocket *)newsock;
+	return 0;
+}
+int lib_sock_ioctl(struct SimSocket *socket, int request, char *argp)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct sock *sk;
+	struct net *net;
+	int err;
+
+	sk = sock->sk;
+	net = sock_net(sk);
+
+	err = sock->ops->ioctl(sock, request, (long)argp);
+
+	/*
+	 * If this ioctl is unknown try to hand it down
+	 * to the NIC driver.
+	 */
+	if (err == -ENOIOCTLCMD)
+		err = dev_ioctl(net, request, argp);
+	return err;
+}
+int lib_sock_setsockopt(struct SimSocket *socket, int level, int optname,
+			const void *optval, int optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	char *coptval = (char *)optval;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_setsockopt(sock, level, optname, coptval, optlen);
+	else
+		err = sock->ops->setsockopt(sock, level, optname, coptval,
+					    optlen);
+	return err;
+}
+int lib_sock_getsockopt(struct SimSocket *socket, int level, int optname,
+			void *optval, int *optlen)
+{
+	struct socket *sock = (struct socket *)socket;
+	int err;
+
+	if (level == SOL_SOCKET)
+		err = sock_getsockopt(sock, level, optname, optval, optlen);
+	else
+		err =
+			sock->ops->getsockopt(sock, level, optname, optval,
+					      optlen);
+	return err;
+}
+
+int lib_sock_canrecv(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+	struct inet_connection_sock *icsk;
+
+	switch (sock->sk->sk_state) {
+	case TCP_CLOSE:
+		if (SOCK_STREAM == sock->sk->sk_type)
+			return 1;
+	case TCP_ESTABLISHED:
+		return sock->sk->sk_receive_queue.qlen > 0;
+	case TCP_SYN_SENT:
+	case TCP_SYN_RECV:
+	case TCP_LAST_ACK:
+	case TCP_CLOSING:
+		return 0;
+	case TCP_FIN_WAIT1:
+	case TCP_FIN_WAIT2:
+	case TCP_TIME_WAIT:
+	case TCP_CLOSE_WAIT:
+		return 1;
+	case TCP_LISTEN:
+	{
+		icsk = inet_csk(sock->sk);
+		return !reqsk_queue_empty(&icsk->icsk_accept_queue);
+	}
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+int lib_sock_cansend(struct SimSocket *socket)
+{
+	struct socket *sock = (struct socket *)socket;
+
+	return sock_writeable(sock->sk);
+}
+
+/**
+ * Struct used to pass pool table context between DCE and Kernel and back from
+ * Kernel to DCE
+ *
+ * When calling sock_poll we provide in ret field the wanted eventmask, and in
+ * the opaque field the DCE poll table
+ *
+ * if a corresponding event occurs later, the PollEvent will be called by kernel
+ * with the DCE poll table in context variable, then we will able to wake up the
+ * thread blocked in poll call.
+ *
+ * Back from sock_poll method the kernel change ret field with the response from
+ * poll return of the corresponding kernel socket, and in opaque field there is
+ * a reference to the kernel poll table we will use this reference to remove us
+ * from the file wait queue when ending the DCE poll call or when ending the DCE
+ * process which is currently polling.
+ *
+ */
+struct poll_table_ref {
+	int ret;
+	void *opaque;
+};
+
+/* Because the poll main loop code is in NS3/DCE we have only on entry
+   in our kernel poll table */
+struct lib_ptable_entry {
+	wait_queue_t wait;
+	wait_queue_head_t *wait_address;
+	int eventMask;  /* Poll wanted event mask. */
+	void *opaque;   /* Pointeur to DCE poll table */
+};
+
+static int lib_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)wait->private;
+
+	/* Filter only wanted events */
+	if (key && !((unsigned long)key & entry->eventMask))
+		return 0;
+
+	lib_poll_event((unsigned long)key, entry->opaque);
+	return 1;
+}
+
+static void lib_pollwait(struct file *filp, wait_queue_head_t *wait_address,
+			 poll_table *p)
+{
+	struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
+	struct lib_ptable_entry *entry =
+		(struct lib_ptable_entry *)
+		lib_malloc(sizeof(struct lib_ptable_entry));
+	struct poll_table_ref *fromDCE =  (struct poll_table_ref *)pwq->table;
+
+	if (!entry)
+		return;
+
+	entry->opaque = fromDCE->opaque; /* Copy DCE poll table reference */
+	entry->eventMask = fromDCE->ret; /* Copy poll mask of wanted events. */
+
+	pwq->table = (struct poll_table_page *)entry;
+
+	init_waitqueue_func_entry(&entry->wait, lib_pollwake);
+	entry->wait.private = entry;
+	entry->wait_address = wait_address;
+	add_wait_queue(wait_address, &entry->wait);
+}
+
+void dce_poll_initwait(struct poll_wqueues *pwq)
+{
+	init_poll_funcptr(&pwq->pt, lib_pollwait);
+	pwq->polling_task = current;
+	pwq->triggered = 0;
+	pwq->error = 0;
+	pwq->table = NULL;
+	pwq->inline_index = 0;
+}
+
+/* call poll on socket ... */
+void lib_sock_poll(struct SimSocket *socket, struct poll_table_ref *ret)
+{
+	struct socket *sock = (struct socket *)socket;
+	/* Provide a fake file structure */
+	struct file zero;
+	poll_table *pwait = 0;
+	struct poll_wqueues *ptable = 0;
+
+	lib_memset(&zero, 0, sizeof(struct file));
+
+	if (ret->opaque) {
+		ptable =
+			(struct poll_wqueues *)lib_malloc(sizeof(struct
+								 poll_wqueues));
+		if (!ptable)
+			return;
+
+		dce_poll_initwait(ptable);
+
+		pwait = &(ptable->pt);
+		/* Pass the DCE pool table to lib_pollwait function */
+		ptable->table = (struct poll_table_page *)ret;
+	}
+
+	ret->ret = sock->ops->poll(&zero, sock, pwait);
+	/* Pass back the kernel poll table to DCE in order to DCE to */
+	/* remove from wait queue */
+	/* using lib_sock_pollfreewait method below */
+	ret->opaque = ptable;
+}
+
+void lib_sock_pollfreewait(void *polltable)
+{
+	struct poll_wqueues *ptable = (struct poll_wqueues *)polltable;
+
+	if (ptable && ptable->table) {
+		struct lib_ptable_entry *entry =
+			(struct lib_ptable_entry *)ptable->table;
+		remove_wait_queue(entry->wait_address, &entry->wait);
+		lib_free(entry);
+	}
+	lib_free(ptable);
+}
+
+
+
+
diff --git a/arch/lib/lib.c b/arch/lib/lib.c
new file mode 100644
index 0000000..52d638e
--- /dev/null
+++ b/arch/lib/lib.c
@@ -0,0 +1,294 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/init.h>         /* initcall_t */
+#include <linux/kernel.h>       /* SYSTEM_BOOTING */
+#include <linux/sched.h>        /* struct task_struct */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <drivers/base/base.h>
+#include <linux/idr.h>
+#include <linux/rcupdate.h>
+#include "sim-init.h"
+#include "sim.h"
+
+enum system_states system_state = SYSTEM_BOOTING;
+/* glues */
+struct task_struct init_task;
+
+struct SimImported g_imported;
+
+
+#define RETURN_void(rettype, v)				     \
+	({						     \
+		(v);					     \
+		lib_softirq_wakeup();			     \
+	})
+
+#define RETURN_nvoid(rettype, v)			     \
+	({						     \
+		rettype x = (v);			     \
+		lib_softirq_wakeup();			     \
+		x;					     \
+	})
+
+#define FORWARDER1(name, type, rettype, t0)			    \
+	extern rettype name(t0);				    \
+	static rettype name ## _forwarder(t0 v0)		    \
+	{							    \
+		lib_update_jiffies();				    \
+		return RETURN_ ## type(rettype, (name(v0)));        \
+	}
+
+#define FORWARDER2(name, type, rettype, t0, t1)				\
+	extern rettype name(t0, t1);					\
+	static rettype name ## _forwarder(t0 v0, t1 v1)			\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1)));	\
+	}
+#define FORWARDER3(name, type, rettype, t0, t1, t2)			\
+	extern rettype name(t0, t1, t2);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2)		\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2)));	\
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER4(name, type, rettype, t0, t1, t2, t3)			\
+	extern rettype name(t0, t1, t2, t3);				\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3)	\
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3))); \
+	}
+#define FORWARDER5(name, type, rettype, t0, t1, t2, t3, t4)		\
+	extern rettype name(t0, t1, t2, t3, t4);			\
+	static rettype name ## _forwarder(t0 v0, t1 v1, t2 v2, t3 v3, t4 v4) \
+	{								\
+		lib_update_jiffies();					\
+		return RETURN_ ## type(rettype, (name(v0, v1, v2, v3, v4))); \
+	}
+
+FORWARDER3(lib_dev_create, nvoid, struct SimDevice *, const char *, void *,
+	   enum SimDevFlags);
+FORWARDER1(lib_dev_destroy, void, void, struct SimDevice *);
+FORWARDER2(lib_dev_set_address, void, void, struct SimDevice *,
+	   unsigned char *);
+FORWARDER2(lib_dev_set_mtu, void, void, struct SimDevice *, int);
+FORWARDER2(lib_dev_create_packet, nvoid, struct SimDevicePacket,
+	   struct SimDevice *, int);
+FORWARDER2(lib_dev_rx, void, void, struct SimDevice *, struct SimDevicePacket);
+
+FORWARDER4(lib_sock_socket, nvoid, int, int, int, int, struct SimSocket **);
+FORWARDER1(lib_sock_close, nvoid, int, struct SimSocket *);
+FORWARDER3(lib_sock_recvmsg, nvoid, ssize_t, struct SimSocket *,
+	   struct msghdr *, int);
+FORWARDER3(lib_sock_sendmsg, nvoid, ssize_t, struct SimSocket *,
+	   const struct msghdr *, int);
+FORWARDER3(lib_sock_getsockname, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_getpeername, nvoid, int, struct SimSocket *,
+	   struct sockaddr *, int *);
+FORWARDER3(lib_sock_bind, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int);
+FORWARDER4(lib_sock_connect, nvoid, int, struct SimSocket *,
+	   const struct sockaddr *, int, int);
+FORWARDER2(lib_sock_listen, nvoid, int, struct SimSocket *, int);
+FORWARDER2(lib_sock_shutdown, nvoid, int, struct SimSocket *, int);
+FORWARDER3(lib_sock_accept, nvoid, int, struct SimSocket *,
+	   struct SimSocket **, int);
+FORWARDER3(lib_sock_ioctl, nvoid, int, struct SimSocket *, int, char *);
+FORWARDER5(lib_sock_setsockopt, nvoid, int, struct SimSocket *, int, int,
+	   const void *, int);
+FORWARDER5(lib_sock_getsockopt, nvoid, int, struct SimSocket *, int, int,
+	   void *, int *);
+
+FORWARDER2(lib_sock_poll, void, void, struct SimSocket *, void *);
+FORWARDER1(lib_sock_pollfreewait, void, void, void *);
+
+FORWARDER1(lib_sys_iterate_files, void, void, const struct SimSysIterator *);
+FORWARDER4(lib_sys_file_read, nvoid, int, const struct SimSysFile *, char *,
+	   int, int);
+FORWARDER4(lib_sys_file_write, nvoid, int, const struct SimSysFile *,
+	   const char *, int, int);
+
+struct SimKernel *g_kernel;
+
+void lib_init(struct SimExported *exported, const struct SimImported *imported,
+	      struct SimKernel *kernel)
+{
+	/* make sure we can call the callbacks */
+	g_imported = *imported;
+	g_kernel = kernel;
+	exported->task_create = lib_task_create;
+	exported->task_destroy = lib_task_destroy;
+	exported->task_get_private = lib_task_get_private;
+	exported->sock_socket = lib_sock_socket_forwarder;
+	exported->sock_close = lib_sock_close_forwarder;
+	exported->sock_recvmsg = lib_sock_recvmsg_forwarder;
+	exported->sock_sendmsg = lib_sock_sendmsg_forwarder;
+	exported->sock_getsockname = lib_sock_getsockname_forwarder;
+	exported->sock_getpeername = lib_sock_getpeername_forwarder;
+	exported->sock_bind = lib_sock_bind_forwarder;
+	exported->sock_connect = lib_sock_connect_forwarder;
+	exported->sock_listen = lib_sock_listen_forwarder;
+	exported->sock_shutdown = lib_sock_shutdown_forwarder;
+	exported->sock_accept = lib_sock_accept_forwarder;
+	exported->sock_ioctl = lib_sock_ioctl_forwarder;
+	exported->sock_setsockopt = lib_sock_setsockopt_forwarder;
+	exported->sock_getsockopt = lib_sock_getsockopt_forwarder;
+
+	exported->sock_poll = lib_sock_poll_forwarder;
+	exported->sock_pollfreewait = lib_sock_pollfreewait_forwarder;
+
+	exported->dev_create = lib_dev_create_forwarder;
+	exported->dev_destroy = lib_dev_destroy_forwarder;
+	exported->dev_get_private = lib_dev_get_private;
+	exported->dev_set_address = lib_dev_set_address_forwarder;
+	exported->dev_set_mtu = lib_dev_set_mtu_forwarder;
+	exported->dev_create_packet = lib_dev_create_packet_forwarder;
+	exported->dev_rx = lib_dev_rx_forwarder;
+
+	exported->sys_iterate_files = lib_sys_iterate_files_forwarder;
+	exported->sys_file_write = lib_sys_file_write_forwarder;
+	exported->sys_file_read = lib_sys_file_read_forwarder;
+
+	pr_notice("%s", linux_banner);
+
+	rcu_init();
+
+	/* in drivers/base/core.c (called normally by drivers/base/init.c) */
+	devices_init();
+	/* in lib/idr.c (called normally by init/main.c) */
+	idr_init_cache();
+	vfs_caches_init(totalram_pages);
+
+	lib_proc_net_initialize();
+
+	/* and, then, call the normal initcalls */
+	initcall_t *call;
+	extern initcall_t __initcall_start[], __initcall_end[];
+
+	call = __initcall_start;
+	do {
+		(*call)();
+		call++;
+	} while (call < __initcall_end);
+
+	/* finally, put the system in RUNNING state. */
+	system_state = SYSTEM_RUNNING;
+}
+
+int lib_vprintf(const char *str, va_list args)
+{
+	return g_imported.vprintf(g_kernel, str, args);
+}
+void *lib_malloc(unsigned long size)
+{
+	return g_imported.malloc(g_kernel, size);
+}
+void lib_free(void *buffer)
+{
+	return g_imported.free(g_kernel, buffer);
+}
+void *lib_memcpy(void *dst, const void *src, unsigned long size)
+{
+	return g_imported.memcpy(g_kernel, dst, src, size);
+}
+void *lib_memset(void *dst, char value, unsigned long size)
+{
+	return g_imported.memset(g_kernel, dst, value, size);
+}
+unsigned long lib_random(void)
+{
+	return g_imported.random(g_kernel);
+}
+void *lib_event_schedule_ns(__u64 ns, void (*fn) (void *context), void *context)
+{
+	return g_imported.event_schedule_ns(g_kernel, ns, fn, context,
+					    lib_update_jiffies);
+}
+void lib_event_cancel(void *event)
+{
+	return g_imported.event_cancel(g_kernel, event);
+}
+__u64 lib_current_ns(void)
+{
+	return g_imported.current_ns(g_kernel);
+}
+struct SimTaskTrampolineContext {
+	void (*callback)(void *);
+	void *context;
+};
+static void lib_task_start_trampoline(void *context)
+{
+	/* we use this trampoline solely for the purpose of executing
+	   lib_update_jiffies prior to calling the callback. */
+	struct SimTaskTrampolineContext *ctx = context;
+	void (*callback)(void *) = ctx->callback;
+	void *callback_context = ctx->context;
+
+	lib_free(ctx);
+	lib_update_jiffies();
+	callback(callback_context);
+}
+struct SimTask *lib_task_start(void (*callback) (void *), void *context)
+{
+	struct SimTaskTrampolineContext *ctx =
+		lib_malloc(sizeof(struct SimTaskTrampolineContext));
+
+	if (!ctx)
+		return NULL;
+	ctx->callback = callback;
+	ctx->context = context;
+	return g_imported.task_start(g_kernel, &lib_task_start_trampoline, ctx);
+}
+void lib_task_wait(void)
+{
+	rcu_sched_qs();
+	g_imported.task_wait(g_kernel);
+	lib_update_jiffies();
+}
+struct SimTask *lib_task_current(void)
+{
+	return g_imported.task_current(g_kernel);
+}
+int lib_task_wakeup(struct SimTask *task)
+{
+	return g_imported.task_wakeup(g_kernel, task);
+}
+void lib_task_yield(void)
+{
+	rcu_idle_enter();
+	g_imported.task_yield(g_kernel);
+	rcu_idle_exit();
+	lib_update_jiffies();
+}
+
+void lib_dev_xmit(struct SimDevice *dev, unsigned char *data, int len)
+{
+	return g_imported.dev_xmit(g_kernel, dev, data, len);
+}
+
+void lib_signal_raised(struct SimTask *task, int sig)
+{
+	g_imported.signal_raised(g_kernel, task, sig);
+}
+
+void lib_poll_event(int flag, void *context)
+{
+	g_imported.poll_event(flag, context);
+}
diff --git a/arch/lib/lib.h b/arch/lib/lib.h
new file mode 100644
index 0000000..abf2a26
--- /dev/null
+++ b/arch/lib/lib.h
@@ -0,0 +1,21 @@
+/*
+ * library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ *         Frederic Urbani
+ */
+
+#ifndef LIB_H
+#define LIB_H
+
+#include <linux/sched.h>
+
+struct SimTask {
+	struct list_head head;
+	struct task_struct kernel_task;
+	void *private;
+};
+
+#endif /* LIB_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 117+ messages in thread

* [PATCH v4 04/10] lib: time handling (kernel glue code)
  2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
                         ` (2 preceding siblings ...)
  2015-04-27  3:00       ` [PATCH v4 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
@ 2015-04-27  3:00       ` Hajime Tazaki
  2015-04-27  3:00       ` [PATCH v4 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
                         ` (7 subsequent siblings)
  11 siblings, 0 replies; 117+ messages in thread
From: Hajime Tazaki @ 2015-04-27  3:00 UTC (permalink / raw)
  To: linux-arch
  Cc: Hajime Tazaki, Arnd Bergmann, Jonathan Corbet, Christoph Lameter,
	Jekka Enberg, Javid Rientjes, Joonsoo Kim, Jndrew Morton,
	linux-kernel, linux-doc, netdev, linux-mm, Jeff Dike,
	Richard Weinberger, Rusty Russell, Ryo Nakamura,
	Christoph Paasch, Mathieu Lacage, libos-nuse

timer related (internal) functions such as add_timer(),
do_gettimeofday() of kernel are trivially reimplemented
for libos. these eventually call the functions registered by lib_init()
API.

Signed-off-by: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
---
 arch/lib/hrtimer.c         | 122 +++++++++++++++++++++++
 arch/lib/tasklet-hrtimer.c |  57 +++++++++++
 arch/lib/time.c            | 144 +++++++++++++++++++++++++++
 arch/lib/timer.c           | 238 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 561 insertions(+)
 create mode 100644 arch/lib/hrtimer.c
 create mode 100644 arch/lib/tasklet-hrtimer.c
 create mode 100644 arch/lib/time.c
 create mode 100644 arch/lib/timer.c

diff --git a/arch/lib/hrtimer.c b/arch/lib/hrtimer.c
new file mode 100644
index 0000000..4565b59
--- /dev/null
+++ b/arch/lib/hrtimer.c
@@ -0,0 +1,122 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/hrtimer.h>
+#include "sim-assert.h"
+#include "sim.h"
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ * @timer:      the timer to be initialized
+ * @clock_id:   the clock to be used
+ * @mode:       timer mode abs/rel
+ */
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+		  enum hrtimer_mode mode)
+{
+	memset(timer, 0, sizeof(*timer));
+}
+static void trampoline(void *context)
+{
+	struct hrtimer *timer = context;
+	enum hrtimer_restart restart = timer->function(timer);
+
+	if (restart == HRTIMER_RESTART) {
+		void *event =
+			lib_event_schedule_ns(ktime_to_ns(timer->_softexpires),
+					      &trampoline, timer);
+		timer->base = event;
+	} else {
+		/* mark as completed. */
+		timer->base = 0;
+	}
+}
+/**
+ * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
+ * @timer:      the timer to be added
+ * @tim:        expiry time
+ * @delta_ns:   "slack" range for the timer
+ * @mode:       expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
+ *
+ * Returns:
+ *  0 on success
+ *  1 when the timer was active
+ */
+int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			     unsigned long delta_ns,
+			     const enum hrtimer_mode mode,
+			     int wakeup)
+{
+	int ret = hrtimer_cancel(timer);
+	s64 ns = ktime_to_ns(tim);
+	void *event;
+
+	if (mode == HRTIMER_MODE_ABS)
+		ns -= lib_current_ns();
+	timer->_softexpires = ns_to_ktime(ns);
+	event = lib_event_schedule_ns(ns, &trampoline, timer);
+	timer->base = event;
+	return ret;
+}
+/**
+ * hrtimer_try_to_cancel - try to deactivate a timer
+ * @timer:      hrtimer to stop
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ * -1 when the timer is currently excuting the callback function and
+ *    cannot be stopped
+ */
+int hrtimer_try_to_cancel(struct hrtimer *timer)
+{
+	/* Note: we cannot return -1 from this function.
+	   see comment in hrtimer_cancel. */
+	if (timer->base == 0)
+		/* timer was not active yet */
+		return 1;
+	lib_event_cancel(timer->base);
+	timer->base = 0;
+	return 0;
+}
+/**
+ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
+ * @timer:      the timer to be cancelled
+ *
+ * Returns:
+ *  0 when the timer was not active
+ *  1 when the timer was active
+ */
+int hrtimer_cancel(struct hrtimer *timer)
+{
+	/* Note: because we assume a uniprocessor non-interruptible */
+	/* system when running in the kernel, we know that the timer */
+	/* is not running when we execute this code, so, know that */
+	/* try_to_cancel cannot return -1 and we don't need to retry */
+	/* the cancel later to wait for the handler to finish. */
+	int ret = hrtimer_try_to_cancel(timer);
+
+	lib_assert(ret >= 0);
+	return ret;
+}
+int
+hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
+}
+int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			   unsigned long delta_ns, const enum hrtimer_mode mode)
+{
+	return __hrtimer_start_range_ns(timer, tim, delta_ns, mode, 1);
+}
+
+int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+{
+	*tp = ns_to_timespec(1);
+	return 0;
+}
diff --git a/arch/lib/tasklet-hrtimer.c b/arch/lib/tasklet-hrtimer.c
new file mode 100644
index 0000000..fef4902
--- /dev/null
+++ b/arch/lib/tasklet-hrtimer.c
@@ -0,0 +1,57 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/interrupt.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
+{
+	struct tasklet_hrtimer *ttimer =
+		container_of(timer, struct tasklet_hrtimer, timer);
+
+	tasklet_schedule(&ttimer->tasklet);
+	return HRTIMER_NORESTART;
+}
+static void __tasklet_hrtimer_trampoline(unsigned long data)
+{
+	struct tasklet_hrtimer *ttimer = (void *)data;
+	enum hrtimer_restart restart;
+
+	restart = ttimer->function(&ttimer->timer);
+	if (restart != HRTIMER_NORESTART)
+		hrtimer_restart(&ttimer->timer);
+}
+/**
+ * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
+ * @ttimer:      tasklet_hrtimer which is initialized
+ * @function:    hrtimer callback function which gets called from softirq context
+ * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
+ * @mode:        hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
+ */
+void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+			  enum hrtimer_restart (*function)(struct hrtimer *),
+			  clockid_t which_clock, enum hrtimer_mode mode)
+{
+	hrtimer_init(&ttimer->timer, which_clock, mode);
+	ttimer->timer.function = __hrtimer_tasklet_trampoline;
+	tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
+		     (unsigned long)ttimer);
+	ttimer->function = function;
+}
+
+void __tasklet_hi_schedule(struct tasklet_struct *t)
+{
+	/* Note: no need to set TASKLET_STATE_SCHED because
+	   it is set by caller. */
+	lib_assert(t->next == 0);
+	/* run the tasklet at the next immediately available opportunity. */
+	void *event =
+		lib_event_schedule_ns(0, (void *)&t->func, (void *)t->data);
+	t->next = event;
+}
diff --git a/arch/lib/time.c b/arch/lib/time.c
new file mode 100644
index 0000000..b54be75
--- /dev/null
+++ b/arch/lib/time.c
@@ -0,0 +1,144 @@
+/*
+ * glue code for library version of Linux kernel
+ * Copyright (c) 2015 INRIA, Hajime Tazaki
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@gmail.com>
+ *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
+ */
+
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/ktime.h>
+#include "sim.h"
+#include "sim-assert.h"
+
+unsigned long volatile jiffies = INITIAL_JIFFIES;
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+struct timespec xtime;
+seqlock_t xtime_lock;
+/* accessed from wrap_clock from do_sys_settimeofday.
+   We don't call the latter so we should never access this variable. */
+struct timespec wall_to_monotonic;
+
+uint64_t ns_to_jiffies(uint64_t ns)
+{
+	do_div(ns, (1000000000 / HZ));
+	return ns;
+}
+
+void lib_update_jiffies(void)
+{
+	jiffies = ns_to_jiffies(lib_current_ns());
+	jiffies_64 = ns_to_jiffies(lib_current_ns());
+}
+
+struct timespec current_kernel_time(void)
+{
+	u64 ns = lib_current_ns();
+	struct timespec spec = ns_to_timespec(ns);
+
+	return spec;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	u64 ns = lib_current_ns();
+
+	*tv = ns_to_timeval(ns);
+}
+
+int do_adjtimex(struct timex *timex)
+{
+	lib_assert(false);
+	return -EPERM;
+}
+ktime_t ktime_get(void)
+{
+	u64 ns = lib_current_ns();
+
+	return ns_to_ktime(ns);
+}
+ktime_t ktime_get_with_offset(enum tk_offsets offs)
+{
+	/* FIXME */
+	return ktime_get();
+}
+
+/* copied from kernel/time/hrtimeer.c */
+#if BITS_PER_LONG < 64
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+u64 __ktime_divns(const ktime_t kt, s64 div)
+{
+	u64 dclc;
+	int sft = 0;
+
+	dclc = ktime_to_ns(kt);
+	/* Make sure the divisor is less than 2^32: */
+	while (div >> 32) {
+		sft++;
+		div >>= 1;
+	}
+	dclc >>= sft;
+	do_div(dclc, (unsigned long)div);
+
+	return dclc;
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+void update_xtime_cache(u64 nsec)
+{
+}
+unsigned long get_seconds(void)
+{
+	u64 ns = lib_current_ns();
+
+	do_div(ns, 1000000000);
+	return ns;
+}
+static unsigned long