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


Groups > linux.kernel > #1261858 > unrolled thread

[RFC PATCH 00/28] Linux Kernel Library

Started byOctavian Purdila <octavian.purdila@intel.com>
First post2015-11-03 21:30 +0100
Last post2015-11-08 14:50 +0100
Articles 20 on this page of 42 — 7 participants

Back to article view | Back to linux.kernel


Contents

  [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 21/28] lkl tools: host lib: posix host operations Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
      Re: [RFC PATCH 21/28] lkl tools: host lib: posix host operations Arnd Bergmann <arnd@arndb.de> - 2015-11-08 00:20 +0100
        Re: [RFC PATCH 21/28] lkl tools: host lib: posix host operations Octavian Purdila <octavian.purdila@intel.com> - 2015-11-08 05:10 +0100
          Re: [RFC PATCH 21/28] lkl tools: host lib: posix host operations Arnd Bergmann <arnd@arndb.de> - 2015-11-08 11:40 +0100
    [RFC PATCH 18/28] lkl tools: host lib: virtio devices Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 19/28] lkl tools: host lib: virtio block device Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
      Re: [RFC PATCH 19/28] lkl tools: host lib: virtio block device Richard Weinberger <richard.weinberger@gmail.com> - 2015-11-07 13:30 +0100
        Re: [RFC PATCH 19/28] lkl tools: host lib: virtio block device Octavian Purdila <octavian.purdila@intel.com> - 2015-11-08 05:20 +0100
          Re: [RFC PATCH 19/28] lkl tools: host lib: virtio block device Richard Weinberger <richard@nod.at> - 2015-11-08 14:40 +0100
    [RFC PATCH 13/28] lkl: initialization and cleanup Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 20/28] lkl tools: host lib: filesystem helpers Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 24/28] lkl tools: tool that reads/writes to/from a filesystem image Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 22/28] lkl tools: "boot" test Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 02/28] kbuild: allow architectures to automatically define kconfig symbols Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 17/28] lkl tools: host lib: memory mapped I/O helpers Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 28/28] lkl tools: add support for Windows host Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 09/28] lkl: timers, time and delay support Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 16/28] lkl tools: host lib: add lkl_strerror and lkl_printf Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:30 +0100
    [RFC PATCH 01/28] asm-generic: atomic64: allow using generic atomic64 on 64bit platforms Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:40 +0100
    [RFC PATCH 04/28] lkl: host interface Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:40 +0100
      Re: [RFC PATCH 04/28] lkl: host interface Hajime Tazaki <thehajime@gmail.com> - 2015-11-04 00:40 +0100
    [RFC PATCH 05/28] lkl: memory handling Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:40 +0100
    [RFC PATCH 07/28] lkl: interrupt support Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:40 +0100
    [RFC PATCH 06/28] lkl: kernel threads support Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:40 +0100
    [RFC PATCH 03/28] lkl: architecture skeleton for Linux kernel library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-03 21:40 +0100
    Re: [RFC PATCH 00/28] Linux Kernel Library Richard Weinberger <richard.weinberger@gmail.com> - 2015-11-03 22:50 +0100
      Re: [RFC PATCH 00/28] Linux Kernel Library "Richard W.M. Jones" <rjones@redhat.com> - 2015-11-03 23:50 +0100
        Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-04 00:30 +0100
          Re: [RFC PATCH 00/28] Linux Kernel Library Austin S Hemmelgarn <ahferroin7@gmail.com> - 2015-11-04 14:30 +0100
          Re: [RFC PATCH 00/28] Linux Kernel Library "Richard W.M. Jones" <rjones@redhat.com> - 2015-11-04 15:00 +0100
            Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-04 15:30 +0100
              Re: [RFC PATCH 00/28] Linux Kernel Library Richard Weinberger <richard@nod.at> - 2015-11-07 01:40 +0100
                Re: [RFC PATCH 00/28] Linux Kernel Library "Richard W.M. Jones" <rjones@redhat.com> - 2015-11-07 08:20 +0100
                Re: [RFC PATCH 00/28] Linux Kernel Library "Richard W.M. Jones" <rjones@redhat.com> - 2015-11-07 11:50 +0100
                  Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-09 17:40 +0100
                Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-08 05:20 +0100
                Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-08 05:40 +0100
        Re: [RFC PATCH 00/28] Linux Kernel Library Hajime Tazaki <thehajime@gmail.com> - 2015-11-04 00:30 +0100
      Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-04 00:10 +0100
        Re: [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila <octavian.purdila@intel.com> - 2015-11-09 16:20 +0100
    Re: [RFC PATCH 00/28] Linux Kernel Library Hajime Tazaki <thehajime@gmail.com> - 2015-11-08 14:50 +0100

Page 1 of 3  [1] 2 3  Next page →


#1261858 — [RFC PATCH 00/28] Linux Kernel Library

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 00/28] Linux Kernel Library
Message-ID<qqQnn-7AN-3@gated-at.bofh.it>
LKL (Linux Kernel Library) is aiming to allow reusing the Linux kernel code
as extensively as possible with minimal effort and reduced maintenance
overhead.

Examples of how LKL can be used are: creating userspace applications
(running on Linux and other operating systems) that can read or write Linux
filesystems or can use the Linux networking stack, creating kernel drivers
for other operating systems that can read Linux filesystems, bootloaders
support for reading/writing Linux filesystems, etc.

With LKL, the kernel code is compiled into an object file that can be
directly linked by applications. The API offered by LKL is based on the
Linux system call interface.

LKL is implemented as an architecture port in arch/lkl. It relies on host
operations defined by the application or a host library (tools/lkl/lib).

The latest LKL version can be found at git@github.com:lkl/linux.git

FAQ
===

Q: How is LKL different from UML?
A: UML provides a full OS environment (e.g. user/kernel separation, user
processes) and also has requirements (a filesystem, processes, etc.) that
makes it hard to use it for standalone applications. UML also relies
heavily on Linux hosts. On the other hand LKL is designed to be linked
directly with the application and hence does not have user/kernel
separation which makes it easier to use it in standalone applications.

Q: How is LKL different from LibOS?
A: LibOS re-implements high-level kernel APIs for timers, softirqs,
scheduling, sysctl, SLAB/SLUB, etc. LKL behaves like any arch port,
implementing the arch level operations requested by the Linux kernel. LKL
also offers a host interface so that support for multiple hosts can be
easily implemented.


Building LKL the host library and LKL applications
==================================================

% cd tools/lkl
% make

will build LKL as a object file, it will install it in tools/lkl/lib together
with the headers files in tools/lkl/include then will build the host library,
tests and a few of application examples:

* tests/boot - a simple applications that uses LKL and exercises the basic
LKL APIs

* fs2tar - a tool that converts a filesystem image to a tar archive

* cptofs/cpfromfs - a tool that copies files to/from a filesystem image


Supported hosts
===============

Currently LKL supports POSIX and Windows userspace applications. New hosts
can be added relatively easy if the host supports gcc and GNU ld. Previous
versions of LKL supported Windows kernel and Haiku kernel hosts.


Octavian Purdila (28):
  asm-generic: atomic64: allow using generic atomic64 on 64bit platforms
  kbuild: allow architectures to automatically define kconfig symbols
  lkl: architecture skeleton for Linux kernel library
  lkl: host interface
  lkl: memory handling
  lkl: kernel threads support
  lkl: interrupt support
  lkl: system call interface and application API
  lkl: timers, time and delay support
  lkl: memory mapped I/O support
  lkl: basic kernel console support
  init: allow architecture code to overide run_init_process
  lkl: initialization and cleanup
  lkl: plug in the build system
  lkl tools: skeleton for host side library, tests and tools
  lkl tools: host lib: add lkl_strerror and lkl_printf
  lkl tools: host lib: memory mapped I/O helpers
  lkl tools: host lib: virtio devices
  lkl tools: host lib: virtio block device
  lkl tools: host lib: filesystem helpers
  lkl tools: host lib: posix host operations
  lkl tools: "boot" test
  lkl tools: tool that converts a filesystem image to tar
  lkl tools: tool that reads/writes to/from a filesystem image
  signal: use CONFIG_X86_32 instead of __i386__
  asm-generic: vmlinux.lds.h: allow customized rodata section name
  lkl: add support for Windows hosts
  lkl tools: add support for Windows host

 MAINTAINERS                             |   6 +
 Makefile                                |   1 +
 arch/lkl/.gitignore                     |   1 +
 arch/lkl/Kconfig                        |  83 ++++++
 arch/lkl/Makefile                       |  39 +++
 arch/lkl/auto.conf                      |   1 +
 arch/lkl/defconfig                      |  35 +++
 arch/lkl/include/asm/Kbuild             |  77 +++++
 arch/lkl/include/asm/bitsperlong.h      |  11 +
 arch/lkl/include/asm/byteorder.h        |  10 +
 arch/lkl/include/asm/dma-mapping.h      |   6 +
 arch/lkl/include/asm/elf.h              |  13 +
 arch/lkl/include/asm/host_ops.h         |   9 +
 arch/lkl/include/asm/io.h               | 104 +++++++
 arch/lkl/include/asm/irq.h              |  10 +
 arch/lkl/include/asm/mutex.h            |   7 +
 arch/lkl/include/asm/page.h             |  13 +
 arch/lkl/include/asm/pgtable.h          |  60 ++++
 arch/lkl/include/asm/processor.h        |  53 ++++
 arch/lkl/include/asm/ptrace.h           |  23 ++
 arch/lkl/include/asm/setup.h            |  12 +
 arch/lkl/include/asm/thread_info.h      |  82 +++++
 arch/lkl/include/asm/unistd.h           |  93 ++++++
 arch/lkl/include/asm/vmlinux.lds.h      |  10 +
 arch/lkl/include/system/stdarg.h        |   1 +
 arch/lkl/include/uapi/asm/Kbuild        |  38 +++
 arch/lkl/include/uapi/asm/bitsperlong.h |  12 +
 arch/lkl/include/uapi/asm/host_ops.h    |  81 +++++
 arch/lkl/include/uapi/asm/irq.h         |  37 +++
 arch/lkl/include/uapi/asm/sigcontext.h  |  15 +
 arch/lkl/include/uapi/asm/unistd.h      | 256 ++++++++++++++++
 arch/lkl/kernel/Makefile                |   3 +
 arch/lkl/kernel/asm-offsets.c           |   1 +
 arch/lkl/kernel/console.c               |  41 +++
 arch/lkl/kernel/irq.c                   | 131 ++++++++
 arch/lkl/kernel/mem.c                   |  67 +++++
 arch/lkl/kernel/misc.c                  |  57 ++++
 arch/lkl/kernel/setup.c                 | 176 +++++++++++
 arch/lkl/kernel/syscalls.c              | 213 +++++++++++++
 arch/lkl/kernel/threads.c               | 235 +++++++++++++++
 arch/lkl/kernel/time.c                  | 125 ++++++++
 arch/lkl/kernel/vmlinux.lds.S           |  45 +++
 arch/lkl/scripts/headers_install.py     | 117 ++++++++
 include/asm-generic/atomic64.h          |   2 +
 include/asm-generic/vmlinux.lds.h       |   9 +-
 include/linux/atomic.h                  |   2 +-
 include/linux/compiler-gcc.h            |   4 +
 init/main.c                             |   4 +-
 kernel/signal.c                         |   2 +-
 scripts/Makefile                        |   2 +
 scripts/link-vmlinux.sh                 |  12 +-
 tools/lkl/.gitignore                    |   4 +
 tools/lkl/Makefile                      |  47 +++
 tools/lkl/cptofs.c                      | 467 +++++++++++++++++++++++++++++
 tools/lkl/fs2tar.c                      | 397 ++++++++++++++++++++++++
 tools/lkl/include/.gitignore            |   1 +
 tools/lkl/include/lkl.h                 | 110 +++++++
 tools/lkl/include/lkl_host.h            |  44 +++
 tools/lkl/lib/.gitignore                |   3 +
 tools/lkl/lib/fs.c                      | 218 ++++++++++++++
 tools/lkl/lib/iomem.c                   | 119 ++++++++
 tools/lkl/lib/iomem.h                   |  14 +
 tools/lkl/lib/nt-host.c                 | 227 ++++++++++++++
 tools/lkl/lib/posix-host.c              | 206 +++++++++++++
 tools/lkl/lib/utils.c                   | 177 +++++++++++
 tools/lkl/lib/virtio.c                  | 365 +++++++++++++++++++++++
 tools/lkl/lib/virtio.h                  |  94 ++++++
 tools/lkl/lib/virtio_blk.c              | 116 +++++++
 tools/lkl/tests/boot.c                  | 514 ++++++++++++++++++++++++++++++++
 tools/lkl/tests/boot.sh                 |  10 +
 70 files changed, 5570 insertions(+), 10 deletions(-)
 create mode 100644 arch/lkl/.gitignore
 create mode 100644 arch/lkl/Kconfig
 create mode 100644 arch/lkl/Makefile
 create mode 100644 arch/lkl/auto.conf
 create mode 100644 arch/lkl/defconfig
 create mode 100644 arch/lkl/include/asm/Kbuild
 create mode 100644 arch/lkl/include/asm/bitsperlong.h
 create mode 100644 arch/lkl/include/asm/byteorder.h
 create mode 100644 arch/lkl/include/asm/dma-mapping.h
 create mode 100644 arch/lkl/include/asm/elf.h
 create mode 100644 arch/lkl/include/asm/host_ops.h
 create mode 100644 arch/lkl/include/asm/io.h
 create mode 100644 arch/lkl/include/asm/irq.h
 create mode 100644 arch/lkl/include/asm/mutex.h
 create mode 100644 arch/lkl/include/asm/page.h
 create mode 100644 arch/lkl/include/asm/pgtable.h
 create mode 100644 arch/lkl/include/asm/processor.h
 create mode 100644 arch/lkl/include/asm/ptrace.h
 create mode 100644 arch/lkl/include/asm/setup.h
 create mode 100644 arch/lkl/include/asm/thread_info.h
 create mode 100644 arch/lkl/include/asm/unistd.h
 create mode 100644 arch/lkl/include/asm/vmlinux.lds.h
 create mode 100644 arch/lkl/include/system/stdarg.h
 create mode 100644 arch/lkl/include/uapi/asm/Kbuild
 create mode 100644 arch/lkl/include/uapi/asm/bitsperlong.h
 create mode 100644 arch/lkl/include/uapi/asm/host_ops.h
 create mode 100644 arch/lkl/include/uapi/asm/irq.h
 create mode 100644 arch/lkl/include/uapi/asm/sigcontext.h
 create mode 100644 arch/lkl/include/uapi/asm/unistd.h
 create mode 100644 arch/lkl/kernel/Makefile
 create mode 100644 arch/lkl/kernel/asm-offsets.c
 create mode 100644 arch/lkl/kernel/console.c
 create mode 100644 arch/lkl/kernel/irq.c
 create mode 100644 arch/lkl/kernel/mem.c
 create mode 100644 arch/lkl/kernel/misc.c
 create mode 100644 arch/lkl/kernel/setup.c
 create mode 100644 arch/lkl/kernel/syscalls.c
 create mode 100644 arch/lkl/kernel/threads.c
 create mode 100644 arch/lkl/kernel/time.c
 create mode 100644 arch/lkl/kernel/vmlinux.lds.S
 create mode 100755 arch/lkl/scripts/headers_install.py
 create mode 100644 tools/lkl/.gitignore
 create mode 100644 tools/lkl/Makefile
 create mode 100644 tools/lkl/cptofs.c
 create mode 100644 tools/lkl/fs2tar.c
 create mode 100644 tools/lkl/include/.gitignore
 create mode 100644 tools/lkl/include/lkl.h
 create mode 100644 tools/lkl/include/lkl_host.h
 create mode 100644 tools/lkl/lib/.gitignore
 create mode 100644 tools/lkl/lib/fs.c
 create mode 100644 tools/lkl/lib/iomem.c
 create mode 100644 tools/lkl/lib/iomem.h
 create mode 100644 tools/lkl/lib/nt-host.c
 create mode 100644 tools/lkl/lib/posix-host.c
 create mode 100644 tools/lkl/lib/utils.c
 create mode 100644 tools/lkl/lib/virtio.c
 create mode 100644 tools/lkl/lib/virtio.h
 create mode 100644 tools/lkl/lib/virtio_blk.c
 create mode 100644 tools/lkl/tests/boot.c
 create mode 100755 tools/lkl/tests/boot.sh

-- 
2.1.0

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

[toc] | [next] | [standalone]


