All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
To: linux-arch@vger.kernel.org
Cc: Hajime Tazaki <tazaki@sfc.wide.ad.jp>,
	Arnd Bergmann <arnd@arndb.de>, Jonathan Corbet <corbet@lwn.net>,
	Christoph Lameter <cl@linux.com>,
	Jekka Enberg <penberg@kernel.org>,
	Javid Rientjes <rientjes@google.com>,
	Joonsoo Kim <iamjoonsoo.kim@lge.com>,
	Jndrew Morton <akpm@linux-foundation.org>,
	linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	netdev@vger.kernel.org, linux-mm@kvack.org,
	Jeff Dike <jdike@addtoit.com>,
	Richard Weinberger <richard@nod.at>,
	Rusty Russell <rusty@rustcorp.com.au>,
	Ryo Nakamura <upa@haeena.net>,
	Christoph Paasch <christoph.paasch@gmail.com>,
	Mathieu Lacage <mathieu.lacage@gmail.com>,
	libos-nuse@googlegroups.com
Subject: [PATCH v4 03/10] lib: public headers and API implementations for userspace programs
Date: Mon, 27 Apr 2015 12:00:11 +0900	[thread overview]
Message-ID: <1430103618-10832-4-git-send-email-tazaki@sfc.wide.ad.jp> (raw)
In-Reply-To: <1430103618-10832-1-git-send-email-tazaki@sfc.wide.ad.jp>

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

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

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


WARNING: multiple messages have this Message-ID (diff)
From: Hajime Tazaki <tazaki@sfc.wide.ad.jp>
To: linux-arch@vger.kernel.org
Cc: Hajime Tazaki <tazaki@sfc.wide.ad.jp>,
	Arnd Bergmann <arnd@arndb.de>, Jonathan Corbet <corbet@lwn.net>,
	Christoph Lameter <cl@linux.com>,
	Jekka Enberg <penberg@kernel.org>,
	Javid Rientjes <rientjes@google.com>,
	Joonsoo Kim <iamjoonsoo.kim@lge.com>,
	Jndrew Morton <akpm@linux-foundation.org>,
	linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	netdev@vger.kernel.org, linux-mm@kvack.org,
	Jeff Dike <jdike@addtoit.com>,
	Richard Weinberger <richard@nod.at>,
	Rusty Russell <rusty@rustcorp.com.au>,
	Ryo Nakamura <upa@haeena.net>,
	Christoph Paasch <christoph.paasch@gmail.com>,
	Mathieu Lacage <mathieu.lacage@gmail.com>,
	libos-nuse@googlegroups.com
Subject: [PATCH v4 03/10] lib: public headers and API implementations for userspace programs
Date: Mon, 27 Apr 2015 12:00:11 +0900	[thread overview]
Message-ID: <1430103618-10832-4-git-send-email-tazaki@sfc.wide.ad.jp> (raw)
In-Reply-To: <1430103618-10832-1-git-send-email-tazaki@sfc.wide.ad.jp>

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

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

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

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  parent reply	other threads:[~2015-04-27  3:04 UTC|newest]

