Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1218279 > unrolled thread

[PATCH v6 00/10] an introduction of Linux library operating system (LibOS)

Started byHajime Tazaki <thehajime@gmail.com>
First post2015-09-03 16:20 +0200
Last post2015-09-03 16:30 +0200
Articles 9 — 1 participant

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH v6 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 07/10] lib: other kernel glue layer code Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 10/10] lib: tools used for test scripts Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 09/10] lib: libos build scripts and documentation Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 02/10] slab: add SLIB (Library memory allocator) for  arch/lib Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:20 +0200
    [PATCH v6 04/10] lib: time handling (kernel glue code) Hajime Tazaki <thehajime@gmail.com> - 2015-09-03 16:30 +0200

#1218279 — [PATCH v6 00/10] an introduction of Linux library operating system (LibOS)

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 00/10] an introduction of Linux library operating system (LibOS)
Message-ID<q4DwS-5Yk-11@gated-at.bofh.it>
Although I've been kept quiet, I'm preparing this 6th version of Linux
LibOS patchset.

During the time, I've observed the growth of our branch and seen two
good news regarding the maintenance overhead and benefit of libos patches.

* news 1

To answer the following suggestion raised by Richard Weinberger, I've
observed the maintenance burden (manual modification, follow stub
function signature, etc) which we were worried about.

> 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.


here is the list of commits which I updated stub functions since
around 4.0 release. As I mentioned, each of stub functions updates are
mostly happened during merge window and those are 2 to 5. We may see
similar numbers in coming the 4.3 version.

4.1-4.2
- 2000c14 lib: fix the signature of vfs_caches_init() (4.2-rc6)
- 576b8d7 lib: fix new proc behavior for emulated proc files (4.2-rc1)
- b72596c lib: fix workqueue stub for new header (4.2-rc1)
- 06289a2 merge conflicts (MAINTAINERS) (4.2-rc1)
- 12c0b79 lib: fix new signature of struct timer_list (4.2-rc0)
4.0-4.1
- acbf6ed lib: fix __ktime_divns() to latest update (4.1-rc7)
- 0fe9ba4 lib: merge fix from net-next around 4.0.0-next (4.1-rc0)
- 070691d lib: fix new sock_sendmsg() API (4.1-rc0)
3.19-4.0
- 609d8c7 lib: adapt linux-4.0.0-rc7
- 796347a lib: adapt linux-4.0.0-rc5

the full list of commit history can be found below, which also
includes other commits of libos enhancements.

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

Considering the number of commits in Linus tree since v4.0 to now
(4.2+) is around 29K, I think the number of stubs update (in libos) is
not that big matter.

I believe saying something with the-number-of-commits makes almost
zero sense, but will help to smell something a bit.

I would like to hear your honest opinions.


* news 2
on the other hand, I also have a good news which libos has detected a
couple of regressions in net-next tree.

- [net-next,v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface. (v4.2-rc0)
 patchwork:
 http://patchwork.ozlabs.org/patch/493675/
 detected by:
 http://ns-3-dce.cloud.wide.ad.jp/jenkins/job/daily-net-next-sim/958/

- [v3] ipv6: Fix protocol resubmission (v4.1-rc7)
 patchwork:
 http://patchwork.ozlabs.org/patch/482645/
 detected by:
 http://ns-3-dce.cloud.wide.ad.jp/jenkins/job/umip-net-next/716/

- [net-next] ipv6: Check RTF_LOCAL on rt->rt6i_flags instead of rt->dst.flags
 patchwork:
 http://patchwork.ozlabs.org/patch/467447/
 detected by:
 http://ns-3-dce.cloud.wide.ad.jp/jenkins/job/daily-net-next-sim/878/

- [net-next] xfrm6: Fix a offset value for network header in _decode_session6 (v3.19-rc7?)
 patchwork:
 http://patchwork.ozlabs.org/patch/436351/

some of detected bugs with other tests like kbuild test robot are not
included: above bugs purely require real and (sometimes) complex
setup, which DCE (libos) eases with the virtualized environment.



changes from v5:
- Patch 09/10 ("lib: libos build scripts and documentation")
1) introduce symbol namespace for the symbols in Linux libos to avoid conflicts
- Patch 04/10 ("lib: time handling (kernel glue code)")
2) lib: un-stub timekeeping code and reuse timekeeping.c and co.
- Overall
3) rebased to Linux 4.2+ (revision 1e1a4e8f439113b7820bc7150569f685e1cc2b43)