#1261859 — [RFC PATCH 21/28] lkl tools: host lib: posix host operations

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 21/28] lkl tools: host lib: posix host operations
Message-ID<qqQnp-7AN-29@gated-at.bofh.it>
In reply to#1261858
Implement LKL host operations for POSIX hosts.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/Makefile         |   6 ++
 tools/lkl/lib/posix-host.c | 206 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 212 insertions(+)
 create mode 100644 tools/lkl/lib/posix-host.c

diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index b13472b..cf97d27 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -3,9 +3,15 @@ CFLAGS := -Iinclude -Wall -g
 ifdef CROSS_COMPILE
 CC=$(CROSS_COMPILE)gcc
 AR=$(CROSS_COMPILE)ar
+LD=$(CROSS_COMPILE)ld
 endif
 
 lib_source = $(filter-out %-host.c,$(wildcard lib/*.c))
+ifneq (,$(filter $(shell $(LD) -r -print-output-format),elf64-x86-64 elf32-i386))
+lib_source += lib/posix-host.c
+LDFLAGS += -lpthread -lrt
+endif
+
 lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o
 
 all: lib/liblkl.a
diff --git a/tools/lkl/lib/posix-host.c b/tools/lkl/lib/posix-host.c
new file mode 100644
index 0000000..4bc1de7
--- /dev/null
+++ b/tools/lkl/lib/posix-host.c
@@ -0,0 +1,206 @@
+#include <pthread.h>
+#include <malloc.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <execinfo.h>
+#include <stdint.h>
+#include <sys/uio.h>
+#include <lkl_host.h>
+#include "iomem.h"
+
+static void print(const char *str, int len)
+{
+	write(STDOUT_FILENO, str, len);
+}
+
+struct pthread_sem {
+	pthread_mutex_t lock;
+	int count;
+	pthread_cond_t cond;
+};
+
+static void *sem_alloc(int count)
+{
+	struct pthread_sem *sem;
+
+	sem = malloc(sizeof(*sem));
+	if (!sem)
+		return NULL;
+
+	pthread_mutex_init(&sem->lock, NULL);
+	sem->count = count;
+	pthread_cond_init(&sem->cond, NULL);
+
+	return sem;
+}
+
+static void sem_free(void *sem)
+{
+	free(sem);
+}
+
+static void sem_up(void *_sem)
+{
+	struct pthread_sem *sem = (struct pthread_sem *)_sem;
+
+	pthread_mutex_lock(&sem->lock);
+	sem->count++;
+	if (sem->count > 0)
+		pthread_cond_signal(&sem->cond);
+	pthread_mutex_unlock(&sem->lock);
+}
+
+static void sem_down(void *_sem)
+{
+	struct pthread_sem *sem = (struct pthread_sem *)_sem;
+
+	pthread_mutex_lock(&sem->lock);
+	while (sem->count <= 0)
+		pthread_cond_wait(&sem->cond, &sem->lock);
+	sem->count--;
+	pthread_mutex_unlock(&sem->lock);
+}
+
+static int thread_create(void (*fn)(void *), void *arg)
+{
+	pthread_t thread;
+
+	return pthread_create(&thread, NULL, (void* (*)(void *))fn, arg);
+}
+
+static void thread_exit(void)
+{
+	pthread_exit(NULL);
+}
+
+static unsigned long long time_ns(void)
+{
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+
+	return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;
+}
+
+static void *timer_alloc(void (*fn)(void *), void *arg)
+{
+	int err;
+	timer_t timer;
+	struct sigevent se =  {
+		.sigev_notify = SIGEV_THREAD,
+		.sigev_value = {
+			.sival_ptr = arg,
+		},
+		.sigev_notify_function = (void (*)(union sigval))fn,
+	};
+
+	err = timer_create(CLOCK_REALTIME, &se, &timer);
+	if (err)
+		return NULL;
+
+	return (void *)(long)timer;
+}
+
+static int timer_set_oneshot(void *_timer, unsigned long ns)
+{
+	timer_t timer = (timer_t)(long)_timer;
+	struct itimerspec ts = {
+		.it_value = {
+			.tv_sec = ns / 1000000000,
+			.tv_nsec = ns % 1000000000,
+		},
+	};
+
+	if (!ts.it_value.tv_nsec)
+		ts.it_value.tv_nsec++;
+
+	return timer_settime(timer, 0, &ts, NULL);
+}
+
+static void timer_free(void *_timer)
+{
+	timer_t timer = (timer_t)(long)_timer;
+
+	timer_delete(timer);
+}
+
+static void panic(void)
+{
+	assert(0);
+}
+
+struct lkl_host_operations lkl_host_ops = {
+	.panic = panic,
+	.thread_create = thread_create,
+	.thread_exit = thread_exit,
+	.sem_alloc = sem_alloc,
+	.sem_free = sem_free,
+	.sem_up = sem_up,
+	.sem_down = sem_down,
+	.time = time_ns,
+	.timer_alloc = timer_alloc,
+	.timer_set_oneshot = timer_set_oneshot,
+	.timer_free = timer_free,
+	.print = print,
+	.mem_alloc = malloc,
+	.mem_free = free,
+	.ioremap = lkl_ioremap,
+	.iomem_access = lkl_iomem_access,
+	.virtio_devices = lkl_virtio_devs,
+};
+
+int fd_get_capacity(union lkl_disk_backstore bs, unsigned long long *res)
+{
+	off_t off;
+
+	off = lseek(bs.fd, 0, SEEK_END);
+	if (off < 0)
+		return -1;
+
+	*res = off;
+	return 0;
+}
+
+void fd_do_rw(union lkl_disk_backstore bs, unsigned int type, unsigned int prio,
+	      unsigned long long sector, struct lkl_dev_buf *bufs, int count)
+{
+	int err = 0;
+	struct iovec *iovec = (struct iovec *)bufs;
+
+	if (count > 1)
+		lkl_printf("%s: %d\n", __func__, count);
+
+	/* TODO: handle short reads/writes */
+	switch (type) {
+	case LKL_DEV_BLK_TYPE_READ:
+		err = preadv(bs.fd, iovec, count, sector * 512);
+		break;
+	case LKL_DEV_BLK_TYPE_WRITE:
+		err = pwritev(bs.fd, iovec, count, sector * 512);
+		break;
+	case LKL_DEV_BLK_TYPE_FLUSH:
+	case LKL_DEV_BLK_TYPE_FLUSH_OUT:
+		err = fdatasync(bs.fd);
+		break;
+	default:
+		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_UNSUP, 0);
+		return;
+	}
+
+	if (err < 0)
+		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_IOERR, 0);
+	else
+		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_OK, err);
+}
+
+struct lkl_dev_blk_ops lkl_dev_blk_ops = {
+	.get_capacity = fd_get_capacity,
+	.request = fd_do_rw,
+};
-- 
2.1.0

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

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


#1264944 — Re: [RFC PATCH 21/28] lkl tools: host lib: posix host operations

FromArnd Bergmann <arnd@arndb.de>
Date2015-11-08 00:20 +0100
SubjectRe: [RFC PATCH 21/28] lkl tools: host lib: posix host operations
Message-ID<qskW6-lV-11@gated-at.bofh.it>
In reply to#1261859
On Tuesday 03 November 2015 22:20:52 Octavian Purdila wrote:
> +struct pthread_sem {
> +	pthread_mutex_t lock;
> +	int count;
> +	pthread_cond_t cond;
> +};
> +
> +static void *sem_alloc(int count)
> +{
> +	struct pthread_sem *sem;
> +
> +	sem = malloc(sizeof(*sem));
> +	if (!sem)
> +		return NULL;
> +
> +	pthread_mutex_init(&sem->lock, NULL);
> +	sem->count = count;
> +	pthread_cond_init(&sem->cond, NULL);
> +
> +	return sem;
> +}

What is the reason to have generalized semaphores in the
host API rather than a simple mutex?

> +static unsigned long long time_ns(void)
> +{
> +	struct timeval tv;
> +
> +	gettimeofday(&tv, NULL);
> +
> +	return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;
> +}

clock_gettime() has been around since POSIX.1-2001 and provides the
nanosecond resolution you use in the interface.

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

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


#1264963 — Re: [RFC PATCH 21/28] lkl tools: host lib: posix host operations

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-08 05:10 +0100
SubjectRe: [RFC PATCH 21/28] lkl tools: host lib: posix host operations
Message-ID<qspsK-3jW-5@gated-at.bofh.it>
In reply to#1264944
On Sun, Nov 8, 2015 at 1:16 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 03 November 2015 22:20:52 Octavian Purdila wrote:
>> +struct pthread_sem {
>> +     pthread_mutex_t lock;
>> +     int count;
>> +     pthread_cond_t cond;
>> +};
>> +
>> +static void *sem_alloc(int count)
>> +{
>> +     struct pthread_sem *sem;
>> +
>> +     sem = malloc(sizeof(*sem));
>> +     if (!sem)
>> +             return NULL;
>> +
>> +     pthread_mutex_init(&sem->lock, NULL);
>> +     sem->count = count;
>> +     pthread_cond_init(&sem->cond, NULL);
>> +
>> +     return sem;
>> +}
>
> What is the reason to have generalized semaphores in the
> host API rather than a simple mutex?
>

Currently waking up from idle after an IRQ event requires a semaphore.
I'll see if we can use a simple mutex for this.

>> +static unsigned long long time_ns(void)
>> +{
>> +     struct timeval tv;
>> +
>> +     gettimeofday(&tv, NULL);
>> +
>> +     return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;
>> +}
>
> clock_gettime() has been around since POSIX.1-2001 and provides the
> nanosecond resolution you use in the interface.
>

Good point, I will change it to clock_gettime.

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

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


#1265069 — Re: [RFC PATCH 21/28] lkl tools: host lib: posix host operations

FromArnd Bergmann <arnd@arndb.de>
Date2015-11-08 11:40 +0100
SubjectRe: [RFC PATCH 21/28] lkl tools: host lib: posix host operations
Message-ID<qsvy9-7nD-11@gated-at.bofh.it>
In reply to#1264963
On Sunday 08 November 2015 06:01:08 Octavian Purdila wrote:
> >> +static void *sem_alloc(int count)
> >> +{
> >> +     struct pthread_sem *sem;
> >> +
> >> +     sem = malloc(sizeof(*sem));
> >> +     if (!sem)
> >> +             return NULL;
> >> +
> >> +     pthread_mutex_init(&sem->lock, NULL);
> >> +     sem->count = count;
> >> +     pthread_cond_init(&sem->cond, NULL);
> >> +
> >> +     return sem;
> >> +}
> >
> > What is the reason to have generalized semaphores in the
> > host API rather than a simple mutex?
> >
> 
> Currently waking up from idle after an IRQ event requires a semaphore.
> I'll see if we can use a simple mutex for this.

According to the pthread_mutex_unlock() man page, you are not allowed
to unlock a mutex from any thread other than the one that owns the
mutex through pthread_mutex_lock(), so if the IRQ event is sent to
another thread, that would not be safe even if it happens to work
on linux+glibc.

Another option would be to use futexes as the basic primitive, which
might make the implementation for Linux hosts a bit more efficient,
but complicates the implementation for hosts that do not implement
those.

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

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


#1261860 — [RFC PATCH 18/28] lkl tools: host lib: virtio devices

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 18/28] lkl tools: host lib: virtio devices
Message-ID<qqQnp-7AN-31@gated-at.bofh.it>
In reply to#1261858
Add helpers for implementing host virtio devices. It uses the memory
mapped I/O helpers to interact with the Linux MMIO virtio transport
driver and offers support to setup and add a new virtio device,
dispatch requests from the incoming queues as well as support for
completing requests.

All added virtio devices are stored in lkl_virtio_devs as strings, per
the Linux MMIO virtio transport driver command line specification.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/include/lkl_host.h |   7 +
 tools/lkl/lib/virtio.c       | 365 +++++++++++++++++++++++++++++++++++++++++++
 tools/lkl/lib/virtio.h       |  86 ++++++++++
 3 files changed, 458 insertions(+)
 create mode 100644 tools/lkl/lib/virtio.c
 create mode 100644 tools/lkl/lib/virtio.h

diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h
index 9f1c270..26d3e43 100644
--- a/tools/lkl/include/lkl_host.h
+++ b/tools/lkl/include/lkl_host.h
@@ -13,4 +13,11 @@ extern struct lkl_host_operations lkl_host_ops;
  */
 int lkl_printf(const char *fmt, ...);
 
+char lkl_virtio_devs[256];
+
+struct lkl_dev_buf {
+	void *addr;
+	unsigned int len;
+};
+
 #endif