Thread overview: 231+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-24 13:10 [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
2015-03-24 13:10 ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 16:13   ` Joe Perches
2015-03-24 16:13     ` Joe Perches
2015-03-24 16:13     ` Joe Perches
2015-03-25 15:31     ` Hajime Tazaki
2015-03-25 15:31       ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 03/11] lib: public headers and API implementations for userspace programs Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 04/11] lib: memory management (kernel glue code) Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 05/11] lib: time handling " Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 06/11] lib: context and scheduling " Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 07/11] lib: sysctl " Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 08/11] lib: other kernel glue layer code Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-29 18:17   ` Richard Weinberger
2015-03-29 18:17     ` Richard Weinberger
2015-03-31  7:36     ` Hajime Tazaki
2015-03-31  7:36       ` Hajime Tazaki
2015-04-03  1:24       ` Hajime Tazaki
2015-04-03  1:24         ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 09/11] lib: asm-generic files Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 10/11] lib: libos build scripts and documentation Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:10 ` [RFC PATCH 11/11] lib: tools used for test scripts Hajime Tazaki
2015-03-24 13:10   ` Hajime Tazaki
2015-03-24 13:21 ` [RFC PATCH 00/11] an introduction of library operating system for Linux (LibOS) Richard Weinberger
2015-03-24 13:21   ` Richard Weinberger
2015-03-24 13:21   ` Richard Weinberger
2015-03-24 13:21   ` Richard Weinberger
2015-03-24 14:25   ` Hajime Tazaki
2015-03-24 14:25     ` Hajime Tazaki
2015-03-24 14:32     ` Richard Weinberger
2015-03-24 14:32       ` Richard Weinberger
2015-03-24 15:24       ` Hajime Tazaki
2015-03-24 15:24         ` Hajime Tazaki
2015-03-24 15:27         ` Richard Weinberger
2015-03-24 15:27           ` Richard Weinberger
2015-03-25 14:48           ` Hajime Tazaki
2015-03-25 14:48             ` Hajime Tazaki
2015-03-25 22:50             ` Richard Weinberger
2015-03-25 22:50               ` Richard Weinberger
2015-03-26 16:24               ` Hajime Tazaki
2015-03-26 16:24                 ` Hajime Tazaki
2015-03-26 18:55                 ` Richard Weinberger
2015-03-26 18:55                   ` Richard Weinberger
2015-03-27  3:31                   ` Rusty Russell
2015-03-27  3:31                     ` Rusty Russell
2015-03-27  3:49                     ` Geert Uytterhoeven
2015-03-27  3:49                       ` Geert Uytterhoeven
2015-03-27  5:52                       ` Richard Weinberger
2015-03-27  5:52                         ` Richard Weinberger
2015-03-27  6:05                     ` Hajime Tazaki
2015-03-27  6:05                       ` Hajime Tazaki
2015-03-27  6:34                   ` Hajime Tazaki
2015-03-27  6:34                     ` Hajime Tazaki
2015-03-27  9:21                     ` Richard Weinberger
2015-03-27  9:21                       ` Richard Weinberger
2015-03-27 15:17                       ` Antti Kantee
2015-03-28 21:17                         ` Richard Weinberger
2015-03-29 15:36                           ` Hajime Tazaki
2015-03-29 16:47                             ` Richard Weinberger
2015-03-29 16:59                           ` Antti Kantee
2015-03-29 18:05                             ` Richard Weinberger
2015-03-29 15:06                       ` Hajime Tazaki
2015-03-29 15:06                         ` Hajime Tazaki
2015-03-30  6:41                         ` Richard Weinberger
2015-03-30  6:41                           ` Richard Weinberger
2015-03-31  7:47                           ` Hajime Tazaki
2015-03-31  7:47                             ` Hajime Tazaki
2015-04-09  8:36                             ` Richard Weinberger
2015-04-09  8:36                               ` Richard Weinberger
2015-04-14  3:20                               ` Hajime Tazaki
2015-04-14  3:20                                 ` Hajime Tazaki
2015-04-01  1:29                         ` Rusty Russell
2015-04-01  1:29                           ` Rusty Russell
2015-04-03  1:43                           ` Hajime Tazaki
2015-04-03  1:43                             ` Hajime Tazaki
2015-04-07  1:25                             ` Rusty Russell
2015-04-07  1:25                               ` Rusty Russell
2015-04-17  9:36 ` [RFC PATCH v2 " Hajime Tazaki
2015-04-17  9:36   ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 01/11] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 02/11] slab: add private memory allocator header for arch/lib Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17 12:17     ` Christoph Lameter
2015-04-17 12:17       ` Christoph Lameter
2015-04-17 12:44       ` Richard Weinberger
2015-04-17 12:44         ` Richard Weinberger
2015-04-17 15:02         ` Hajime Tazaki
2015-04-17 15:02           ` Hajime Tazaki
2015-04-17 15:08           ` Richard Weinberger
2015-04-17 15:08             ` Richard Weinberger
2015-04-17 15:27             ` Hajime Tazaki
2015-04-17 15:27               ` Hajime Tazaki
2015-04-17 22:26             ` Christoph Lameter
2015-04-17 22:26               ` Christoph Lameter
2015-04-17  9:36   ` [RFC PATCH v2 03/11] lib: public headers and API implementations for userspace programs Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 04/11] lib: memory management (kernel glue code) Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 05/11] lib: time handling " Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 06/11] lib: context and scheduling " Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 07/11] lib: sysctl " Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 08/11] lib: other kernel glue layer code Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 09/11] lib: asm-generic files Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 10/11] lib: libos build scripts and documentation Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-17  9:36   ` [RFC PATCH v2 11/11] lib: tools used for test scripts Hajime Tazaki
2015-04-17  9:36     ` Hajime Tazaki
2015-04-19 13:28   ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Hajime Tazaki
2015-04-19 13:28     ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 04/10] lib: time handling (kernel glue code) Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 06/10] lib: sysctl handling (kernel glue code) Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 07/10] lib: other kernel glue layer code Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 08/10] lib: auxially files for auto-generated asm-generic files of libos Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 09/10] lib: libos build scripts and documentation Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-20 20:43       ` Paul Bolle
2015-04-20 20:43         ` Paul Bolle
2015-04-22  5:33         ` Hajime Tazaki
2015-04-22  5:33           ` Hajime Tazaki
2015-04-19 13:28     ` [RFC PATCH v3 10/10] lib: tools used for test scripts Hajime Tazaki
2015-04-19 13:28       ` Hajime Tazaki
2015-04-24  7:40     ` [RFC PATCH v3 00/10] an introduction of library operating system for Linux (LibOS) Richard Weinberger
2015-04-24  7:40       ` Richard Weinberger
2015-04-24  8:22       ` Hajime Tazaki
2015-04-24  8:22         ` Hajime Tazaki
2015-04-24  8:59         ` Richard Weinberger
2015-04-24  8:59           ` Richard Weinberger
2015-04-24  9:50           ` Hajime Tazaki
2015-04-24  9:50             ` Hajime Tazaki
2015-04-27  3:00     ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
2015-04-27  3:00       ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` Hajime Tazaki [this message]
2015-04-27  3:00         ` [PATCH v4 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 04/10] lib: time handling (kernel glue code) Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 06/10] lib: sysctl handling (kernel glue code) Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 07/10] lib: other kernel glue layer code Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 08/10] lib: auxially files for auto-generated asm-generic files of libos Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 09/10] lib: libos build scripts and documentation Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  3:00       ` [PATCH v4 10/10] lib: tools used for test scripts Hajime Tazaki
2015-04-27  3:00         ` Hajime Tazaki
2015-04-27  7:29       ` [PATCH v4 00/10] an introduction of Linux library operating system (LibOS) Richard Weinberger
2015-04-27  7:29         ` Richard Weinberger
2015-04-27  7:39         ` Richard Weinberger
2015-04-27  7:39           ` Richard Weinberger
2015-04-29 23:16           ` Hajime Tazaki
2015-04-29 23:16             ` Hajime Tazaki
2015-05-13  5:28       ` [PATCH v5 " Hajime Tazaki
2015-05-13  5:28         ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 04/10] lib: time handling (kernel glue code) Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 06/10] lib: sysctl handling (kernel glue code) Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 07/10] lib: other kernel glue layer code Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 08/10] lib: auxiliary files for auto-generated asm-generic files of libos Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 09/10] lib: libos build scripts and documentation Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-05-13  5:28         ` [PATCH v5 10/10] lib: tools used for test scripts Hajime Tazaki
2015-05-13  5:28           ` Hajime Tazaki
2015-09-03 14:16         ` [PATCH v6 00/10] an introduction of Linux library operating system (LibOS) Hajime Tazaki
2015-09-03 14:16           ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 01/10] sysctl: make some functions unstatic to access by arch/lib Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 02/10] slab: add SLIB (Library memory allocator) for arch/lib Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 03/10] lib: public headers and API implementations for userspace programs Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 04/10] lib: time handling (kernel glue code) Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 05/10] lib: context and scheduling functions (kernel glue code) for libos Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 06/10] lib: sysctl handling (kernel glue code) Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 07/10] lib: other kernel glue layer code Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 08/10] lib: auxiliary files for auto-generated asm-generic files of libos Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 09/10] lib: libos build scripts and documentation Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki
2015-09-03 14:16           ` [PATCH v6 10/10] lib: tools used for test scripts Hajime Tazaki
2015-09-03 14:16             ` Hajime Tazaki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430103618-10832-4-git-send-email-tazaki@sfc.wide.ad.jp \
    --to=tazaki@sfc.wide.ad.jp \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=christoph.paasch@gmail.com \
    --cc=cl@linux.com \
    --cc=corbet@lwn.net \
    --cc=iamjoonsoo.kim@lge.com \
    --cc=jdike@addtoit.com \
    --cc=libos-nuse@googlegroups.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mathieu.lacage@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=penberg@kernel.org \
    --cc=richard@nod.at \
    --cc=rientjes@google.com \
    --cc=rusty@rustcorp.com.au \
    --cc=upa@haeena.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.