changes from v4:
- Patch 09/10 ("lib: libos build scripts and documentation")
1) lib: fix dependency detection of kernel/time/timeconst.h
   (commented by Richard Weinberger)
- Overall
2) rebased to Linux 4.1-rc3 (4cfceaf0c087f47033f5e61a801f4136d6fb68c6)

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
-----------------
[v5] : https://lkml.org/lkml/2015/5/13/25
[v4] : https://lkml.org/lkml/2015/4/26/279
[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
personality 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 an 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-v6


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: auxiliary 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                     | 235 ++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/capability.c                 |  25 ++
 arch/lib/defconfig                    | 655 ++++++++++++++++++++++++++++++++++
 arch/lib/filemap.c                    |  32 ++
 arch/lib/fs.c                         |  70 ++++
 arch/lib/generate-linker-script.py    |  50 +++
 arch/lib/glue.c                       | 284 +++++++++++++++
 arch/lib/hrtimer.c                    | 117 ++++++
 arch/lib/include/asm/Kbuild           |  57 +++
 arch/lib/include/asm/atomic.h         |  62 ++++
 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                 | 370 +++++++++++++++++++
 arch/lib/lib.c                        | 296 +++++++++++++++
 arch/lib/lib.h                        |  21 ++
 arch/lib/modules.c                    |  36 ++
 arch/lib/pid.c                        |  29 ++
 arch/lib/print.c                      |  56 +++
 arch/lib/proc.c                       |  36 ++
 arch/lib/random.c                     |  54 +++
 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                       | 116 ++++++
 arch/lib/timer.c                      | 299 ++++++++++++++++
 arch/lib/vmscan.c                     |  26 ++
 arch/lib/workqueue.c                  | 238 ++++++++++++
 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                             | 209 +++++++++++
 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, 5573 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

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

[toc] | [next] | [standalone]


#1218280 — [PATCH v6 05/10] lib: context and scheduling functions (kernel glue code) for libos

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 05/10] lib: context and scheduling functions (kernel glue code) for libos
Message-ID<q4DwS-5Yk-17@gated-at.bofh.it>
In reply to#1218279
context primitives of kernel such as soft interrupts, scheduling,
tasklet are implemented for libos. these functions eventually call the
functions registered by lib_init() API as well.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
---
 arch/lib/sched.c     | 406 +++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/softirq.c   | 108 ++++++++++++++
 arch/lib/tasklet.c   |  76 ++++++++++
 arch/lib/workqueue.c | 238 ++++++++++++++++++++++++++++++
 4 files changed, 828 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 000000000000..98a568a16903
--- /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 000000000000..3f6363a70317
--- /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 000000000000..6cc68f4a1a1d
--- /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 000000000000..2f835d300cbc
--- /dev/null
+++ b/arch/lib/workqueue.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/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;
+}
+
+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

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

[toc] | [prev] | [next] | [standalone]


#1218281 — [PATCH v6 07/10] lib: other kernel glue layer code

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 07/10] lib: other kernel glue layer code
Message-ID<q4DwS-5Yk-19@gated-at.bofh.it>
In reply to#1218279
These files are used to provide the same function calls so that other
network stack code keeps untouched.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Christoph Paasch <christoph.paasch@gmail.com>
---
 arch/lib/capability.c |  25 +++++
 arch/lib/filemap.c    |  32 ++++++
 arch/lib/fs.c         |  70 +++++++++++++
 arch/lib/glue.c       | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/lib/modules.c    |  36 +++++++
 arch/lib/pid.c        |  29 ++++++
 arch/lib/print.c      |  56 ++++++++++
 arch/lib/proc.c       |  36 +++++++
 arch/lib/random.c     |  54 ++++++++++
 arch/lib/sysfs.c      |  83 +++++++++++++++
 arch/lib/vmscan.c     |  26 +++++
 11 files changed, 731 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 000000000000..3a1f30129fb7