diff --git a/tools/lkl/lib/virtio.c b/tools/lkl/lib/virtio.c
new file mode 100644
index 0000000..034152e
--- /dev/null
+++ b/tools/lkl/lib/virtio.c
@@ -0,0 +1,365 @@
+#include <string.h>
+#include <stdio.h>
+#include <lkl_host.h>
+#include "iomem.h"
+#include "virtio.h"
+
+#define VIRTIO_DEV_MAGIC		0x74726976
+#define VIRTIO_DEV_VERSION		2
+
+#define VIRTIO_MMIO_MAGIC_VALUE		0x000
+#define VIRTIO_MMIO_VERSION		0x004
+#define VIRTIO_MMIO_DEVICE_ID		0x008
+#define VIRTIO_MMIO_VENDOR_ID		0x00c
+#define VIRTIO_MMIO_DEVICE_FEATURES	0x010
+#define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014
+#define VIRTIO_MMIO_DRIVER_FEATURES	0x020
+#define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024
+#define VIRTIO_MMIO_QUEUE_SEL		0x030
+#define VIRTIO_MMIO_QUEUE_NUM_MAX	0x034
+#define VIRTIO_MMIO_QUEUE_NUM		0x038
+#define VIRTIO_MMIO_QUEUE_READY		0x044
+#define VIRTIO_MMIO_QUEUE_NOTIFY	0x050
+#define VIRTIO_MMIO_INTERRUPT_STATUS	0x060
+#define VIRTIO_MMIO_INTERRUPT_ACK	0x064
+#define VIRTIO_MMIO_STATUS		0x070
+#define VIRTIO_MMIO_QUEUE_DESC_LOW	0x080
+#define VIRTIO_MMIO_QUEUE_DESC_HIGH	0x084
+#define VIRTIO_MMIO_QUEUE_AVAIL_LOW	0x090
+#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH	0x094
+#define VIRTIO_MMIO_QUEUE_USED_LOW	0x0a0
+#define VIRTIO_MMIO_QUEUE_USED_HIGH	0x0a4
+#define VIRTIO_MMIO_CONFIG_GENERATION	0x0fc
+#define VIRTIO_MMIO_CONFIG		0x100
+#define VIRTIO_MMIO_INT_VRING		0x01
+#define VIRTIO_MMIO_INT_CONFIG		0x02
+
+#define VIRTIO_DEV_STATUS_ACK		0x01
+#define VIRTIO_DEV_STATUS_DRV		0x02
+#define VIRTIO_DEV_STATUS_FEATURES_OK	0x08
+#define VIRTIO_DEV_STATUS_DRV_OK	0x04
+#define VIRTIO_DEV_STATUS_FAILED	0x80
+
+#define VIRTIO_F_VERSION_1		(1ULL << 32)
+#define VIRTIO_RING_F_EVENT_IDX		(1ULL << 29)
+#define VIRTIO_DESC_F_NEXT		1
+
+static inline uint16_t virtio_get_used_event(struct virtio_queue *q)
+{
+	return q->avail->ring[q->num];
+}
+
+static inline void virtio_set_avail_event(struct virtio_queue *q, uint16_t val)
+{
+	*((uint16_t *)&q->used->ring[q->num]) = val;
+}
+
+#define ring_entry(q, r, idx) \
+	q->r->ring[idx & (q->num - 1)]
+
+static inline void virtio_deliver_irq(struct virtio_dev *dev)
+{
+	dev->int_status |= VIRTIO_MMIO_INT_VRING;
+	lkl_trigger_irq(dev->irq, NULL);
+}
+
+void virtio_dev_complete(struct virtio_dev_req *req, uint32_t len)
+{
+	struct virtio_queue *q = req->q;
+	struct virtio_dev *dev = req->dev;
+	uint16_t idx = le16toh(q->used->idx) & (q->num - 1);
+	int send_irq = 0;
+
+	q->used->ring[idx].id = htole16(req->desc_idx);
+	q->used->ring[idx].len = htole16(len);
+	if (virtio_get_used_event(q) == q->used->idx)
+		send_irq = 1;
+	q->used->idx = htole16(le16toh(q->used->idx) + 1);
+
+	if (send_irq)
+		virtio_deliver_irq(dev);
+
+	lkl_host_ops.mem_free(req);
+}
+
+static void virtio_process_avail_one(struct virtio_dev *dev,
+				     struct virtio_queue *q,
+				     int avail_idx)
+{
+	int j;
+	uint16_t desc_idx;
+	struct virtio_desc *i;
+	struct virtio_dev_req *req = NULL;
+
+	avail_idx = avail_idx & (q->num - 1);
+	desc_idx = le16toh(q->avail->ring[avail_idx]) & (q->num - 1);
+
+	i = &q->desc[desc_idx];
+	j = 1;
+	while (le16toh(i->flags) & VIRTIO_DESC_F_NEXT) {
+		desc_idx = le16toh(i->next) & (q->num - 1);
+		i = &q->desc[desc_idx];
+		j++;
+	}
+
+	req = lkl_host_ops.mem_alloc((uintptr_t)&req->buf[j]);
+	if (!req)
+		return;
+
+	req->dev = dev;
+	req->q = q;
+	req->desc_idx = q->avail->ring[avail_idx];
+	req->buf_count = j;
+
+	desc_idx = le16toh(q->avail->ring[avail_idx]) & (q->num - 1);
+	i = &q->desc[desc_idx];
+	j = 0;
+	req->buf[j].addr = (void *)(uintptr_t)le64toh(i->addr);
+	req->buf[j].len = le32toh(i->len);
+	while (le16toh(i->flags) & VIRTIO_DESC_F_NEXT) {
+		desc_idx = le16toh(i->next) & (q->num - 1);
+		i = &q->desc[desc_idx];
+		j++;
+		req->buf[j].addr = (void *)(uintptr_t)le64toh(i->addr);
+		req->buf[j].len = le32toh(i->len);
+	}
+
+	dev->ops->queue(dev, req);
+}
+
+static void virtio_process_avail(struct virtio_dev *dev, uint32_t qidx)
+{
+	struct virtio_queue *q = &dev->queue[qidx];
+
+	virtio_set_avail_event(q, q->avail->idx);
+
+	while (q->last_avail_idx != le16toh(q->avail->idx)) {
+		virtio_process_avail_one(dev, q, q->last_avail_idx);
+		q->last_avail_idx++;
+	}
+}
+
+static inline uint32_t virtio_read_device_features(struct virtio_dev *dev)
+{
+	if (dev->device_features_sel)
+		return (uint32_t)(dev->device_features >> 32);
+
+	return (uint32_t)dev->device_features;
+}
+
+static inline void virtio_write_driver_features(struct virtio_dev *dev,
+						uint32_t val)
+{
+	uint64_t tmp;
+
+	if (dev->driver_features_sel) {
+		tmp = dev->driver_features & 0xFFFFFFFF;
+		dev->driver_features = tmp | (uint64_t)val << 32;
+	} else {
+		tmp = dev->driver_features & 0xFFFFFFFF00000000;
+		dev->driver_features = tmp | val;
+	}
+}
+
+static int virtio_read(void *data, int offset, void *res, int size)
+{
+	uint32_t val;
+	struct virtio_dev *dev = (struct virtio_dev *)data;
+	int ret = 0;
+
+	if (offset >= VIRTIO_MMIO_CONFIG) {
+		offset -= VIRTIO_MMIO_CONFIG;
+		if (offset + size > dev->config_len)
+			return -LKL_EINVAL;
+		memcpy(res, dev->config_data + offset, size);
+		return 0;
+	}
+
+	if (size != sizeof(uint32_t))
+		return -LKL_EINVAL;
+
+	switch (offset) {
+	case VIRTIO_MMIO_MAGIC_VALUE:
+		val = VIRTIO_DEV_MAGIC;
+		break;
+	case VIRTIO_MMIO_VERSION:
+		val = VIRTIO_DEV_VERSION;
+		break;
+	case VIRTIO_MMIO_DEVICE_ID:
+		val = dev->device_id;
+		break;
+	case VIRTIO_MMIO_VENDOR_ID:
+		val = dev->vendor_id;
+		break;
+	case VIRTIO_MMIO_DEVICE_FEATURES:
+		val = virtio_read_device_features(dev);
+		break;
+	case VIRTIO_MMIO_QUEUE_NUM_MAX:
+		val = dev->queue[dev->queue_sel].num_max;
+		break;
+	case VIRTIO_MMIO_QUEUE_READY:
+		val = dev->queue[dev->queue_sel].ready;
+		break;
+	case VIRTIO_MMIO_INTERRUPT_STATUS:
+		val = dev->int_status;
+		break;
+	case VIRTIO_MMIO_STATUS:
+		val = dev->status;
+		break;
+	case VIRTIO_MMIO_CONFIG_GENERATION:
+		val = dev->config_gen;
+		break;
+	default:
+		ret = -1;
+	}
+
+	*(uint32_t *)res = htole32(val);
+
+	return ret;
+}
+
+static inline void set_ptr_low(void **ptr, uint32_t val)
+{
+	uint64_t tmp = (uintptr_t)*ptr;
+
+	tmp = (tmp & 0xFFFFFFFF00000000) | val;
+	*ptr = (void *)(long)tmp;
+}
+
+static inline void set_ptr_high(void **ptr, uint32_t val)
+{
+	uint64_t tmp = (uintptr_t)*ptr;
+
+	tmp = (tmp & 0x00000000FFFFFFFF) | ((uint64_t)val << 32);
+	*ptr = (void *)(long)tmp;
+}
+
+static int virtio_write(void *data, int offset, void *res, int size)
+{
+	struct virtio_dev *dev = (struct virtio_dev *)data;
+	struct virtio_queue *q = &dev->queue[dev->queue_sel];
+	uint32_t val;
+	int ret = 0;
+
+	if (offset >= VIRTIO_MMIO_CONFIG) {
+		offset -= VIRTIO_MMIO_CONFIG;
+
+		if (offset + size >= dev->config_len)
+			return -LKL_EINVAL;
+		memcpy(dev->config_data + offset, res, size);
+		return 0;
+	}
+
+	if (size != sizeof(uint32_t))
+		return -LKL_EINVAL;
+
+	val = le32toh(*(uint32_t *)res);
+
+	switch (offset) {
+	case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
+		if (val > 1)
+			return -LKL_EINVAL;
+		dev->device_features_sel = val;
+		break;
+	case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
+		if (val > 1)
+			return -LKL_EINVAL;
+		dev->driver_features_sel = val;
+		break;
+	case VIRTIO_MMIO_DRIVER_FEATURES:
+		virtio_write_driver_features(dev, val);
+		break;
+	case VIRTIO_MMIO_QUEUE_SEL:
+		dev->queue_sel = val;
+		break;
+	case VIRTIO_MMIO_QUEUE_NUM:
+		dev->queue[dev->queue_sel].num = val;
+		break;
+	case VIRTIO_MMIO_QUEUE_READY:
+		dev->queue[dev->queue_sel].ready = val;
+		break;
+	case VIRTIO_MMIO_QUEUE_NOTIFY:
+		virtio_process_avail(dev, val);
+		break;
+	case VIRTIO_MMIO_INTERRUPT_ACK:
+		dev->int_status = 0;
+		break;
+	case VIRTIO_MMIO_STATUS:
+		if (val & VIRTIO_DEV_STATUS_FEATURES_OK &&
+		    (!(dev->driver_features & VIRTIO_F_VERSION_1) ||
+		     !(dev->driver_features & VIRTIO_RING_F_EVENT_IDX) ||
+		     dev->ops->check_features(dev->driver_features & 0xFFFFFF)))
+			val &= ~VIRTIO_DEV_STATUS_FEATURES_OK;
+		dev->status = val;
+		break;
+	case VIRTIO_MMIO_QUEUE_DESC_LOW:
+		set_ptr_low((void **)&q->desc, val);
+		break;
+	case VIRTIO_MMIO_QUEUE_DESC_HIGH:
+		set_ptr_high((void **)&q->desc, val);
+		break;
+	case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
+		set_ptr_low((void **)&q->avail, val);
+		break;
+	case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
+		set_ptr_high((void **)&q->avail, val);
+		break;
+	case VIRTIO_MMIO_QUEUE_USED_LOW:
+		set_ptr_low((void **)&q->used, val);
+		break;
+	case VIRTIO_MMIO_QUEUE_USED_HIGH:
+		set_ptr_high((void **)&q->used, val);
+		break;
+	default:
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static const struct lkl_iomem_ops virtio_ops = {
+	.read = virtio_read,
+	.write = virtio_write,
+};
+
+char lkl_virtio_devs[256];
+static char *devs = lkl_virtio_devs;
+
+int virtio_dev_setup(struct virtio_dev *dev, int queues, int num_max)
+{
+	int qsize = queues * sizeof(*dev->queue);
+	int ret, avail, mmio_size;
+	int i;
+
+	dev->irq = lkl_get_free_irq("virtio");
+	if (dev->irq < 0)
+		return dev->irq;
+
+	dev->device_features |= VIRTIO_F_VERSION_1 | VIRTIO_RING_F_EVENT_IDX;
+	dev->queue = lkl_host_ops.mem_alloc(qsize);
+	if (!dev->queue)
+		return -LKL_ENOMEM;
+
+	memset(dev->queue, 0, qsize);
+	for (i = 0; i < queues; i++)
+		dev->queue[i].num_max = num_max;
+
+	mmio_size = VIRTIO_MMIO_CONFIG + dev->config_len;
+	ret = register_iomem(dev, mmio_size, &virtio_ops);
+	if (ret)
+		lkl_host_ops.mem_free(dev->queue);
+
+	avail = sizeof(lkl_virtio_devs) - (devs - lkl_virtio_devs);
+	devs += snprintf(devs, avail, " virtio_mmio.device=%d@%p:%d",
+			 mmio_size, dev, dev->irq);
+
+	return ret;
+}
+
+void virtio_dev_cleanup(struct virtio_dev *dev)
+{
+	lkl_put_irq(dev->irq, "virtio");
+	unregister_iomem(dev);
+	lkl_host_ops.mem_free(dev->queue);
+}
+
diff --git a/tools/lkl/lib/virtio.h b/tools/lkl/lib/virtio.h
new file mode 100644
index 0000000..1bacbe6
--- /dev/null
+++ b/tools/lkl/lib/virtio.h
@@ -0,0 +1,86 @@
+#ifndef _LKL_LIB_VIRTIO_H
+#define _LKL_LIB_VIRTIO_H
+
+#include <stdint.h>
+#include <lkl_host.h>
+
+struct virtio_desc {
+	uint64_t addr;
+	uint32_t len;
+	uint16_t flags;
+	uint16_t next;
+};
+
+struct virtio_avail {
+	uint16_t flags;
+	uint16_t idx;
+	uint16_t ring[];
+};
+
+struct virtio_used_elem {
+	uint32_t id;
+	uint32_t len;
+};
+
+struct virtio_used {
+	uint16_t flags;
+	uint16_t idx;
+	struct virtio_used_elem ring[];
+};
+
+struct virtio_queue {
+	uint32_t num_max;
+	uint32_t num;
+	uint32_t ready;
+
+	struct virtio_desc *desc;
+	struct virtio_avail *avail;
+	struct virtio_used *used;
+	uint16_t last_avail_idx;
+	void *config_data;
+	int config_len;
+};
+
+struct virtio_dev_req {
+	struct virtio_dev *dev;
+	struct virtio_queue *q;
+	uint16_t desc_idx;
+	uint16_t buf_count;
+	struct lkl_dev_buf buf[];
+};
+
+struct virtio_dev_ops {
+	int (*check_features)(uint32_t features);
+	void (*queue)(struct virtio_dev *dev, struct virtio_dev_req *req);
+};
+
+struct virtio_dev {
+	uint32_t device_id;
+	uint32_t vendor_id;
+	uint64_t device_features;
+	uint32_t device_features_sel;
+	uint64_t driver_features;
+	uint32_t driver_features_sel;
+	uint32_t queue_sel;
+	struct virtio_queue *queue;
+	uint32_t queue_notify;
+	uint32_t int_status;
+	uint32_t status;
+	uint32_t config_gen;
+
+	struct virtio_dev_ops *ops;
+	int irq;
+	void *config_data;
+	int config_len;
+};
+
+int virtio_dev_setup(struct virtio_dev *dev, int queues, int num_max);
+void virtio_dev_cleanup(struct virtio_dev *dev);
+void virtio_dev_complete(struct virtio_dev_req *req, uint32_t len);
+
+#define container_of(ptr, type, member) \
+	(type *)((char *)(ptr) - __builtin_offsetof(type, member))
+
+#include <endian.h>
+
+#endif /* _LKL_LIB_VIRTIO_H */
-- 
2.1.0

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

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


#1261861 — [RFC PATCH 19/28] lkl tools: host lib: virtio block device

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 19/28] lkl tools: host lib: virtio block device
Message-ID<qqQnp-7AN-33@gated-at.bofh.it>
In reply to#1261858
Host independent implementation for virtio block devices. The host
dependent part of the host library must provide an implementation for
lkl_dev_block_ops.

Disks can be added to the LKL configuration via lkl_disk_add(), a new
LKL application API.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/include/lkl.h      |  20 ++++++++
 tools/lkl/include/lkl_host.h |  21 ++++++++
 tools/lkl/lib/virtio_blk.c   | 116 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 tools/lkl/lib/virtio_blk.c

diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h
index 958614d..0c30b23 100644
--- a/tools/lkl/include/lkl.h
+++ b/tools/lkl/include/lkl.h
@@ -20,4 +20,24 @@ static inline long lkl_sys_lseek(unsigned int fd, __lkl__kernel_loff_t off,
  */
 const char *lkl_strerror(int err);
 
+/**
+ * lkl_disk_backstore - host dependend disk backstore
+ *
+ * @fd - an open file descriptor that can be used by preadv/pwritev; used by
+ * POSIX hosts
+ */
+union lkl_disk_backstore {
+	int fd;
+};
+
+/**
+ * lkl_disk_add - add a new disk
+ *
+ * Must be called before calling lkl_start_kernel.
+ *
+ * @backstore - the disk backstore
+ * @returns a disk id (0 is valid) or a strictly negative value in case of error
+ */
+int lkl_disk_add(union lkl_disk_backstore backstore);
+
 #endif
diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h
index 26d3e43..2dafaa8 100644
--- a/tools/lkl/include/lkl_host.h
+++ b/tools/lkl/include/lkl_host.h
@@ -20,4 +20,25 @@ struct lkl_dev_buf {
 	unsigned int len;
 };
 
+extern struct lkl_dev_blk_ops lkl_dev_blk_ops;
+
+#define LKL_DEV_BLK_TYPE_READ		0
+#define LKL_DEV_BLK_TYPE_WRITE		1
+#define LKL_DEV_BLK_TYPE_FLUSH		4
+#define LKL_DEV_BLK_TYPE_FLUSH_OUT	5
+
+struct lkl_dev_blk_ops {
+	int (*get_capacity)(union lkl_disk_backstore bs,
+			    unsigned long long *res);
+	void (*request)(union lkl_disk_backstore bs, unsigned int type,
+			unsigned int prio, unsigned long long sector,
+			struct lkl_dev_buf *bufs, int count);
+};
+
+#define LKL_DEV_BLK_STATUS_OK		0
+#define LKL_DEV_BLK_STATUS_IOERR	1
+#define LKL_DEV_BLK_STATUS_UNSUP	2
+
+void lkl_dev_blk_complete(struct lkl_dev_buf *bufs, unsigned char status,
+			  int len);
 #endif
diff --git a/tools/lkl/lib/virtio_blk.c b/tools/lkl/lib/virtio_blk.c
new file mode 100644
index 0000000..3262f42
--- /dev/null
+++ b/tools/lkl/lib/virtio_blk.c
@@ -0,0 +1,116 @@
+#include <lkl_host.h>
+#include "virtio.h"
+
+struct virtio_blk_dev {
+	struct virtio_dev dev;
+	struct {
+		uint64_t capacity;
+	} config;
+	struct lkl_dev_blk_ops *ops;
+	union lkl_disk_backstore backstore;
+};
+
+struct virtio_blk_req_header {
+	uint32_t type;
+	uint32_t prio;
+	uint64_t sector;
+};
+
+struct virtio_blk_req_trailer {
+	uint8_t status;
+};
+
+static int blk_check_features(uint32_t features)
+{
+	if (!features)
+		return 0;
+
+	return -LKL_EINVAL;
+}
+
+void lkl_dev_blk_complete(struct lkl_dev_buf *bufs, unsigned char status,
+			  int len)
+{
+	struct virtio_dev_req *req;
+	struct virtio_blk_req_trailer *f;
+
+	req = container_of(bufs - 1, struct virtio_dev_req, buf);
+
+	if (req->buf_count < 2) {
+		lkl_printf("virtio_blk: no status buf\n");
+		return;
+	}
+
+	if (req->buf[req->buf_count - 1].len != sizeof(*f)) {
+		lkl_printf("virtio_blk: bad status buf\n");
+	} else {
+		f = req->buf[req->buf_count - 1].addr;
+		f->status = status;
+	}
+
+	virtio_dev_complete(req, len);
+}
+
+static void blk_queue(struct virtio_dev *dev, struct virtio_dev_req *req)
+{
+	struct virtio_blk_req_header *h;
+	struct virtio_blk_dev *blk_dev;
+
+	if (req->buf[0].len != sizeof(struct virtio_blk_req_header)) {
+		lkl_printf("virtio_blk: bad header buf\n");
+		lkl_dev_blk_complete(&req->buf[1], LKL_DEV_BLK_STATUS_UNSUP, 0);
+		return;
+	}
+
+	h = req->buf[0].addr;
+	blk_dev = container_of(dev, struct virtio_blk_dev, dev);
+
+	blk_dev->ops->request(blk_dev->backstore, le32toh(h->type),
+			      le32toh(h->prio), le32toh(h->sector),
+			      &req->buf[1], req->buf_count - 2);
+}
+
+static struct virtio_dev_ops blk_ops = {
+	.check_features = blk_check_features,
+	.queue = blk_queue,
+};
+
+int lkl_disk_add(union lkl_disk_backstore backstore)
+{
+	struct virtio_blk_dev *dev;
+	unsigned long long capacity;
+	int ret;
+	static int count;
+
+	dev = lkl_host_ops.mem_alloc(sizeof(*dev));
+	if (!dev)
+		return -LKL_ENOMEM;
+
+	dev->dev.device_id = 2;
+	dev->dev.vendor_id = 0;
+	dev->dev.device_features = 0;
+	dev->dev.config_gen = 0;
+	dev->dev.config_data = &dev->config;
+	dev->dev.config_len = sizeof(dev->config);
+	dev->dev.ops = &blk_ops;
+	dev->ops = &lkl_dev_blk_ops;
+	dev->backstore = backstore;
+
+	ret = dev->ops->get_capacity(backstore, &capacity);
+	if (ret) {
+		ret = -LKL_ENOMEM;
+		goto out_free;
+	}
+	dev->config.capacity = capacity;
+
+	ret = virtio_dev_setup(&dev->dev, 1, 65536);
+	if (ret)
+		goto out_free;
+
+	return count++;
+
+out_free:
+	lkl_host_ops.mem_free(dev);
+
+	return ret;
+}
-- 
2.1.0

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

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


#1264828 — Re: [RFC PATCH 19/28] lkl tools: host lib: virtio block device

FromRichard Weinberger <richard.weinberger@gmail.com>
Date2015-11-07 13:30 +0100
SubjectRe: [RFC PATCH 19/28] lkl tools: host lib: virtio block device
Message-ID<qsaN3-2eE-3@gated-at.bofh.it>
In reply to#1261861
On Tue, Nov 3, 2015 at 9:20 PM, Octavian Purdila
<octavian.purdila@intel.com> wrote:
> Host independent implementation for virtio block devices. The host
> dependent part of the host library must provide an implementation for
> lkl_dev_block_ops.
>
> Disks can be added to the LKL configuration via lkl_disk_add(), a new
> LKL application API.
>
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
> ---
>  tools/lkl/include/lkl.h      |  20 ++++++++
>  tools/lkl/include/lkl_host.h |  21 ++++++++
>  tools/lkl/lib/virtio_blk.c   | 116 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 157 insertions(+)
>  create mode 100644 tools/lkl/lib/virtio_blk.c

Can you please outline what the differences between this driver and
UML's block driver are?

While UML and LKL have different goals they could at least share some drivers.
UML also has networking drivers you could reuse.
Maybe it would make sense to integrate LKL completely into arch/um if
we find a nice way
to combine them.
CONFIG_UML_LIBRARY, hmm?
Would be a nice opportunity to clear away some dung from arch/um and
refactor it. :-)

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

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


#1264964 — Re: [RFC PATCH 19/28] lkl tools: host lib: virtio block device

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-08 05:20 +0100
SubjectRe: [RFC PATCH 19/28] lkl tools: host lib: virtio block device
Message-ID<qspCp-3nA-3@gated-at.bofh.it>
In reply to#1264828
On Sat, Nov 7, 2015 at 2:24 PM, Richard Weinberger
<richard.weinberger@gmail.com> wrote:
> On Tue, Nov 3, 2015 at 9:20 PM, Octavian Purdila
> <octavian.purdila@intel.com> wrote:
>> Host independent implementation for virtio block devices. The host
>> dependent part of the host library must provide an implementation for
>> lkl_dev_block_ops.
>>
>> Disks can be added to the LKL configuration via lkl_disk_add(), a new
>> LKL application API.
>>
>> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
>> ---
>>  tools/lkl/include/lkl.h      |  20 ++++++++
>>  tools/lkl/include/lkl_host.h |  21 ++++++++
>>  tools/lkl/lib/virtio_blk.c   | 116 +++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 157 insertions(+)
>>  create mode 100644 tools/lkl/lib/virtio_blk.c
>

Hi Richard,

> Can you please outline what the differences between this driver and
> UML's block driver are?
>

LKL actually uses the standard virtio block driver, it does not
implement a new (Linux kernel) driver.

This patch is the implementation for the host side device (in virtio's
spec lingo).

Or maybe I misunderstood your question?

> While UML and LKL have different goals they could at least share some drivers.
> UML also has networking drivers you could reuse.
> Maybe it would make sense to integrate LKL completely into arch/um if
> we find a nice way
> to combine them.
> CONFIG_UML_LIBRARY, hmm?
> Would be a nice opportunity to clear away some dung from arch/um and
> refactor it. :-)
>

Yeah, that would be nice :) I think the key part is to define the
right host operations (in LKL terms) that can support UML. I'll have
to spend some time to study UML's internals a bit to see if that would
be doable.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

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


#1265087 — Re: [RFC PATCH 19/28] lkl tools: host lib: virtio block device

FromRichard Weinberger <richard@nod.at>
Date2015-11-08 14:40 +0100
SubjectRe: [RFC PATCH 19/28] lkl tools: host lib: virtio block device
Message-ID<qsyml-Jh-7@gated-at.bofh.it>
In reply to#1264964
Am 08.11.2015 um 05:15 schrieb Octavian Purdila:
> On Sat, Nov 7, 2015 at 2:24 PM, Richard Weinberger
> <richard.weinberger@gmail.com> wrote:
>> On Tue, Nov 3, 2015 at 9:20 PM, Octavian Purdila
>> <octavian.purdila@intel.com> wrote:
>>> Host independent implementation for virtio block devices. The host
>>> dependent part of the host library must provide an implementation for
>>> lkl_dev_block_ops.
>>>
>>> Disks can be added to the LKL configuration via lkl_disk_add(), a new
>>> LKL application API.
>>>
>>> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
>>> ---
>>>  tools/lkl/include/lkl.h      |  20 ++++++++
>>>  tools/lkl/include/lkl_host.h |  21 ++++++++
>>>  tools/lkl/lib/virtio_blk.c   | 116 +++++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 157 insertions(+)
>>>  create mode 100644 tools/lkl/lib/virtio_blk.c
>>
> 
> Hi Richard,
> 
>> Can you please outline what the differences between this driver and
>> UML's block driver are?
>>
> 
> LKL actually uses the standard virtio block driver, it does not
> implement a new (Linux kernel) driver.
> 
> This patch is the implementation for the host side device (in virtio's
> spec lingo).
> 
> Or maybe I misunderstood your question?

I just realized, that virtio does not depend on PCI, I thought you've implemented something
on your own. That said, UML could also use virtio block.

>> While UML and LKL have different goals they could at least share some drivers.
>> UML also has networking drivers you could reuse.
>> Maybe it would make sense to integrate LKL completely into arch/um if
>> we find a nice way
>> to combine them.
>> CONFIG_UML_LIBRARY, hmm?
>> Would be a nice opportunity to clear away some dung from arch/um and
>> refactor it. :-)
>>
> 
> Yeah, that would be nice :) I think the key part is to define the
> right host operations (in LKL terms) that can support UML. I'll have
> to spend some time to study UML's internals a bit to see if that would
> be doable.

arch/um/os-Linux/ is a good place to start. It implements most things on the host side.
Drivers like UML'S block driver always have foo_user.c and foo_kern.c part.

In case of any questions, just ask!

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

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


#1261862 — [RFC PATCH 13/28] lkl: initialization and cleanup

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 13/28] lkl: initialization and cleanup
Message-ID<qqQnp-7AN-37@gated-at.bofh.it>
In reply to#1261858
Add the lkl_start_kernel and lkl_sys_halt APIs that start and
respectively stops the Linux kernel.

lkl_start_kernel creates a separate threads that will run the initial
and idle kernel thread. It waits for the kernel to complete
initialization before returning, to avoid races with system calls
issues by the host application.

During the setup phase, we create "/init" in initial ramfs root
filesystem to avoid mounting the "real" rootfs since ramfs is good
enough for now.

lkl_stop_kernel will shutdown the kernel, terminate all threads and
free all host resources used by the kernel before returning.

This patch also introduces idle CPU handling since it is closely
related to the shutdown process. A host semaphore is used to wait for
new interrupts when the kernel switches the CPU to idle to avoid
wasting host CPU cycles. When the kernel is shutdown we terminate the
idle thread at the first CPU idle event.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 arch/lkl/include/asm/setup.h |  12 +++
 arch/lkl/kernel/setup.c      | 176 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 188 insertions(+)
 create mode 100644 arch/lkl/include/asm/setup.h
 create mode 100644 arch/lkl/kernel/setup.c

diff --git a/arch/lkl/include/asm/setup.h b/arch/lkl/include/asm/setup.h
new file mode 100644
index 0000000..b82cdbf
--- /dev/null
+++ b/arch/lkl/include/asm/setup.h
@@ -0,0 +1,12 @@
+#ifndef _ASM_LKL_SETUP_H
+#define _ASM_LKL_SETUP_H
+
+#define COMMAND_LINE_SIZE 4096
+
+#ifndef __ASSEMBLY__
+#define ARCH_RUN_INIT_PROCESS
+int run_init_process(const char *init_filename);
+void wakeup_cpu(void);
+#endif
+
+#endif
diff --git a/arch/lkl/kernel/setup.c b/arch/lkl/kernel/setup.c
new file mode 100644
index 0000000..aad2ad7
--- /dev/null
+++ b/arch/lkl/kernel/setup.c
@@ -0,0 +1,176 @@
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/start_kernel.h>
+#include <linux/syscalls.h>
+#include <asm/host_ops.h>
+#include <asm/irq.h>
+#include <asm/unistd.h>
+
+struct lkl_host_operations *lkl_ops;
+static char cmd_line[COMMAND_LINE_SIZE];
+static void *idle_sem;
+static void *init_sem;
+static void *halt_sem;
+static bool halt;
+void (*pm_power_off)(void) = NULL;
+static unsigned long mem_size;
+
+long lkl_panic_blink(int state)
+{
+	lkl_ops->panic();
+	return 0;
+}
+
+void __init setup_arch(char **cl)
+{
+	*cl = cmd_line;
+	panic_blink = lkl_panic_blink;
+	bootmem_init(mem_size);
+}
+
+int run_init_process(const char *init_filename)
+{
+	lkl_ops->sem_up(init_sem);
+
+	run_syscalls();
+
+	kernel_halt();
+
+	/* We want to kill init without panic()ing */
+	init_pid_ns.child_reaper = 0;
+	do_exit(0);
+
+	return 0;
+}
+
+static void __init lkl_run_kernel(void *arg)
+{
+	start_kernel();
+}
+
+int __init lkl_start_kernel(struct lkl_host_operations *ops,
+			    unsigned long _mem_size,
+			    const char *fmt, ...)
+{
+	va_list ap;
+	int ret;
+
+	lkl_ops = ops;
+	mem_size = _mem_size;
+
+	va_start(ap, fmt);
+	ret = vsnprintf(boot_command_line, COMMAND_LINE_SIZE, fmt, ap);
+	va_end(ap);
+
+	if (ops->virtio_devices)
+		strncpy(boot_command_line + ret, ops->virtio_devices,
+			COMMAND_LINE_SIZE - ret);
+
+	memcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+
+	ret = threads_init();
+	if (ret)
+		return ret;
+
+	init_sem = lkl_ops->sem_alloc(0);
+	if (!init_sem)
+		return -ENOMEM;
+
+	idle_sem = lkl_ops->sem_alloc(0);
+	if (!idle_sem) {
+		ret = -ENOMEM;
+		goto out_free_init_sem;
+	}
+
+	ret = lkl_ops->thread_create(lkl_run_kernel, NULL);
+	if (ret) {
+		ret = -ENOMEM;
+		goto out_free_idle_sem;
+	}
+
+	lkl_ops->sem_down(init_sem);
+
+	return 0;
+
+out_free_idle_sem:
+	lkl_ops->sem_free(idle_sem);
+
+out_free_init_sem:
+	lkl_ops->sem_free(init_sem);
+
+	return ret;
+}
+
+void machine_halt(void)
+{
+	halt = true;
+}
+
+void machine_power_off(void)
+{
+	machine_halt();
+}
+
+void machine_restart(char *unused)
+{
+	machine_halt();
+}
+
+long lkl_sys_halt(void)
+{
+	long err;
+	long params[6] = { 0, };
+
+	halt_sem = lkl_ops->sem_alloc(0);
+	if (!halt_sem)
+		return -ENOMEM;
+
+	err = lkl_syscall(__NR_reboot, params);
+	if (err < 0) {
+		lkl_ops->sem_free(halt_sem);
+		return err;
+	}
+
+	lkl_ops->sem_down(halt_sem);
+
+	lkl_ops->sem_free(halt_sem);
+	lkl_ops->sem_free(idle_sem);
+	lkl_ops->sem_free(init_sem);
+
+	return 0;
+}
+
+void arch_cpu_idle(void)
+{
+	if (halt) {
+		threads_cleanup();
+		free_IRQ();
+		free_mem();
+		lkl_ops->sem_up(halt_sem);
+		lkl_ops->thread_exit();
+	}
+
+	lkl_ops->sem_down(idle_sem);
+
+	local_irq_enable();
+}
+
+void wakeup_cpu(void)
+{
+	lkl_ops->sem_up(idle_sem);
+}
+
+/* skip mounting the "real" rootfs. ramfs is good enough. */
+static int __init fs_setup(void)
+{
+	int fd;
+
+	fd = sys_open("/init", O_CREAT, 0600);
+	WARN_ON(fd < 0);
+	sys_close(fd);
+
+	return 0;
+}
+late_initcall(fs_setup);
-- 
2.1.0

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

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


#1261863 — [RFC PATCH 20/28] lkl tools: host lib: filesystem helpers

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 20/28] lkl tools: host lib: filesystem helpers
Message-ID<qqQnp-7AN-39@gated-at.bofh.it>
In reply to#1261858
Add LKL applications APIs to mount and unmount a filesystem from a
disk added via lkl_disk_add().

Also add open/close/read directory wrappers on top of
lkl_sys_getdents64.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/include/lkl.h |  66 +++++++++++++++
 tools/lkl/lib/fs.c      | 218 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 284 insertions(+)
 create mode 100644 tools/lkl/lib/fs.c

diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h
index 0c30b23..e6a9c77 100644
--- a/tools/lkl/include/lkl.h
+++ b/tools/lkl/include/lkl.h
@@ -40,4 +40,70 @@ union lkl_disk_backstore {
  */
 int lkl_disk_add(union lkl_disk_backstore backstore);
 
+/**
+ * lkl_mount_dev - mount a disk
+ *
+ * This functions creates a device file for the given disk, creates a mount
+ * point and mounts the device over the mount point.
+ *
+ * @disk_id - the disk id identifying the disk to be mounted
+ * @fs_type - filesystem type
+ * @flags - mount flags
+ * @data - additional filesystem specific mount data
+ * @mnt_str - a string that will be filled by this function with the path where
+ * the filisystem has been mounted
+ * @mnt_str_len - size of mnt_str
+ * @returns - 0 on success, a negative value on error
+ */
+long lkl_mount_dev(unsigned int disk_id, const char *fs_type, int flags,
+		   void *data, char *mnt_str, int mnt_str_len);
+
+/**
+ * lkl_umount_dev - umount a disk
+ *
+ * This functions umounts the given disks and removes the device file and the
+ * mount point.
+ *
+ * @disk_id - the disk id identifying the disk to be mounted
+ * @flags - umount flags
+ * @timeout_ms - timeout to wait for the kernel to flush closed files so that
+ * umount can succeed
+ * @returns - 0 on success, a negative value on error
+ */
+long lkl_umount_dev(unsigned int disk_id, int flags, long timeout_ms);
+
+/**
+ * lkl_opendir - open a directory
+ *
+ * @path - directory path
+ * @err - pointer to store the error in case of failure
+ * @returns - a handle to be used when calling lkl_readdir
+ */
+struct lkl_dir *lkl_opendir(const char *path, int *err);
+
+/**
+ * lkl_closedir - close the directory
+ *
+ * @dir - the directory handler as returned by lkl_opendir
+ */
+void lkl_closedir(struct lkl_dir *dir);
+
+/**
+ * lkl_readdir - get the next available entry of the directory
+ *
+ * @dir - the directory handler as returned by lkl_opendir
+ * @returns - a lkl_dirent64 entry or NULL if the end of the directory stream is
+ * reached or if an error occurred; check lkl_errdir() to distinguish between
+ * errors or end of the directory stream
+ */
+struct lkl_dirent64 *lkl_readdir(struct lkl_dir *dir);
+
+/**
+ * lkl_errdir - checks if an error occurred during the last lkl_readdir call
+ *
+ * @dir - the directory handler as returned by lkl_opendir
+ * @returns - 0 if no error occurred, or a negative value otherwise
+ */
+int lkl_errdir(struct lkl_dir *dir);
+
 #endif
diff --git a/tools/lkl/lib/fs.c b/tools/lkl/lib/fs.c
new file mode 100644
index 0000000..16f4d44
--- /dev/null
+++ b/tools/lkl/lib/fs.c
@@ -0,0 +1,218 @@
+#include <stdio.h>
+#include <string.h>
+#include <lkl_host.h>
+
+long lkl_mount_sysfs(void)
+{
+	long ret;
+	static int sysfs_mounted;
+
+	if (sysfs_mounted)
+		return 0;
+
+	ret = lkl_sys_mkdir("/sys", 0700);
+	if (ret)
+		return ret;
+
+	ret = lkl_sys_mount("none", "sys", "sysfs", 0, NULL);
+
+	if (ret == 0)
+		sysfs_mounted = 1;
+
+	return ret;
+}
+
+static long get_virtio_blkdev(int disk_id)
+{
+	char sysfs_path[] = "/sys/block/vda/dev";
+	char buf[16] = { 0, };
+	long fd, ret;
+	int major, minor;
+
+	ret = lkl_mount_sysfs();
+	if (ret)
+		return ret;
+
+	sysfs_path[strlen("/sys/block/vd")] += disk_id;
+
+	fd = lkl_sys_open(sysfs_path, LKL_O_RDONLY, 0);
+	if (fd < 0)
+		return fd;
+
+	ret = lkl_sys_read(fd, buf, sizeof(buf));
+	if (ret < 0)
+		goto out_close;
+
+	if (ret == sizeof(buf)) {
+		ret = -LKL_ENOBUFS;
+		goto out_close;
+	}
+
+	ret = sscanf(buf, "%d:%d", &major, &minor);
+	if (ret != 2) {
+		ret = -LKL_EINVAL;
+		goto out_close;
+	}
+
+	ret = LKL_MKDEV(major, minor);
+
+out_close:
+	lkl_sys_close(fd);
+
+	return ret;
+}
+
+long lkl_mount_dev(unsigned int disk_id, const char *fs_type, int flags,
+		   void *data, char *mnt_str, int mnt_str_len)
+{
+	char dev_str[] = { "/dev/xxxxxxxx" };
+	unsigned int dev;
+	int err;
+
+	if (mnt_str_len < sizeof("/mnt/xxxxxxxx"))
+		return -LKL_ENOMEM;
+
+	dev = get_virtio_blkdev(disk_id);
+
+	snprintf(dev_str, sizeof(dev_str), "/dev/%08x", dev);
+	snprintf(mnt_str, mnt_str_len, "/mnt/%08x", dev);
+
+	err = lkl_sys_access("/dev", LKL_S_IRWXO);
+	if (err < 0) {
+		if (err == -LKL_ENOENT)
+			err = lkl_sys_mkdir("/dev", 0700);
+		if (err < 0)
+			return err;
+	}
+
+	err = lkl_sys_mknod(dev_str, LKL_S_IFBLK | 0600, dev);
+	if (err < 0)
+		return err;
+
+	err = lkl_sys_access("/mnt", LKL_S_IRWXO);
+	if (err < 0) {
+		if (err == -LKL_ENOENT)
+			err = lkl_sys_mkdir("/mnt", 0700);
+		if (err < 0)
+			return err;
+	}
+
+	err = lkl_sys_mkdir(mnt_str, 0700);
+	if (err < 0) {
+		lkl_sys_unlink(dev_str);
+		return err;
+	}
+
+	err = lkl_sys_mount(dev_str, mnt_str, fs_type, flags, data);
+	if (err < 0) {
+		lkl_sys_unlink(dev_str);
+		lkl_sys_rmdir(mnt_str);
+		return err;
+	}
+
+	return 0;
+}
+
+long lkl_umount_dev(unsigned int disk_id, int flags, long timeout_ms)
+{
+	char dev_str[] = { "/dev/xxxxxxxx" };
+	char mnt_str[] = { "/mnt/xxxxxxxx" };
+	long incr = 10000000; /* 10 ms */
+	struct lkl_timespec ts = {
+		.tv_sec = 0,
+		.tv_nsec = incr,
+	};
+	unsigned int dev;
+	int err;
+
+	dev = get_virtio_blkdev(disk_id);
+
+	snprintf(dev_str, sizeof(dev_str), "/dev/%08x", dev);
+	snprintf(mnt_str, sizeof(mnt_str), "/mnt/%08x", dev);
+
+	do {
+		err = lkl_sys_umount(mnt_str, flags);
+		if (err == -LKL_EBUSY) {
+			lkl_sys_nanosleep(&ts, NULL);
+			timeout_ms -= incr / 1000000;
+		}
+	} while (err == -LKL_EBUSY && timeout_ms > 0);
+
+	if (err)
+		return err;
+
+	err = lkl_sys_unlink(dev_str);
+	if (err)
+		return err;
+
+	return lkl_sys_rmdir(mnt_str);
+}
+
+struct lkl_dir {
+	int fd;
+	char buf[1024];
+	char *pos;
+	int len;
+};
+
+struct lkl_dir *lkl_opendir(const char *path, int *err)
+{
+	struct lkl_dir *dir = lkl_host_ops.mem_alloc(sizeof(struct lkl_dir));
+
+	if (!dir) {
+		*err = -LKL_ENOMEM;
+		return NULL;
+	}
+
+	dir->fd = lkl_sys_open(path, LKL_O_RDONLY | LKL_O_DIRECTORY, 0);
+	if (dir->fd < 0) {
+		*err = dir->fd;
+		lkl_host_ops.mem_free(dir);
+		return NULL;
+	}
+
+	dir->len = 0;
+	dir->pos = NULL;
+
+	return dir;
+}
+
+void lkl_closedir(struct lkl_dir *dir)
+{
+	lkl_sys_close(dir->fd);
+	lkl_host_ops.mem_free(dir);
+}
+
+struct lkl_dirent64 *lkl_readdir(struct lkl_dir *dir)
+{
+	struct lkl_dirent64 *de;
+
+	if (dir->len < 0)
+		return NULL;
+
+	if (!dir->pos || dir->pos - dir->buf >= dir->len)
+		goto read_buf;
+
+return_de:
+	de = (struct lkl_dirent64 *)dir->pos;
+	dir->pos += de->d_reclen;
+
+	return de;
+
+read_buf:
+	dir->pos = NULL;
+	dir->len = lkl_sys_getdents64(dir->fd, dir->buf, sizeof(dir->buf));
+	if (dir->len <= 0)
+		return NULL;
+
+	dir->pos = dir->buf;
+	goto return_de;
+}
+
+int lkl_errdir(struct lkl_dir *dir)
+{
+	if (dir->len >= 0)
+		return 0;
+
+	return dir->len;
+}
-- 
2.1.0

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

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


#1261864 — [RFC PATCH 24/28] lkl tools: tool that reads/writes to/from a filesystem image

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 24/28] lkl tools: tool that reads/writes to/from a filesystem image
Message-ID<qqQnp-7AN-41@gated-at.bofh.it>
In reply to#1261858
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/.gitignore |   2 +
 tools/lkl/Makefile   |   6 +-
 tools/lkl/cptofs.c   | 467 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 474 insertions(+), 1 deletion(-)
 create mode 100644 tools/lkl/cptofs.c

diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore
index a345a79..1048323 100644
--- a/tools/lkl/.gitignore
+++ b/tools/lkl/.gitignore
@@ -1,2 +1,4 @@
 test/boot
 fs2tar