--- /dev/null
+++ b/arch/lib/capability.c
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	return 0;
+}
+
+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 000000000000..ce424ffae8c2
--- /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 000000000000..33efe5f1da32
--- /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 65535;
+}
diff --git a/arch/lib/glue.c b/arch/lib/glue.c
new file mode 100644
index 000000000000..bdbed913ee9e
--- /dev/null
+++ b/arch/lib/glue.c
@@ -0,0 +1,284 @@
+/*
+ * 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;
+
+/* defined in sched.c, used in net/sched/em_meta.c */
+unsigned long avenrun[3];
+/* 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 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;
+}
+
+int sysctl_max_threads(struct ctl_table *table, int write,
+		       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	return 1;
+}
+
+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 000000000000..ca43fdc691b0
--- /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 000000000000..00cf7b620c43
--- /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 000000000000..09b1bb54790a
--- /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 000000000000..3183d05f2c91
--- /dev/null
+++ b/arch/lib/proc.c
@@ -0,0 +1,36 @@
+/*
+ * 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;
+extern const struct inode_operations proc_link_inode_operations;
+
+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;
+	proc_root_sim->proc_iops = &proc_link_inode_operations;
+	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 000000000000..282678d31f03
--- /dev/null
+++ b/arch/lib/random.c
@@ -0,0 +1,54 @@
+/*
+ * 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 000000000000..2def2caab454
--- /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 000000000000..3132f66d5085
--- /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

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

[toc] | [prev] | [next] | [standalone]


#1218284 — [PATCH v6 10/10] lib: tools used for test scripts

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 10/10] lib: tools used for test scripts
Message-ID<q4DwT-5Yk-31@gated-at.bofh.it>
In reply to#1218279
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 <thehajime@gmail.com>
---
 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 000000000000..57a74a05482c
--- /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 000000000000..a27eb84e7712
--- /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 $(BAKEBUILD_PARAMS)
+
+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 000000000000..51ac5a52336e
--- /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 000000000000..9377ac3214c1
--- /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 000000000000..e81e2d84c156
--- /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 000000000000..198e7e4c66ac
--- /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

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

[toc] | [prev] | [next] | [standalone]


#1218285 — [PATCH v6 03/10] lib: public headers and API implementations for userspace programs

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 03/10] lib: public headers and API implementations for userspace programs
Message-ID<q4DwT-5Yk-37@gated-at.bofh.it>
In reply to#1218279
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 <thehajime@gmail.com>
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         | 370 ++++++++++++++++++++++++++++++++++++++++++
 arch/lib/lib.c                | 296 +++++++++++++++++++++++++++++++++
 arch/lib/lib.h                |  21 +++
 9 files changed, 1148 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 000000000000..974122c3a0f1
--- /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 000000000000..e871a594b82c
--- /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 000000000000..2bf82451cfa8
--- /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 000000000000..d50b99b26d71
--- /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 000000000000..b30d7e878325
--- /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 000000000000..1efa64607d77
--- /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 000000000000..75760c774288
--- /dev/null
+++ b/arch/lib/lib-socket.c
@@ -0,0 +1,370 @@
+/*
+ * 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;
+}
+
+/**
+ * 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 000000000000..10879aecff6c
--- /dev/null
+++ b/arch/lib/lib.c
@@ -0,0 +1,296 @@
+/*
+ * 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();
+	buses_init();
+	timekeeping_init();
+	/* in lib/idr.c (called normally by init/main.c) */
+	idr_init_cache();
+	vfs_caches_init();
+
+	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 000000000000..abf2a2628bb2
--- /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

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

[toc] | [prev] | [next] | [standalone]


#1218286 — [PATCH v6 09/10] lib: libos build scripts and documentation

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 09/10] lib: libos build scripts and documentation
Message-ID<q4DwT-5Yk-29@gated-at.bofh.it>
In reply to#1218279
document and build scripts for libos architecture.

Signed-off-by: Hajime Tazaki <thehajime@gmail.com>
Signed-off-by: Ryo Nakamura <upa@haeena.net>
---
 Documentation/virtual/libos-howto.txt | 144 ++++++++
 MAINTAINERS                           |   9 +
 arch/lib/.gitignore                   |   3 +
 arch/lib/Kconfig                      | 124 +++++++
 arch/lib/Makefile                     | 235 ++++++++++++
 arch/lib/Makefile.print               |  45 +++
 arch/lib/defconfig                    | 655 ++++++++++++++++++++++++++++++++++
 arch/lib/generate-linker-script.py    |  50 +++
 8 files changed, 1265 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