+cptofs
+cpfromfs
diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index 9aeab49..4084609 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -12,11 +12,13 @@ ifneq (,$(filter $(shell $(LD) -r -print-output-format),elf64-x86-64 elf32-i386)
 source += $(wildcard *.c)
 lib_source += lib/posix-host.c
 LDFLAGS += -lpthread -lrt
+source += $(wildcard *.c)
+execs =  cpfromfs
 endif
 
 lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o
 objs = $(patsubst %.c,%.o, $(source))
-execs = $(patsubst %.c,%, $(source))
+execs += $(patsubst %.c,%, $(source))
 
 all: lib/liblkl.a $(execs)
 
@@ -38,3 +40,5 @@ clean:
 	-rm -rf include/lkl/ lib/liblkl.a $(lib_objs) $(objs) $(execs)
 
 fs2tar: LDFLAGS += -larchive
+cpfromfs: cptofs
+	if ! [ -e $@ ]; then ln -s $< $@; fi
diff --git a/tools/lkl/cptofs.c b/tools/lkl/cptofs.c
new file mode 100644
index 0000000..0017395
--- /dev/null
+++ b/tools/lkl/cptofs.c
@@ -0,0 +1,467 @@
+#include <stdio.h>
+#include <time.h>
+#include <argp.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#undef st_atime
+#undef st_mtime
+#undef st_ctime
+#include <dirent.h>
+#include <lkl.h>
+#include <lkl_host.h>
+
+static const char doc_cptofs[] = "Copy files to a filesystem image";
+static const char doc_cpfromfs[] = "Copy files from a filesystem image";
+static const char args_doc_cptofs[] = "-t fstype -i fsimage path fs_path";
+static const char args_doc_cpfromfs[] = "-t fstype -i fsimage fs_path path";
+
+static struct argp_option options[] = {
+	{"enable-printk", 'p', 0, 0, "show Linux printks"},
+	{"filesystem-type", 't', "string", 0,
+	 "select filesystem type - mandatory"},
+	{"filesystem-image", 'i', "string", 0,
+	 "path to the filesystem image - mandatory"},
+	{"selinux", 's', "string", 0, "selinux attributes for destination"},
+	{0},
+};
+
+static struct cl_args {
+	int printk;
+	const char *fsimg_type;
+	const char *fsimg_path;
+	const char *src_path;
+	const char *dst_path;
+	const char *selinux;
+} cla;
+
+static int cptofs;
+
+static error_t parse_opt(int key, char *arg, struct argp_state *state)
+{
+	struct cl_args *cla = state->input;
+
+	switch (key) {
+	case 'p':
+		cla->printk = 1;
+		break;
+	case 't':
+		cla->fsimg_type = arg;
+		break;
+	case 'i':
+		cla->fsimg_path = arg;
+		break;
+	case 's':
+		cla->selinux = arg;
+		break;
+	case ARGP_KEY_ARG:
+		if (!cla->src_path) {
+			cla->src_path = arg;
+		} else if (!cla->dst_path) {
+			cla->dst_path = arg;
+		} else {
+			argp_usage(state);
+			return -1;
+		}
+		break;
+	case ARGP_KEY_END:
+		if (state->arg_num < 2 || !cla->fsimg_type || !cla->fsimg_path)
+			argp_usage(state);
+	default:
+		return ARGP_ERR_UNKNOWN;
+	}
+
+	return 0;
+}
+
+static struct argp argp_cptofs = {
+	.options = options,
+	.parser = parse_opt,
+	.args_doc = args_doc_cptofs,
+	.doc = doc_cptofs,
+};
+
+static struct argp argp_cpfromfs = {
+	.options = options,
+	.parser = parse_opt,
+	.args_doc = args_doc_cpfromfs,
+	.doc = doc_cpfromfs,
+};
+
+static int searchdir(const char *fs_path, const char *path, const char *match);
+
+static int open_src(const char *path)
+{
+	int fd;
+
+	if (cptofs)
+		fd = open(path, O_RDONLY, 0);
+	else
+		fd = lkl_sys_open(path, LKL_O_RDONLY, 0);
+
+	if (fd < 0)
+		fprintf(stderr, "unable to open file %s for reading: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(fd));
+
+	return fd;
+}
+
+static int open_dst(const char *path, int mode)
+{
+	int fd;
+
+	if (cptofs)
+		fd = lkl_sys_open(path, LKL_O_RDWR | LKL_O_TRUNC | LKL_O_CREAT,
+				  mode);
+	else
+		fd = open(path, O_RDWR | O_TRUNC | O_CREAT, mode);
+
+	if (fd < 0)
+		fprintf(stderr, "unable to open file %s for writing: %s\n",
+			path, cptofs ? lkl_strerror(fd) : strerror(errno));
+
+	if (cla.selinux && cptofs) {
+		int ret = lkl_sys_fsetxattr(fd, "security.selinux", cla.selinux,
+					    strlen(cla.selinux), 0);
+		if (ret)
+			fprintf(stderr, "unable to set selinux attribute on %s: %s\n",
+				path, lkl_strerror(ret));
+	}
+
+	return fd;
+}
+
+static int read_src(int fd, char *buf, int len)
+{
+	int ret;
+
+	if (cptofs)
+		ret = read(fd, buf, len);
+	else
+		ret = lkl_sys_read(fd, buf, len);
+
+	if (ret < 0)
+		fprintf(stderr, "error reading file: %s\n",
+			cptofs ? strerror(errno) : lkl_strerror(ret));
+
+	return ret;
+}
+
+static int write_dst(int fd, char *buf, int len)
+{
+	int ret;
+
+	if (cptofs)
+		ret = lkl_sys_write(fd, buf, len);
+	else
+		ret = write(fd, buf, len);
+
+	if (ret < 0)
+		fprintf(stderr, "error writing file: %s\n",
+			cptofs ? lkl_strerror(ret) : strerror(errno));
+
+	return ret;
+}
+
+static void close_src(int fd)
+{
+	if (cptofs)
+		close(fd);
+	else
+		lkl_sys_close(fd);
+}
+
+static void close_dst(int fd)
+{
+	if (cptofs)
+		lkl_sys_close(fd);
+	else
+		close(fd);
+}
+
+static int copy_file(const char *src, const char *dst, int mode)
+{
+	long len, to_write, wrote;
+	char buf[4096], *ptr;
+	int ret = 0;
+	int fd_src, fd_dst;
+
+	fd_src = open_src(src);
+	if (fd_src < 0)
+		return fd_src;
+
+	fd_dst = open_dst(dst, mode);
+	if (fd_dst < 0)
+		return fd_dst;
+
+	do {
+		len = read_src(fd_src, buf, sizeof(buf));
+
+		if (len > 0) {
+			ptr = buf;
+			to_write = len;
+			do {
+				wrote = write_dst(fd_dst, ptr, to_write);
+
+				if (wrote < 0) {
+					ret = wrote;
+					goto out;
+				}
+
+				to_write -= wrote;
+				ptr += len;
+
+			} while (to_write > 0);
+		}
+
+		if (len < 0)
+			ret = len;
+
+	} while (len > 0);
+
+out:
+	close_src(fd_src);
+	close_dst(fd_dst);
+
+	return ret;
+}
+
+static int stat_src(const char *path, int *type, int *mode)
+{
+	struct stat stat;
+	struct lkl_stat64 lkl_stat;
+	int ret;
+
+	if (cptofs) {
+		ret = lstat(path, &stat);
+		*type = stat.st_mode & S_IFMT;
+		*mode = stat.st_mode & ~S_IFMT;
+	} else {
+		ret = lkl_sys_lstat64(path, &lkl_stat);
+		*type = lkl_stat.st_mode & S_IFMT;
+		*mode = lkl_stat.st_mode & ~S_IFMT;
+	}
+
+	if (ret)
+		fprintf(stderr, "fsimg fstat64(%s) error: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(ret));
+
+	return ret;
+}
+
+static int mkdir_dst(const char *path, int mode)
+{
+	int ret;
+
+	if (cptofs) {
+		ret = lkl_sys_mkdir(path, mode);
+		if (ret == -LKL_EEXIST)
+			ret = 0;
+	} else {
+		ret = mkdir(path, mode);
+		if (ret < 0 && errno == EEXIST)
+			ret = 0;
+	}
+
+	if (ret)
+		fprintf(stderr, "unable to create directory %s: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(ret));
+
+	return ret;
+}
+
+static int do_entry(const char *_src, const char *_dst, const char *name)
+{
+	char src[PATH_MAX], dst[PATH_MAX];
+	int type, mode;
+	int ret;
+
+	snprintf(src, sizeof(src), "%s/%s", _src, name);
+	snprintf(dst, sizeof(dst), "%s/%s", _dst, name);
+
+	ret = stat_src(src, &type, &mode);
+
+	switch (type) {
+	case S_IFREG:
+	{
+		ret = copy_file(src, dst, mode);
+		break;
+	}
+	case S_IFDIR:
+		ret = mkdir_dst(dst, mode);
+		if (ret)
+			break;
+		ret = searchdir(src, dst, NULL);
+		break;
+	case S_IFLNK:
+	case S_IFSOCK:
+	case S_IFBLK:
+	case S_IFCHR:
+	case S_IFIFO:
+	default:
+		printf("skipping %s: unsupported entry type %d\n", src, type);
+	}
+
+	if (ret)
+		printf("error processing entry %s, aborting\n", src);
+
+	return ret;
+}
+
+static DIR *open_dir(const char *path)
+{
+	DIR *dir;
+	int err;
+
+	if (cptofs)
+		dir = opendir(path);
+	else
+		dir = (DIR *)lkl_opendir(path, &err);
+
+	if (!dir)
+		fprintf(stderr, "unable to open directory %s: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(err));
+	return dir;
+}
+
+static const char *read_dir(DIR *dir, const char *path)
+{
+	struct lkl_dir *lkl_dir = (struct lkl_dir *)dir;
+	const char *name = NULL;
+	const char *err = NULL;
+
+	if (cptofs) {
+		struct dirent *de = readdir(dir);
+
+		if (de)
+			name = de->d_name;
+	} else {
+		struct lkl_dirent64 *de = lkl_readdir(lkl_dir);
+
+		if (de)
+			name = de->d_name;
+	}
+
+	if (!name) {
+		if (cptofs) {
+			if (errno)
+				err = strerror(errno);
+		} else {
+			if (lkl_errdir(lkl_dir))
+				err = lkl_strerror(lkl_errdir(lkl_dir));
+		}
+	}
+
+	if (err)
+		fprintf(stderr, "error while reading directory %s: %s\n",
+			path, err);
+	return name;
+}
+
+static void close_dir(DIR *dir)
+{
+	if (cptofs)
+		closedir(dir);
+	else
+		lkl_closedir((struct lkl_dir *)dir);
+}
+
+static int searchdir(const char *src, const char *dst, const char *match)
+{
+	DIR *dir;
+	const char *name;
+	int ret = 0;
+
+	dir = open_dir(src);
+	if (!dir)
+		return -1;
+
+	while ((name = read_dir(dir, src))) {
+		if (!strcmp(name, ".") || !strcmp(name, "..") ||
+		    (match && fnmatch(match, name, 0) != 0))
+			continue;
+
+		ret = do_entry(src, dst, name);
+		if (ret)
+			goto out;
+	}
+
+out:
+	close_dir(dir);
+
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	union lkl_disk_backstore bs;
+	long ret;
+	char mpoint[32], src_path[PATH_MAX], dst_path[PATH_MAX];
+	char *src_path_dir, *src_path_base;
+	unsigned int disk_id;
+
+	if (strstr(argv[0], "cptofs")) {
+		cptofs = 1;
+		ret = argp_parse(&argp_cptofs, argc, argv, 0, 0, &cla);
+	} else {
+		ret = argp_parse(&argp_cpfromfs, argc, argv, 0, 0, &cla);
+	}
+
+	if (ret < 0)
+		return -1;
+
+	if (!cla.printk)
+		lkl_host_ops.print = NULL;
+
+	bs.fd = open(cla.fsimg_path, cptofs ? O_RDWR : O_RDONLY);
+	if (bs.fd < 0) {
+		fprintf(stderr, "can't open fsimg %s: %s\n", cla.fsimg_path,
+			strerror(errno));
+		ret = 1;
+		goto out;
+	}
+
+	disk_id = lkl_disk_add(bs);
+	if (disk_id < 0) {
+		fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret));
+		goto out_close;
+	}
+
+	lkl_start_kernel(&lkl_host_ops, 100 * 1024 * 1024, "");
+
+	ret = lkl_mount_dev(disk_id, cla.fsimg_type, cptofs ? 0 : LKL_MS_RDONLY,
+			    NULL, mpoint, sizeof(mpoint));
+	if (ret) {
+		fprintf(stderr, "can't mount disk: %s\n", lkl_strerror(ret));
+		goto out_close;
+	}
+
+	if (cptofs) {
+		snprintf(src_path, sizeof(src_path),  "%s", cla.src_path);
+		snprintf(dst_path, sizeof(dst_path),  "%s/%s", mpoint,
+			 cla.dst_path);
+	} else {
+		snprintf(src_path, sizeof(src_path),  "%s/%s", mpoint,
+			 cla.src_path);
+		snprintf(dst_path, sizeof(dst_path),  "%s", cla.dst_path);
+	}
+
+	src_path_dir = dirname(strdup(src_path));
+	src_path_base = basename(strdup(src_path));
+
+	ret = searchdir(src_path_dir, dst_path, src_path_base);
+
+	ret = lkl_umount_dev(disk_id, 0, 1000);
+
+out_close:
+	close(bs.fd);
+
+out:
+	lkl_sys_halt();
+
+	return ret;
+}
-- 
2.1.0

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

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


#1261865 — [RFC PATCH 22/28] lkl tools: "boot" test

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 22/28] lkl tools: "boot" test
Message-ID<qqQnp-7AN-43@gated-at.bofh.it>
In reply to#1261858
Add a simple LKL test applications that starts the kernel and performs
simple tests that minimally exercise the LKL API.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/.gitignore    |   1 +
 tools/lkl/Makefile      |   7 +-
 tools/lkl/tests/boot.c  | 488 ++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lkl/tests/boot.sh |  10 +
 4 files changed, 504 insertions(+), 2 deletions(-)
 create mode 100644 tools/lkl/tests/boot.c
 create mode 100755 tools/lkl/tests/boot.sh

diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore
index e69de29..7c456f2 100644
--- a/tools/lkl/.gitignore
+++ b/tools/lkl/.gitignore
@@ -0,0 +1 @@
+test/boot
diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index cf97d27..1ae4481 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -7,14 +7,17 @@ LD=$(CROSS_COMPILE)ld
 endif
 
 lib_source = $(filter-out %-host.c,$(wildcard lib/*.c))
+source = $(wildcard tests/*.c)
 ifneq (,$(filter $(shell $(LD) -r -print-output-format),elf64-x86-64 elf32-i386))
 lib_source += lib/posix-host.c
 LDFLAGS += -lpthread -lrt
 endif
 
 lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o
+objs = $(patsubst %.c,%.o, $(source))
+execs = $(patsubst %.c,%, $(source))
 
-all: lib/liblkl.a
+all: lib/liblkl.a $(execs)
 
 lib/liblkl.a: $(lib_objs)
 	$(AR) -rc $@ $^
@@ -31,4 +34,4 @@ $(objs): lib/lkl.o
 $(execs): lib/liblkl.a
 
 clean:
-	-rm -rf include/lkl/ lib/liblkl.a $(lib_objs)
+	-rm -rf include/lkl/ lib/liblkl.a $(lib_objs) $(objs) $(execs)
diff --git a/tools/lkl/tests/boot.c b/tools/lkl/tests/boot.c
new file mode 100644
index 0000000..f5945aa
--- /dev/null
+++ b/tools/lkl/tests/boot.c
@@ -0,0 +1,488 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <lkl.h>
+#include <lkl_host.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static struct cl_args {
+	int printk;
+	const char *disk_filename;
+} cla;
+
+static struct cl_option {
+	const char *long_name;
+	char short_name;
+	const char *help;
+	int has_arg;
+} options[] = {
+	{"enable-printk", 'p', "show Linux printks", 0},
+	{"disk-file", 'd', "disk file to use", 1},
+	{0},
+};
+
+static int parse_opt(int key, char *arg)
+{
+	switch (key) {
+	case 'p':
+		cla.printk = 1;
+		break;
+	case 'd':
+		cla.disk_filename = arg;
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+void printk(const char *str, int len)
+{
+	if (cla.printk)
+		write(STDOUT_FILENO, str, len);
+}
+
+#define TEST(name) do_test(#name, test_##name)
+
+static void do_test(char *name, int (*fn)(char *, int))
+{
+	char str[60];
+	int result;
+
+	result = fn(str, sizeof(str));
+	printf("%-20s %s [%s]\n", name, result ? "passed" : "failed", str);
+}
+
+#define sleep_ns 87654321
+
+int test_nanosleep(char *str, int len)
+{
+	struct lkl_timespec ts = {
+		.tv_sec = 0,
+		.tv_nsec = sleep_ns,
+	};
+	struct timespec start, stop;
+	long delta;
+	long ret;
+
+	clock_gettime(CLOCK_MONOTONIC, &start);
+	ret = lkl_sys_nanosleep(&ts, NULL);
+	clock_gettime(CLOCK_MONOTONIC, &stop);
+
+	delta = (stop.tv_sec - start.tv_sec) +
+		(stop.tv_nsec - start.tv_nsec);
+
+	snprintf(str, len, "%ld", delta);
+
+	if (ret == 0 && delta > sleep_ns * 0.9 && delta < sleep_ns * 1.1)
+		return 1;
+
+	return 0;
+}
+
+int test_getpid(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_getpid();
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 1)
+		return 1;
+
+	return 0;
+}
+
+#define access_rights 0721
+
+int test_creat(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_creat("/file", access_rights);
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+int test_close(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_close(0);
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+int test_failopen(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_open("/file2", 0, 0);
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == -LKL_ENOENT)
+		return 1;
+
+	return 0;
+}
+
+int test_umask(char *str, int len)
+{
+	long ret, ret2;
+
+	ret = lkl_sys_umask(0777);
+
+	ret2 = lkl_sys_umask(0);
+
+	snprintf(str, len, "%lo %lo", ret, ret2);
+
+	if (ret > 0 && ret2 == 0777)
+		return 1;
+
+	return 0;
+}
+
+int test_open(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_open("/file", LKL_O_RDWR, 0);
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+static const char write_test[] = "test";
+
+int test_write(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_write(0, write_test, sizeof(write_test));
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == sizeof(write_test))
+		return 1;
+
+	return 0;
+}
+
+int test_lseek(char *str, int len)
+{
+	long ret;
+	__lkl__kernel_loff_t res;
+
+	ret = lkl_sys_lseek(0, 0, &res, LKL_SEEK_SET);
+
+	snprintf(str, len, "%ld %lld", ret, res);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+int test_read(char *str, int len)
+{
+	char buf[10] = { 0, };
+	long ret;
+
+	ret = lkl_sys_read(0, buf, sizeof(buf));
+
+	snprintf(str, len, "%ld %s", ret, buf);
+
+	if (ret == sizeof(write_test) && strcmp(write_test, buf) == 0)
+		return 1;
+
+	return 0;
+}
+
+int test_fstat64(char *str, int len)
+{
+	struct lkl_stat64 stat;
+	long ret;
+
+	ret = lkl_sys_fstat64(0, &stat);
+
+	snprintf(str, len, "%ld %o %lld", ret, stat.st_mode, stat.st_size);
+
+	if (ret == 0 && stat.st_size == sizeof(write_test) &&
+	    stat.st_mode == (access_rights | LKL_S_IFREG))
+		return 1;
+
+	return 0;
+}
+
+int test_mkdir(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_mkdir("/mnt", access_rights);
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+int test_stat64(char *str, int len)
+{
+	struct lkl_stat64 stat;
+	long ret;
+
+	ret = lkl_sys_stat64("/mnt", &stat);
+
+	snprintf(str, len, "%ld %o", ret, stat.st_mode);
+
+	if (ret == 0 && stat.st_mode == (access_rights | LKL_S_IFDIR))
+		return 1;
+
+	return 0;
+}
+
+static const char *tmp_file;
+static union lkl_disk_backstore bs;
+static int disk_id = -1;
+
+int test_disk_add(char *str, int len)
+{
+	bs.fd = open(cla.disk_filename, O_RDWR);
+	if (bs.fd < 0)
+		goto out_unlink;
+
+	disk_id = lkl_disk_add(bs);
+	if (disk_id < 0)
+		goto out_close;
+
+	goto out;
+
+out_close:
+	close(bs.fd);
+out_unlink:
+	unlink(cla.disk_filename);
+
+out:
+	snprintf(str, len, "%x %d", bs.fd, disk_id);
+
+	if (disk_id >= 0)
+		return 1;
+
+	return 0;
+}
+
+static char mnt_point[32];
+
+static int test_mount(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_mount_dev(disk_id, "ext4", 0, NULL, mnt_point,
+			    sizeof(mnt_point));
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+static int test_chdir(char *str, int len)
+{
+	long ret;
+
+	ret = lkl_sys_chdir(mnt_point);
+
+	snprintf(str, len, "%ld", ret);
+
+	if (ret == 0)
+		return 1;
+
+	return 0;
+}
+
+static int dir_fd;
+
+static int test_opendir(char *str, int len)
+{
+	dir_fd = lkl_sys_open(".", LKL_O_RDONLY | LKL_O_DIRECTORY, 0);
+
+	snprintf(str, len, "%d", dir_fd);
+
+	if (dir_fd > 0)
+		return 1;
+
+	return 0;
+}
+
+static int test_getdents64(char *str, int len)
+{
+	long ret;
+	char buf[1024], *pos;
+	struct lkl_dirent64 *de;
+	int wr;
+
+	ret = lkl_sys_getdents64(dir_fd, buf, sizeof(buf));
+
+	wr = snprintf(str, len, "%d ", dir_fd);
+	str += wr;
+	len -= wr;
+
+	if (ret < 0)
+		return 0;
+
+	for (pos = buf; pos - buf < ret; pos += de->d_reclen) {
+		de = (struct lkl_dirent64 *)pos;
+
+		wr = snprintf(str, len, "%s ", de->d_name);
+		str += wr;
+		len -= wr;
+	}
+
+	return 1;
+}
+
+static int test_umount(char *str, int len)
+{
+	long ret, ret2, ret3;
+
+	ret = lkl_sys_close(dir_fd);
+
+	ret2 = lkl_sys_chdir("/");
+
+	ret3 = lkl_umount_dev(disk_id, 0, 1000);
+
+	snprintf(str, len, "%ld %ld %ld", ret, ret2, ret3);
+
+	if (!ret && !ret2 && !ret3)
+		return 1;
+
+	return 0;
+}
+
+static struct cl_option *find_short_opt(char name)
+{
+	struct cl_option *opt;
+
+	for (opt = options; opt->short_name != 0; opt++) {
+		if (opt->short_name == name)
+			return opt;
+	}
+
+	return NULL;
+}
+
+static struct cl_option *find_long_opt(const char *name)
+{
+	struct cl_option *opt;
+
+	for (opt = options; opt->long_name; opt++) {
+		if (strcmp(opt->long_name, name) == 0)
+			return opt;
+	}
+
+	return NULL;
+}
+
+static void print_help(void)
+{
+	struct cl_option *opt;
+
+	printf("usage:\n");
+	for (opt = options; opt->long_name; opt++)
+		printf("-%c, --%-20s %s\n", opt->short_name, opt->long_name,
+		       opt->help);
+}
+
+static int parse_opts(int argc, char **argv)
+{
+	int i;
+
+	for (i = 1; i < argc; i++) {
+		struct cl_option *opt = NULL;
+
+		if (argv[i][0] == '-') {
+			if (argv[i][1] != '-')
+				opt = find_short_opt(argv[i][1]);
+			else
+				opt = find_long_opt(&argv[i][2]);
+		}
+
+		if (!opt) {
+			print_help();
+			return -1;
+		}
+
+		if (parse_opt(opt->short_name, argv[i + 1]) < 0) {
+			print_help();
+			return -1;
+		}
+
+		if (opt->has_arg)
+			i++;
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	if (parse_opts(argc, argv) < 0)
+		return -1;
+
+	lkl_host_ops.print = printk;
+
+	TEST(disk_add);
+
+	lkl_start_kernel(&lkl_host_ops, 10 * 1024 * 1024, "");
+
+	TEST(getpid);
+	TEST(umask);
+	TEST(creat);
+	TEST(close);
+	TEST(failopen);
+	TEST(open);
+	TEST(write);
+	TEST(lseek);
+	TEST(read);
+	TEST(fstat64);
+	TEST(mkdir);
+	TEST(stat64);
+	TEST(nanosleep);
+	TEST(mount);
+	TEST(chdir);
+	TEST(opendir);
+	TEST(getdents64);
+	TEST(umount);
+
+	lkl_sys_halt();
+
+	close(bs.fd);
+	unlink(tmp_file);
+
+	return 0;
+}
diff --git a/tools/lkl/tests/boot.sh b/tools/lkl/tests/boot.sh
new file mode 100755
index 0000000..3fb7b1f
--- /dev/null
+++ b/tools/lkl/tests/boot.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+file=`mktemp`
+dd if=/dev/zero of=$file bs=1024 count=10240
+
+yes | mkfs.ext4 -q $file
+
+./boot -d $file $@
+
+rm $file
-- 
2.1.0

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

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


#1261866 — [RFC PATCH 02/28] kbuild: allow architectures to automatically define kconfig symbols

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 02/28] kbuild: allow architectures to automatically define kconfig symbols
Message-ID<qqQnp-7AN-51@gated-at.bofh.it>
In reply to#1261858
This patch calls an architecture hook during the kernel config process
that allows the architecture to automatically define kconfig
symbols. This can be done by exporting environment variables from the
new architecture hook.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index d5b3739..668b8fe 100644
--- a/Makefile
+++ b/Makefile
@@ -554,6 +554,7 @@ endif # KBUILD_EXTMOD
 
 ifeq ($(dot-config),1)
 # Read in config
+-include arch/$(SRCARCH)/auto.conf
 -include include/config/auto.conf
 
 ifeq ($(KBUILD_EXTMOD),)
-- 
2.1.0

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

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


#1261867 — [RFC PATCH 17/28] lkl tools: host lib: memory mapped I/O helpers

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 17/28] lkl tools: host lib: memory mapped I/O helpers
Message-ID<qqQnp-7AN-45@gated-at.bofh.it>
In reply to#1261858
This patch adds helpers for implementing the memory mapped I/O host
operations that can be used by code that implements host
devices. Generic host operations for lkl_ioremap and lkl_iomem_access
are provided that allows multiplexing multiple I/O memory mapped
regions.

The host device code can create a new memory mapped I/O region with
register_iomem(). Read and write access functions need to be provided
by the caller.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/lib/iomem.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lkl/lib/iomem.h |  14 ++++++
 2 files changed, 133 insertions(+)
 create mode 100644 tools/lkl/lib/iomem.c
 create mode 100644 tools/lkl/lib/iomem.h

diff --git a/tools/lkl/lib/iomem.c b/tools/lkl/lib/iomem.c
new file mode 100644
index 0000000..bef6b71
--- /dev/null
+++ b/tools/lkl/lib/iomem.c
@@ -0,0 +1,119 @@
+#include <string.h>
+#include <stdint.h>
+#include <lkl_host.h>
+
+#include "iomem.h"
+
+#define IOMEM_OFFSET_BITS		24
+#define IOMEM_ADDR_MARK			0x8000000
+#define MAX_IOMEM_REGIONS		(IOMEM_ADDR_MARK >> IOMEM_OFFSET_BITS)
+
+#define IOMEM_ADDR_TO_INDEX(addr) \
+	((((uintptr_t)addr & ~IOMEM_ADDR_MARK) >> IOMEM_OFFSET_BITS))
+#define IOMEM_ADDR_TO_OFFSET(addr) \
+	(((uintptr_t)addr) & ((1 << IOMEM_OFFSET_BITS) - 1))
+#define IOMEM_INDEX_TO_ADDR(i) \
+	(void *)(uintptr_t)((i << IOMEM_OFFSET_BITS) | IOMEM_ADDR_MARK)
+
+static struct iomem_region {
+	void *base;
+	void *iomem_addr;
+	int size;
+	const struct lkl_iomem_ops *ops;
+} *iomem_regions[MAX_IOMEM_REGIONS];
+
+static struct iomem_region *find_iomem_reg(void *base)
+{
+	int i;
+
+	for (i = 0; i < MAX_IOMEM_REGIONS; i++)
+		if (iomem_regions[i] && iomem_regions[i]->base == base)
+			return iomem_regions[i];
+
+	return NULL;
+}
+
+int register_iomem(void *base, int size, const struct lkl_iomem_ops *ops)
+{
+	struct iomem_region *iomem_reg;
+	int i;
+
+	if (size > (1 << IOMEM_OFFSET_BITS) - 1)
+		return -1;
+
+	if (find_iomem_reg(base))
+		return -1;
+
+	for (i = 0; i < MAX_IOMEM_REGIONS; i++)
+		if (!iomem_regions[i])
+			break;
+
+	if (i >= MAX_IOMEM_REGIONS)
+		return -1;
+
+	iomem_reg = lkl_host_ops.mem_alloc(sizeof(*iomem_reg));
+	if (!iomem_reg)
+		return -1;
+
+	iomem_reg->base = base;
+	iomem_reg->size = size;
+	iomem_reg->ops = ops;
+	iomem_reg->iomem_addr = IOMEM_INDEX_TO_ADDR(i);
+
+	iomem_regions[i] = iomem_reg;
+
+	return 0;
+}
+
+void unregister_iomem(void *iomem_base)
+{
+	struct iomem_region *iomem_reg = find_iomem_reg(iomem_base);
+	unsigned int index;
+
+	if (!iomem_reg) {
+		lkl_printf("%s: invalid iomem base %p\n", __func__, iomem_base);
+		return;
+	}
+
+	index = IOMEM_ADDR_TO_INDEX(iomem_reg->iomem_addr);
+	if (index >= MAX_IOMEM_REGIONS) {
+		lkl_printf("%s: invalid iomem_addr %p\n", __func__,
+			   iomem_reg->iomem_addr);
+		return;
+	}
+
+	iomem_regions[index] = NULL;
+	lkl_host_ops.mem_free(iomem_reg->base);
+	lkl_host_ops.mem_free(iomem_reg);
+}
+
+void *lkl_ioremap(long addr, int size)
+{
+	struct iomem_region *iomem_reg = find_iomem_reg((void *)addr);
+
+	if (iomem_reg && size <= iomem_reg->size)
+		return iomem_reg->iomem_addr;
+
+	return NULL;
+}
+
+int lkl_iomem_access(const volatile void *addr, void *res, int size, int write)
+{
+	struct iomem_region *iomem_reg;
+	int index = IOMEM_ADDR_TO_INDEX(addr);
+	int offset = IOMEM_ADDR_TO_OFFSET(addr);
+	int ret;
+
+	if (index > MAX_IOMEM_REGIONS || !iomem_regions[index] ||
+	    offset + size > iomem_regions[index]->size)
+		return -1;
+
+	iomem_reg = iomem_regions[index];
+
+	if (write)
+		ret = iomem_reg->ops->write(iomem_reg->base, offset, res, size);
+	else
+		ret = iomem_reg->ops->read(iomem_reg->base, offset, res, size);
+
+	return ret;
+}
diff --git a/tools/lkl/lib/iomem.h b/tools/lkl/lib/iomem.h
new file mode 100644
index 0000000..53707d7
--- /dev/null
+++ b/tools/lkl/lib/iomem.h
@@ -0,0 +1,14 @@
+#ifndef _LKL_LIB_IOMEM_H
+#define _LKL_LIB_IOMEM_H
+
+struct lkl_iomem_ops {
+	int (*read)(void *data, int offset, void *res, int size);
+	int (*write)(void *data, int offset, void *value, int size);
+};
+
+int register_iomem(void *base, int size, const struct lkl_iomem_ops *ops);
+void unregister_iomem(void *iomem_base);
+void *lkl_ioremap(long addr, int size);
+int lkl_iomem_access(const volatile void *addr, void *res, int size, int write);
+
+#endif /* _LKL_LIB_IOMEM_H */
-- 
2.1.0

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

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


#1261870 — [RFC PATCH 28/28] lkl tools: add support for Windows host

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 28/28] lkl tools: add support for Windows host
Message-ID<qqQnq-7AN-55@gated-at.bofh.it>
In reply to#1261858
Add host operations for Windows host and virtio disk support.

Trivial changes to the generic virtio host code are made since mingw %p
format is different then what the MMIO virtion driver expects.

The boot test is updated to support Window hosts as well.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/Makefile      |   5 +-
 tools/lkl/include/lkl.h |   5 +-
 tools/lkl/lib/nt-host.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lkl/lib/virtio.c  |   4 +-
 tools/lkl/lib/virtio.h  |   8 ++
 tools/lkl/tests/boot.c  |  26 ++++++
 6 files changed, 270 insertions(+), 5 deletions(-)
 create mode 100644 tools/lkl/lib/nt-host.c

diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index 4084609..d3d0e0b 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -14,6 +14,9 @@ lib_source += lib/posix-host.c
 LDFLAGS += -lpthread -lrt
 source += $(wildcard *.c)
 execs =  cpfromfs
+else ifeq ($(shell $(LD) -r -print-output-format),pe-i386)
+lib_source += lib/nt-host.c
+KOPT="KALLSYMS_EXTRA_PASS=1"
 endif
 
 lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o
@@ -27,7 +30,7 @@ lib/liblkl.a: $(lib_objs)
 
 lib/lkl.o:
 	$(MAKE) -C ../.. ARCH=lkl defconfig
-	$(MAKE) -C ../.. ARCH=lkl install INSTALL_PATH=$(PWD)
+	$(MAKE) -C ../.. ARCH=lkl $(KOPT) install INSTALL_PATH=$(PWD)
 
 %: %.o
 	$(CC) -o $@ $^ $(LDFLAGS)
diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h
index e6a9c77..aebd635 100644
--- a/tools/lkl/include/lkl.h
+++ b/tools/lkl/include/lkl.h
@@ -23,11 +23,12 @@ const char *lkl_strerror(int err);
 /**
  * lkl_disk_backstore - host dependend disk backstore
  *
- * @fd - an open file descriptor that can be used by preadv/pwritev; used by
- * POSIX hosts
+ * @fd - a POSIX file descriptor that can be used by preadv/pwritev
+ * @handle - an NT file handle that can be used by ReadFile/WriteFile
  */
 union lkl_disk_backstore {
 	int fd;
+	void *handle;
 };
 
 /**
diff --git a/tools/lkl/lib/nt-host.c b/tools/lkl/lib/nt-host.c
new file mode 100644
index 0000000..9ac2dd7
--- /dev/null
+++ b/tools/lkl/lib/nt-host.c
@@ -0,0 +1,227 @@
+#include <windows.h>
+#include <assert.h>
+#include <unistd.h>
+#include <lkl_host.h>
+#include "iomem.h"
+
+static void *sem_alloc(int count)
+{
+	return CreateSemaphore(NULL, count, 100, NULL);
+}
+
+static void sem_up(void *sem)
+{
+	ReleaseSemaphore(sem, 1, NULL);
+}
+
+static void sem_down(void *sem)
+{
+	WaitForSingleObject(sem, INFINITE);
+}
+
+static void sem_free(void *sem)
+{
+	CloseHandle(sem);
+}
+
+static int thread_create(void (*fn)(void *), void *arg)
+{
+	DWORD WINAPI (*win_fn)(LPVOID arg) = (DWORD WINAPI (*)(LPVOID))fn;
+
+	return CreateThread(NULL, 0, win_fn, arg, 0, NULL) ? 0 : -1;
+}
+
+static void thread_exit(void)
+{
+	ExitThread(0);
+}
+
+
+/*
+ * With 64 bits, we can cover about 583 years at a nanosecond resolution.
+ * Windows counts time from 1601 so we do have about 100 years before we
+ * overflow.
+ */
+static unsigned long long time_ns(void)
+{
+	SYSTEMTIME st;
+	FILETIME ft;
+	LARGE_INTEGER li;
+
+	GetSystemTime(&st);
+	SystemTimeToFileTime(&st, &ft);
+	li.LowPart = ft.dwLowDateTime;
+	li.HighPart = ft.dwHighDateTime;
+
+	return li.QuadPart*100;
+}
+
+struct timer {
+	HANDLE queue;
+	void (*callback)(void *);
+	void *arg;
+};
+
+static void *timer_alloc(void (*fn)(void *), void *arg)
+{
+	struct timer *t;
+
+	t = malloc(sizeof(*t));
+	if (!t)
+		return NULL;
+
+	t->queue = CreateTimerQueue();
+	if (!t->queue) {
+		free(t);
+		return NULL;
+	}
+
+	t->callback = fn;
+	t->arg = arg;
+
+	return t;
+}
+
+static void CALLBACK timer_callback(void *arg, BOOLEAN TimerOrWaitFired)
+{
+	struct timer *t = (struct timer *)arg;
+
+	if (TimerOrWaitFired)
+		t->callback(t->arg);
+}
+
+static int timer_set_oneshot(void *timer, unsigned long ns)
+{
+	struct timer *t = (struct timer *)timer;
+	HANDLE tmp;
+
+	return !CreateTimerQueueTimer(&tmp, t->queue, timer_callback, t,
+				      ns / 1000000, 0, 0);
+}
+
+static void timer_free(void *timer)
+{
+	struct timer *t = (struct timer *)timer;
+	HANDLE completion;
+
+	completion = CreateEvent(NULL, FALSE, FALSE, NULL);
+	DeleteTimerQueueEx(t->queue, completion);
+	WaitForSingleObject(completion, INFINITE);
+	free(t);
+}
+
+static void panic(void)
+{
+	int *x = NULL;
+
+	*x = 1;
+	assert(0);
+}
+
+static void print(const char *str, int len)
+{
+	write(1, str, len);
+}
+
+static void *mem_alloc(unsigned long size)
+{
+	return malloc(size);
+}
+
+struct lkl_host_operations lkl_host_ops = {
+	.panic = panic,
+	.thread_create = thread_create,
+	.thread_exit = thread_exit,
+	.sem_alloc = sem_alloc,
+	.sem_free = sem_free,
+	.sem_up = sem_up,
+	.sem_down = sem_down,
+	.time = time_ns,
+	.timer_alloc = timer_alloc,
+	.timer_set_oneshot = timer_set_oneshot,
+	.timer_free = timer_free,
+	.print = print,
+	.mem_alloc = mem_alloc,
+	.mem_free = free,
+	.ioremap = lkl_ioremap,
+	.iomem_access = lkl_iomem_access,
+	.virtio_devices = lkl_virtio_devs,
+};
+
+int handle_get_capacity(union lkl_disk_backstore bs, unsigned long long *res)
+{
+	LARGE_INTEGER tmp;
+
+	if (!GetFileSizeEx(bs.handle, &tmp))
+		return -1;
+
+	*res = tmp.QuadPart;
+	return 0;
+}
+
+void handle_do_rw(union lkl_disk_backstore bs, unsigned int type,
+		  unsigned int prio, unsigned long long sector,
+		  struct lkl_dev_buf *bufs, int count)
+{
+	unsigned long long offset = sector * 512;
+	OVERLAPPED ov = { 0, };
+	int err = 0, ret;
+
+	switch (type) {
+	case LKL_DEV_BLK_TYPE_READ:
+	case LKL_DEV_BLK_TYPE_WRITE:
+	{
+		int i;
+
+		for (i = 0; i < count; i++) {
+			DWORD res;
+
+			ov.Offset = offset & 0xffffffff;
+			ov.OffsetHigh = offset >> 32;
+
+			if (type == LKL_DEV_BLK_TYPE_READ)
+				ret = ReadFile(bs.handle, bufs[i].addr,
+					       bufs[i].len, &res, &ov);
+			else
+				ret = WriteFile(bs.handle, bufs[i].addr,
+						bufs[i].len, &res, &ov);
+			if (!ret) {
+				lkl_printf("%s: I/O error: %d\n", __func__,
+					   GetLastError());
+				err = -1;
+				goto out;
+			}
+
+			if (res != bufs[i].len) {
+				lkl_printf("%s: I/O error: short: %d %d\n",
+					   res, bufs[i].len);
+				err = -1;
+				goto out;
+			}
+
+			offset += bufs[i].len;
+		}
+		break;
+	}
+	case LKL_DEV_BLK_TYPE_FLUSH:
+	case LKL_DEV_BLK_TYPE_FLUSH_OUT:
+		ret = FlushFileBuffers(bs.handle);
+		if (!ret)
+			err = 1;
+		break;
+	default:
+		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_UNSUP, 0);
+		return;
+	}
+
+out:
+	if (err < 0)
+		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_IOERR, 0);
+	else
+		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_OK, err);
+}
+
+struct lkl_dev_blk_ops lkl_dev_blk_ops = {
+	.get_capacity = handle_get_capacity,
+	.request = handle_do_rw,
+};
diff --git a/tools/lkl/lib/virtio.c b/tools/lkl/lib/virtio.c
index 034152e..17522b2 100644
--- a/tools/lkl/lib/virtio.c
+++ b/tools/lkl/lib/virtio.c
@@ -350,8 +350,8 @@ int virtio_dev_setup(struct virtio_dev *dev, int queues, int num_max)
 		lkl_host_ops.mem_free(dev->queue);
 
 	avail = sizeof(lkl_virtio_devs) - (devs - lkl_virtio_devs);
-	devs += snprintf(devs, avail, " virtio_mmio.device=%d@%p:%d",
-			 mmio_size, dev, dev->irq);
+	devs += snprintf(devs, avail, " virtio_mmio.device=%d@0x%lx:%d",
+			 mmio_size, (uintptr_t)dev, dev->irq);
 
 	return ret;
 }
diff --git a/tools/lkl/lib/virtio.h b/tools/lkl/lib/virtio.h
index 1bacbe6..b76b18b 100644
--- a/tools/lkl/lib/virtio.h
+++ b/tools/lkl/lib/virtio.h
@@ -81,6 +81,14 @@ void virtio_dev_complete(struct virtio_dev_req *req, uint32_t len);
 #define container_of(ptr, type, member) \
 	(type *)((char *)(ptr) - __builtin_offsetof(type, member))
 
+#ifndef __MINGW32__
 #include <endian.h>
+#else
+#define le32toh(x) (x)
+#define le16toh(x) (x)
+#define htole32(x) (x)
+#define htole16(x) (x)
+#define le64toh(x) (x)
+#endif
 
 #endif /* _LKL_LIB_VIRTIO_H */
diff --git a/tools/lkl/tests/boot.c b/tools/lkl/tests/boot.c
index f5945aa..8b401b7 100644
--- a/tools/lkl/tests/boot.c
+++ b/tools/lkl/tests/boot.c
@@ -4,10 +4,17 @@
 #include <time.h>
 #include <stdlib.h>
 #include <stdint.h>