diff --git a/Documentation/virtual/libos-howto.txt b/Documentation/virtual/libos-howto.txt
new file mode 100644
index 000000000000..fbf7946f42ef
--- /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 4be7e5e7e9f9..b919060c9821 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6197,6 +6197,15 @@ S:	Supported
 F:	drivers/nvdimm/pmem.c
 F:	include/linux/pmem.h
 
+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 000000000000..4370d48271cb
--- /dev/null
+++ b/arch/lib/.gitignore
@@ -0,0 +1,3 @@
+linker.lds
+objs.mk
+tools
diff --git a/arch/lib/Kconfig b/arch/lib/Kconfig
new file mode 100644
index 000000000000..eef92af0e711
--- /dev/null
+++ b/arch/lib/Kconfig
@@ -0,0 +1,124 @@
+mainmenu "Linux Library OS (libos) $KERNELVERSION Configuration"
+
+config LIB
+       def_bool y
+       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 ARCH
+	string
+	option env="ARCH"
+
+config KERNELVERSION
+	string
+	option env="KERNELVERSION"
+
+config MODULES
+	def_bool y
+	option modules
+
+config MMU
+        def_bool n
+
+config FPU
+        def_bool n
+
+config SMP
+        def_bool n
+
+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_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 MULTIUSER
+       def_bool n
+
+config NETDEVICES
+       def_bool y
+
+source "net/Kconfig"
+
+source "drivers/base/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+config SLIB
+       def_bool y
\ No newline at end of file
diff --git a/arch/lib/Makefile b/arch/lib/Makefile
new file mode 100644
index 000000000000..e287005addb6
--- /dev/null
+++ b/arch/lib/Makefile
@@ -0,0 +1,235 @@
+ARCH_DIR := arch/lib
+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
+
+# 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=include/generated/compile.h include/generated/bounds.h \
+	include/generated/timeconst.h lib/crc32table.h $(ARCH_DIR)/linker.lds
+
+# 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)
+
+# 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 ($(SUBARCH),x86)
+  ifeq ($(shell uname -m),x86_64)
+	CFLAGS+= -DCONFIG_64BIT
+  endif
+endif
+
+KBUILD_CFLAGS := CFLAGS
+LDFLAGS += -shared -nodefaultlibs -lgcc_s -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 timekeeping.o jiffies.o clocksource.o ntp.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 rng.o
+drivers/base/_to_keep=class.o core.o bus.o dd.o driver.o devres.o module.o map.o syscore.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_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_linker = GEN     $@
+      cmd_linker = ld -shared --verbose | ./$^ > $@
+$(ARCH_DIR)/linker.lds: $(ARCH_DIR)/generate-linker-script.py
+	$(call if_changed,linker)
+
+# calll kernel/time/Makefile
+include/generated/timeconst.h: $(srctree)/.config
+	$(Q) $(MAKE) $(build)=. $@
+
+# call lib/Makefile
+lib/crc32table.h:
+	$(Q) $(MAKE) $(build)=lib $@
+
+# call init/Makefile
+include/generated/compile.h: asm-generic include/generated/utsrelease.h\
+	 $(version_h)
+	$(Q) $(MAKE) $(build)=init $@
+
+# 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
+
+include/generated/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
+
+# objcopy trick is taken from rumpkernel
+GCCSYMBOLS=__umoddi3|__udivdi3
+EXP_SYMRENAME=rump|RUMP|lib_|g_imported|g_kernel|__initcall_start|__initcall_end|__gcov|_end|_GLOBAL_OFFSET_TABLE|${GCCSYMBOLS}'${_SYMQUIRK}'${RUMP_SYM_NORENAME:D|${RUMP_SYM_NORENAME}}
+
+quiet_cmd_cc = CC      $@
+      cmd_cc = 	mkdir -p $(dir $@);	\
+		$(CC) $(CFLAGS) -c $< -o $@; \
+		${NM} -go $@ | awk ' \
+		$$NF!~/^'${_PQ}'(${EXP_SYMRENAME})/ \
+		{s=$$NF;sub(/^'${_PQ}'/, "&rumpns_", s); print $$NF, s}'\
+		| sort | uniq  > $@.renametab; \
+		objcopy --preserve-dates --redefine-syms $@.renametab $@; \
+		rm -f $@.renametab
+
+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 $(AUTOGENS)
+	$(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)
+
+archprepare: include/generated/bounds.h include/generated/utsrelease.h \
+	asm-generic $(version_h)
+
+test:
+	$(Q) $(MAKE) -C $(DCE_TESTDIR)/
+
+.PHONY : clean
diff --git a/arch/lib/Makefile.print b/arch/lib/Makefile.print
new file mode 100644
index 000000000000..8585fc841e39
--- /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:=$(shell echo $(filter %/, $(obj-y) $(obj-m)) | tr ' ' '\n' | sort -u | tr '\n' ' ')
+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 000000000000..7fab6d9c3930
--- /dev/null
+++ b/arch/lib/defconfig
@@ -0,0 +1,655 @@
+#
+# 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=y
+CONFIG_NET_FOU=y
+CONFIG_NET_FOU_IP_TUNNELS=y
+# 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=y
+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=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+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 000000000000..db3d7f8dab16
--- /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)
-- 
2.1.0

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