+#ifndef __MINGW32__
+#include <argp.h>
+#endif
 #include <lkl.h>
 #include <lkl_host.h>
+#ifndef __MINGW32__
 #include <sys/stat.h>
 #include <fcntl.h>
+#else
+#include <windows.h>
+#endif
 
 static struct cl_args {
 	int printk;
@@ -60,6 +67,7 @@ static void do_test(char *name, int (*fn)(char *, int))
 
 #define sleep_ns 87654321
 
+#ifndef __MINGW32__
 int test_nanosleep(char *str, int len)
 {
 	struct lkl_timespec ts = {
@@ -84,6 +92,7 @@ int test_nanosleep(char *str, int len)
 
 	return 0;
 }
+#endif
 
 int test_getpid(char *str, int len)
 {
@@ -270,8 +279,14 @@ static int disk_id = -1;
 
 int test_disk_add(char *str, int len)
 {
+#ifdef __MINGW32__
+	bs.handle = CreateFile(cla.disk_filename, GENERIC_READ | GENERIC_WRITE,
+			       0, NULL, OPEN_EXISTING, 0, NULL);
+	if (!bs.handle)
+#else
 	bs.fd = open(cla.disk_filename, O_RDWR);
 	if (bs.fd < 0)
+#endif
 		goto out_unlink;
 
 	disk_id = lkl_disk_add(bs);
@@ -281,9 +296,18 @@ int test_disk_add(char *str, int len)
 	goto out;
 
 out_close:
+#ifdef __MINGW32__
+	CloseHandle(bs.handle);
+#else
 	close(bs.fd);
+#endif
+
 out_unlink:
+#ifdef __MINGW32__
+	DeleteFile(cla.disk_filename);
+#else
 	unlink(cla.disk_filename);
+#endif
 
 out:
 	snprintf(str, len, "%x %d", bs.fd, disk_id);
@@ -472,7 +496,9 @@ int main(int argc, char **argv)
 	TEST(fstat64);
 	TEST(mkdir);
 	TEST(stat64);
+#ifndef __MINGW32__
 	TEST(nanosleep);
+#endif
 	TEST(mount);
 	TEST(chdir);
 	TEST(opendir);
-- 
2.1.0

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

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


#1261871 — [RFC PATCH 09/28] lkl: timers, time and delay support

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 09/28] lkl: timers, time and delay support
Message-ID<qqQnq-7AN-57@gated-at.bofh.it>
In reply to#1261858
Clockevent driver based on host timer operations and clocksource
driver and udelay support based on host time operations.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 arch/lkl/kernel/time.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 125 insertions(+)
 create mode 100644 arch/lkl/kernel/time.c

diff --git a/arch/lkl/kernel/time.c b/arch/lkl/kernel/time.c
new file mode 100644
index 0000000..d099736
--- /dev/null
+++ b/arch/lkl/kernel/time.c
@@ -0,0 +1,125 @@
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/host_ops.h>
+
+void __ndelay(unsigned long nsecs)
+{
+	unsigned long long start = lkl_ops->time();
+
+	while (lkl_ops->time() < start + nsecs)
+		;
+}
+
+void __udelay(unsigned long usecs)
+{
+	__ndelay(usecs * NSEC_PER_USEC);
+}
+
+void __const_udelay(unsigned long xloops)
+{
+	__udelay(xloops / 5);
+}
+
+void calibrate_delay(void)
+{
+}
+
+static cycle_t clock_read(struct clocksource *cs)
+{
+	return lkl_ops->time();
+}
+
+static struct clocksource clocksource = {
+	.name	= "lkl",
+	.rating = 499,
+	.read	= clock_read,
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+	.mask	= CLOCKSOURCE_MASK(64),
+};
+
+static void *timer;
+
+static int timer_irq;
+
+static void timer_fn(void *arg)
+{
+	lkl_trigger_irq(timer_irq, NULL);
+}
+
+static int clockevent_set_state_shutdown(struct clock_event_device *evt)
+{
+	if (timer) {
+		lkl_ops->timer_free(timer);
+		timer = NULL;
+	}
+
+	return 0;
+}
+
+static int clockevent_set_state_oneshot(struct clock_event_device *evt)
+{
+	timer = lkl_ops->timer_alloc(timer_fn, NULL);
+	if (!timer)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *dev = (struct clock_event_device *)dev_id;
+
+	dev->event_handler(dev);
+
+	return IRQ_HANDLED;
+}
+
+static int clockevent_next_event(unsigned long hz,
+				 struct clock_event_device *evt)
+{
+	unsigned long ns = 1000000000 * hz / HZ;
+
+	return lkl_ops->timer_set_oneshot(timer, ns);
+}
+
+static struct clock_event_device clockevent = {
+	.name			= "lkl",
+	.features		= CLOCK_EVT_FEAT_ONESHOT,
+	.set_state_oneshot	= clockevent_set_state_oneshot,
+	.set_next_event		= clockevent_next_event,
+	.set_state_shutdown	= clockevent_set_state_shutdown,
+};
+
+static struct irqaction irq0  = {
+	.handler = timer_irq_handler,
+	.flags = IRQF_NOBALANCING | IRQF_TIMER,
+	.dev_id = &clockevent,
+	.name = "timer"
+};
+
+void __init time_init(void)
+{
+	int ret;
+
+	if (!lkl_ops->timer_alloc || !lkl_ops->timer_free ||
+	    !lkl_ops->timer_set_oneshot || !lkl_ops->time) {
+		pr_err("lkl: no time or timer support provided by host\n");
+		return;
+	}
+
+	timer_irq = lkl_get_free_irq("timer");
+	setup_irq(timer_irq, &irq0);
+
+	ret = clocksource_register_khz(&clocksource, 1000000);
+	if (ret)
+		pr_err("lkl: unable to register clocksource\n");
+
+	clockevents_config_and_register(&clockevent, HZ, 0, 0xffffffff);
+
+	pr_info("lkl: time and timers initialized\n");
+}
-- 
2.1.0

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

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


#1261872 — [RFC PATCH 16/28] lkl tools: host lib: add lkl_strerror and lkl_printf

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:30 +0100
Subject[RFC PATCH 16/28] lkl tools: host lib: add lkl_strerror and lkl_printf
Message-ID<qqQnp-7AN-47@gated-at.bofh.it>
In reply to#1261858
Add basic utility functions for getting a string from a kernel error
code and a fprintf like function that uses the host print
operation. The latter is useful for informing the user about errors
that occur in the host library.

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/include/lkl.h      |   8 ++
 tools/lkl/include/lkl_host.h |   7 ++
 tools/lkl/lib/utils.c        | 177 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 192 insertions(+)
 create mode 100644 tools/lkl/lib/utils.c

diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h
index 2de5ed4..958614d 100644
--- a/tools/lkl/include/lkl.h
+++ b/tools/lkl/include/lkl.h
@@ -12,4 +12,12 @@ static inline long lkl_sys_lseek(unsigned int fd, __lkl__kernel_loff_t off,
 	return lkl_sys_llseek(fd, off >> 32, off & 0xffffffff, res, whence);
 }
 
+/**
+ * lkl_strerror - returns a string describing the given error code
+ *
+ * @err - error code
+ * @returns - string for the given error code
+ */
+const char *lkl_strerror(int err);
+
 #endif
diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h
index 8ee9ba0..9f1c270 100644
--- a/tools/lkl/include/lkl_host.h
+++ b/tools/lkl/include/lkl_host.h
@@ -6,4 +6,11 @@
 
 extern struct lkl_host_operations lkl_host_ops;
 
+/**
+ * lkl_printf - print a message via the host print operation
+ *
+ * @fmt - printf like format string
+ */
+int lkl_printf(const char *fmt, ...);
+
 #endif
diff --git a/tools/lkl/lib/utils.c b/tools/lkl/lib/utils.c
new file mode 100644
index 0000000..f8b676f
--- /dev/null
+++ b/tools/lkl/lib/utils.c
@@ -0,0 +1,177 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <lkl_host.h>
+
+static const char * const lkl_err_strings[] = {
+	"Success",
+	"Operation not permitted",
+	"No such file or directory",
+	"No such process",
+	"Interrupted system call",
+	"I/O error",
+	"No such device or address",
+	"Argument list too long",
+	"Exec format error",
+	"Bad file number",
+	"No child processes",
+	"Try again",
+	"Out of memory",
+	"Permission denied",
+	"Bad address",
+	"Block device required",
+	"Device or resource busy",
+	"File exists",
+	"Cross-device link",
+	"No such device",
+	"Not a directory",
+	"Is a directory",
+	"Invalid argument",
+	"File table overflow",
+	"Too many open files",
+	"Not a typewriter",
+	"Text file busy",
+	"File too large",
+	"No space left on device",
+	"Illegal seek",
+	"Read-only file system",
+	"Too many links",
+	"Broken pipe",
+	"Math argument out of domain of func",
+	"Math result not representable",
+	"Resource deadlock would occur",
+	"File name too long",
+	"No record locks available",
+	"Invalid system call number",
+	"Directory not empty",
+	"Too many symbolic links encountered",
+	"Bad error code", /* EWOULDBLOCK is EAGAIN */
+	"No message of desired type",
+	"Identifier removed",
+	"Channel number out of range",
+	"Level 2 not synchronized",
+	"Level 3 halted",
+	"Level 3 reset",
+	"Link number out of range",
+	"Protocol driver not attached",
+	"No CSI structure available",
+	"Level 2 halted",
+	"Invalid exchange",
+	"Invalid request descriptor",
+	"Exchange full",
+	"No anode",
+	"Invalid request code",
+	"Invalid slot",
+	"Bad error code", /* EDEADLOCK is EDEADLK */
+	"Bad font file format",
+	"Device not a stream",
+	"No data available",
+	"Timer expired",
+	"Out of streams resources",
+	"Machine is not on the network",
+	"Package not installed",
+	"Object is remote",
+	"Link has been severed",
+	"Advertise error",
+	"Srmount error",
+	"Communication error on send",
+	"Protocol error",
+	"Multihop attempted",
+	"RFS specific error",
+	"Not a data message",
+	"Value too large for defined data type",
+	"Name not unique on network",
+	"File descriptor in bad state",
+	"Remote address changed",
+	"Can not access a needed shared library",
+	"Accessing a corrupted shared library",
+	".lib section in a.out corrupted",
+	"Attempting to link in too many shared libraries",
+	"Cannot exec a shared library directly",
+	"Illegal byte sequence",
+	"Interrupted system call should be restarted",
+	"Streams pipe error",
+	"Too many users",
+	"Socket operation on non-socket",
+	"Destination address required",
+	"Message too long",
+	"Protocol wrong type for socket",
+	"Protocol not available",
+	"Protocol not supported",
+	"Socket type not supported",
+	"Operation not supported on transport endpoint",
+	"Protocol family not supported",
+	"Address family not supported by protocol",
+	"Address already in use",
+	"Cannot assign requested address",
+	"Network is down",
+	"Network is unreachable",
+	"Network dropped connection because of reset",
+	"Software caused connection abort",
+	"Connection reset by peer",
+	"No buffer space available",
+	"Transport endpoint is already connected",
+	"Transport endpoint is not connected",
+	"Cannot send after transport endpoint shutdown",
+	"Too many references: cannot splice",
+	"Connection timed out",
+	"Connection refused",
+	"Host is down",
+	"No route to host",
+	"Operation already in progress",
+	"Operation now in progress",
+	"Stale file handle",
+	"Structure needs cleaning",
+	"Not a XENIX named type file",
+	"No XENIX semaphores available",
+	"Is a named type file",
+	"Remote I/O error",
+	"Quota exceeded",
+	"No medium found",
+	"Wrong medium type",
+	"Operation Canceled",
+	"Required key not available",
+	"Key has expired",
+	"Key has been revoked",
+	"Key was rejected by service",
+	"Owner died",
+	"State not recoverable",
+	"Operation not possible due to RF-kill",
+	"Memory page has hardware error",
+};
+
+const char *lkl_strerror(int err)
+{
+	if (err < 0)
+		err = -err;
+
+	if (err >= sizeof(lkl_err_strings) / sizeof(const char *))
+		return "Bad error code";
+
+	return lkl_err_strings[err];
+}
+
+int lkl_printf(const char *fmt, ...)
+{
+	char *buffer;
+	va_list args, copy;
+	int n;
+
+	va_start(args, fmt);
+	va_copy(copy, args);
+	n = vsnprintf(NULL, 0, fmt, copy);
+	va_end(copy);
+
+	buffer = lkl_host_ops.mem_alloc(n + 1);
+	if (!buffer) {
+		va_end(args);
+		return 0;
+	}
+	vsnprintf(buffer, n + 1, fmt, args);
+	va_end(args);
+
+	lkl_host_ops.print(buffer, n);
+
+	lkl_host_ops.mem_free(buffer);
+
+	return n;
+}
-- 
2.1.0

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

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


#1261874 — [RFC PATCH 01/28] asm-generic: atomic64: allow using generic atomic64 on 64bit platforms

FromOctavian Purdila <octavian.purdila@intel.com>
Date2015-11-03 21:40 +0100
Subject[RFC PATCH 01/28] asm-generic: atomic64: allow using generic atomic64 on 64bit platforms
Message-ID<qqQx4-7Ef-5@gated-at.bofh.it>
In reply to#1261858
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 include/asm-generic/atomic64.h | 2 ++
 include/linux/atomic.h         | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/asm-generic/atomic64.h b/include/asm-generic/atomic64.h
index d48e78c..d0eb6cd 100644
--- a/include/asm-generic/atomic64.h
+++ b/include/asm-generic/atomic64.h
@@ -12,9 +12,11 @@
 #ifndef _ASM_GENERIC_ATOMIC64_H
 #define _ASM_GENERIC_ATOMIC64_H
 
+#ifndef CONFIG_64BIT
 typedef struct {
 	long long counter;
 } atomic64_t;
+#endif
 
 #define ATOMIC64_INIT(i)	{ (i) }
 
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index 00a5763..81814c8 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -451,10 +451,10 @@ static inline int atomic_dec_if_positive(atomic_t *v)
 }
 #endif
 
-#include <asm-generic/atomic-long.h>
 #ifdef CONFIG_GENERIC_ATOMIC64
 #include <asm-generic/atomic64.h>
 #endif
+#include <asm-generic/atomic-long.h>
 
 #ifndef atomic64_andnot
 static inline void atomic64_andnot(long long i, atomic64_t *v)
-- 
2.1.0

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

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


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | linux.kernel


csiph-web