[toc] | [prev] | [next] | [standalone]


#1218287 — [PATCH v6 02/10] slab: add SLIB (Library memory allocator) for arch/lib

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 02/10] slab: add SLIB (Library memory allocator) for arch/lib
Message-ID<q4DwT-5Yk-49@gated-at.bofh.it>
In reply to#1218279
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 <thehajime@gmail.com>
---
 include/linux/slab.h     |   6 +-
 include/linux/slib_def.h |  21 +++++
 mm/Makefile              |   1 +
 mm/slab.h                |   4 +
 mm/slib.c                | 209 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 240 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 a99f0e5243e1..104c1aeec560 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 000000000000..d9fe7d59bd4e
--- /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 98c4eaeabdcb..7d8314f95ce3 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 8da63e4e470f..2cf4f0f67a19 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 000000000000..974c8aed0275
--- /dev/null
+++ b/mm/slib.c
@@ -0,0 +1,209 @@
+/*
+ * 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 __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+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

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

[toc] | [prev] | [next] | [standalone]


#1218288 — [PATCH v6 01/10] sysctl: make some functions unstatic to access by arch/lib

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:20 +0200
Subject[PATCH v6 01/10] sysctl: make some functions unstatic to access by arch/lib
Message-ID<q4DwT-5Yk-51@gated-at.bofh.it>
In reply to#1218279
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 <thehajime@gmail.com>
---
 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 fdda62e6115e..e1003cf51d22 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -57,7 +57,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,
@@ -99,8 +99,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;
@@ -335,7 +336,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
@@ -356,7 +357,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;
@@ -374,7 +375,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;
@@ -707,7 +708,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;
@@ -865,7 +867,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))
@@ -961,13 +963,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;
@@ -988,13 +990,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);
@@ -1106,7 +1108,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))
@@ -1119,7 +1121,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;
@@ -1135,7 +1137,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;
 
@@ -1516,7 +1518,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;
 
@@ -1525,7 +1527,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

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

[toc] | [prev] | [next] | [standalone]


#1218292 — [PATCH v6 04/10] lib: time handling (kernel glue code)

FromHajime Tazaki <thehajime@gmail.com>
Date2015-09-03 16:30 +0200
Subject[PATCH v6 04/10] lib: time handling (kernel glue code)
Message-ID<q4DGx-69n-9@gated-at.bofh.it>
In reply to#1218279
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 <thehajime@gmail.com>
---
 arch/lib/hrtimer.c         | 117 ++++++++++++++++++
 arch/lib/tasklet-hrtimer.c |  57 +++++++++
 arch/lib/time.c            | 116 ++++++++++++++++++
 arch/lib/timer.c           | 299 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 589 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 000000000000..6a99bad6c5b7
--- /dev/null
+++ b/arch/lib/hrtimer.c
@@ -0,0 +1,117 @@
+/*
+ * 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;
+}
+void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+			   unsigned long delta_ns, const enum hrtimer_mode mode)
+{
+	__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 000000000000..fef4902d4938
--- /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 000000000000..bc119843e0fd
--- /dev/null
+++ b/arch/lib/time.c
@@ -0,0 +1,116 @@
+/*
+ * 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());
+}
+
+/* copied from kernel/time/hrtimeer.c */
+#if BITS_PER_LONG < 64
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+s64 __ktime_divns(const ktime_t kt, s64 div)
+{
+	int sft = 0;
+	s64 dclc;
+	u64 tmp;
+
+	dclc = ktime_to_ns(kt);
+	tmp = dclc < 0 ? -dclc : dclc;
+
+	/* Make sure the divisor is less than 2^32: */
+	while (div >> 32) {
+		sft++;
+		div >>= 1;
+	}
+	tmp >>= sft;
+	do_div(tmp, (unsigned long) div);
+	return dclc < 0 ? -tmp : tmp;
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+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();
+}
+
+void read_persistent_clock(struct timespec *ts)
+{
+	u64 nsecs = lib_current_ns();
+
+	set_normalized_timespec(ts, nsecs / NSEC_PER_SEC,
+				nsecs % NSEC_PER_SEC);
+}
+
+void __init time_init(void)
+{
+}
diff --git a/arch/lib/timer.c b/arch/lib/timer.c
new file mode 100644
index 000000000000..d290e3721841
--- /dev/null
+++ b/arch/lib/timer.c
@@ -0,0 +1,299 @@
+/*
+ * 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 <linux/hash.h>
+#include <linux/hashtable.h>
+
+#include "sim-assert.h"
+#include "sim.h"
+
+static DEFINE_HASHTABLE(lib_timers_hashtable, 9);
+struct lib_timer {
+	struct timer_list *timer;
+	struct hlist_node t_hash;
+	void *event;
+};
+
+static int hash(struct timer_list *timer)
+{
+	return hash_32(hash32_ptr(timer), HASH_BITS(lib_timers_hashtable));
+}
+
+static struct lib_timer *__lib_timers_find(struct hlist_head *head,
+					   struct timer_list *timer)
+{
+	struct lib_timer *l_timer;
+
+	hlist_for_each_entry(l_timer, head, t_hash) {
+		if (l_timer->timer == timer)
+			return l_timer;
+	}
+	return NULL;
+}
+
+static struct lib_timer *lib_timer_find(struct timer_list *timer)
+{
+	struct hlist_head *head;
+
+	head = &lib_timers_hashtable[hash(timer)];
+	return __lib_timers_find(head, timer);
+}
+
+/**
+ * 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.pprev field set to NULL (timer_pending
+	 * will return 0)
+	 */
+	timer->entry.pprev = NULL;
+}
+
+struct hlist_head g_expired_events;
+struct hlist_head g_pending_events;
+
+static void run_timer_softirq(struct softirq_action *h)
+{
+	while (!hlist_empty(&g_expired_events)) {
+		struct timer_list *timer =
+			hlist_entry((&g_expired_events)->first,
+				    struct timer_list, entry);
+		void (*fn)(unsigned long);
+		unsigned long data;
+		struct lib_timer *l_timer = lib_timer_find(timer);
+
+		fn = timer->function;
+		data = timer->data;
+		lib_assert(l_timer->event == 0);
+
+		hlist_del(&timer->entry);
+		timer->entry.pprev = 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;
+	struct lib_timer *l_timer;
+
+	ensure_softirq_opened();
+	timer = context;
+
+	l_timer = lib_timer_find(timer);
+	if (l_timer)
+		l_timer->event = NULL;
+
+	if (timer->entry.pprev != 0)
+		hlist_del(&timer->entry);
+
+	timer->entry.pprev = NULL;
+	hlist_add_head(&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;
+	struct hlist_head *head;
+
+	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 hash table */
+	/* to be able to retrieve it from del_timer */
+	head = &lib_timers_hashtable[hash(timer)];
+	if (!__lib_timers_find(head, timer)) {
+		struct lib_timer *l_timer;
+
+		l_timer = lib_malloc(sizeof(struct lib_timer));
+		l_timer->timer = timer;
+		l_timer->event = event;
+		hlist_add_head(&l_timer->t_hash, head);
+	}
+
+	/* finally, store timer in list of pending events. */
+	hlist_add_head(&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;
+	struct lib_timer *l_timer;
+
+	if (timer->entry.pprev == NULL)
+		return 0;
+
+	l_timer = lib_timer_find(timer);
+	if (l_timer != NULL && l_timer->event != NULL) {
+		lib_event_cancel(l_timer->event);
+
+		if (l_timer->t_hash.next != LIST_POISON1) {
+			hlist_del(&l_timer->t_hash);
+			lib_free(l_timer);
+		}
+		retval = 1;
+	} else {
+		retval = 0;
+	}
+
+	if (timer->entry.next != LIST_POISON1)
+		hlist_del(&timer->entry);
+	timer->entry.pprev = 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

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

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web