Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] rump hypcall integration for LKL #255

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions arch/lkl/Kconfig
Original file line number Diff line number Diff line change
@@ -45,6 +45,12 @@ config 64BIT
config BIG_ENDIAN
def_bool n

config KALLSYMS_BASE_RELATIVE
def_bool n

config TTY
def_bool n

config GENERIC_CSUM
def_bool y

@@ -58,6 +64,12 @@ config RWSEM_GENERIC_SPINLOCK
bool
default y

config PCI
bool "PCI support"
select NO_GENERIC_PCI_IOPORT_MAP
select GENERIC_PCI_IOMAP
default y

source init/Kconfig

source net/Kconfig
38 changes: 37 additions & 1 deletion arch/lkl/Makefile
Original file line number Diff line number Diff line change
@@ -14,24 +14,60 @@ else
$(error Unrecognized platform: $(OUTPUT_FORMAT))
endif

ifeq ($(OUTPUT_FORMAT),elf32-littlearm)
CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork -mfpu=vfp
KBUILD_CFLAGS += $(CFLAGS_ABI)
endif

ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64-freebsd))
NPROC=$(shell sysctl -n hw.ncpu)
else
NPROC=$(shell nproc)
endif

LDFLAGS_vmlinux += -r

ifeq ($(buildrump),yes)
# objcopy trick is taken from rumpkernel
GCCSYMBOLS=__umoddi3|__udivdi3|__aeabi_idiv|__aeabi_idivmod|__aeabi_llsl
GCCSYMBOLS:=$(GCCSYMBOLS)|__aeabi_llsr|__aeabi_uidiv|__aeabi_uidivmod|__aeabi_uldivmod
GCCATOMIC=__sync_synchronize|__sync_fetch_and_sub_4|__sync_fetch_and_add_4
GCCATOMIC:=$(GCCATOMIC)|__sync_fetch_and_and_4|__sync_fetch_and_or_4
VMLINUX_SYMS=__start___ex_table|__stop___ex_table|boot_cmdline
EXP_SYMRENAME=rump|RUMP|bmk_|lib_|nuse_|lkl_|__tls|__initcall_start
EXP_SYMRENAME:=$(EXP_SYMRENAME)|__initcall_end|__gcov|_end|_GLOBAL_OFFSET_TABLE|__assert13
EXP_SYMRENAME:=$(EXP_SYMRENAME)|${GCCSYMBOLS}|${GCCATOMIC}'${_SYMQUIRK}'
EXP_SYMRENAME:=$(EXP_SYMRENAME)${RUMP_SYM_NORENAME:D|${RUMP_SYM_NORENAME}}|${VMLINUX_SYMS}

define make_ns_symbols
${Q}echo " OBJCPY " $1 $2; \
${NM} -go $1 | awk ' \
$$NF!~/^'${_PQ}'(${EXP_SYMRENAME})/ \
{s=$$NF;sub(/^'${_PQ}'/, "&rumpns_", s); print $$NF, s}'\
| sort | uniq > $2.renametab; \
$(OBJCOPY) -R .eh_frame -L __start___ex_table \
-L __stop___ex_table --preserve-dates \
--redefine-syms $2.renametab $1 $2; \
rm -f $2.renametab
endef
else
LKL_ENTRY_POINTS := lkl_start_kernel lkl_sys_halt lkl_syscall lkl_trigger_irq \
lkl_get_free_irq lkl_put_irq lkl_create_syscall_thread \
lkl_stop_syscall_thread lkl_is_running
define make_ns_symbols
$(OBJCOPY) -R .eh_frame -R .syscall_defs $(foreach sym,$(LKL_ENTRY_POINTS),\
-G$(prefix)$(sym)) vmlinux lkl.o
endef
endif

core-y += arch/lkl/kernel/
core-y += arch/lkl/mm/
core-y += arch/lkl/drivers/

all: lkl.o

lkl.o: vmlinux
$(OBJCOPY) -R .eh_frame -R .syscall_defs $(foreach sym,$(LKL_ENTRY_POINTS),-G$(prefix)$(sym)) vmlinux lkl.o
$(call make_ns_symbols,vmlinux,lkl.o)

arch/lkl/include/generated/uapi/asm/syscall_defs.h: vmlinux
$(OBJCOPY) -j .syscall_defs -O binary --set-section-flags .syscall_defs=alloc $< $@
9 changes: 7 additions & 2 deletions arch/lkl/defconfig
Original file line number Diff line number Diff line change
@@ -31,8 +31,9 @@ CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_XFS_FS=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_BTRFS_FS=y
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_ISO9660_FS=y
#CONFIG_BTRFS_FS=y
#CONFIG_BTRFS_FS_POSIX_ACL=y
# CONFIG_FILE_LOCKING is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
@@ -93,3 +94,7 @@ CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_REDUCED=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_PCI=y
CONFIG_NET_CORE=y
CONFIG_VIRTIO_PCI=y
CONFIG_GENERIC_IOMAP=y
13 changes: 13 additions & 0 deletions arch/lkl/drivers/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

obj-y = rumpdev_pci.o

# need to build with
librumpdev_linux_pci.a: ${RUMP_BMK_PCI_HYPERCALLS}
rm -f $@
$(AR) rc $@ ${RUMP_BMK_PCI_HYPERCALLS}

install: librumpdev_linux_pci.a
install -D librumpdev_linux_pci.a ${DESTDIR}/lib/


.PHONY: ${RUMP_BMK_PCI_HYPERCALLS}
43 changes: 43 additions & 0 deletions arch/lkl/drivers/pci_user.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* Reused from src-netbsd/sys/rump/dev/lib/libpci/pci_user.h */
/*
* Possible userfeature macro flags:
*
* RUMPCOMP_USERFEATURE_PCI_DMAFREE:
* Support free'ing DMA memory. If not, panic() when free() is called.
*
* RUMPCOMP_USERFEATURE_PCI_IOSPACE
* Support for PCI I/O space. If yes, rumpcomp_pci_iospace_init()
* must be provided.
*/


void *rumpcomp_pci_map(unsigned long addr, unsigned long len);
int rumpcomp_pci_confread(unsigned int bus, unsigned int dev,
unsigned int fun, int reg, unsigned int *value);
int rumpcomp_pci_confwrite(unsigned int bus, unsigned int dev,
unsigned int fun, int reg, unsigned int value);
int rumpcomp_pci_irq_map(unsigned int bus, unsigned int device,
unsigned int fun, int intrline, unsigned int cookie);
void *rumpcomp_pci_irq_establish(unsigned int cookie,
int (*handler)(void *), void *data);

/* XXX: needs work: support boundary-restricted allocations */
int rumpcomp_pci_dmalloc(size_t size, size_t align,
unsigned long *pap, unsigned long *vap);
#ifdef RUMPCOMP_USERFEATURE_PCI_DMAFREE
void rumpcomp_pci_dmafree(unsigned long mem, size_t size);
#endif

struct rumpcomp_pci_dmaseg {
unsigned long ds_pa;
unsigned long ds_len;
unsigned long ds_vacookie;
};
int rumpcomp_pci_dmamem_map(struct rumpcomp_pci_dmaseg *dss, size_t nseg,
size_t totlen, void **vap);

unsigned long rumpcomp_pci_virt_to_mach(void *virt);

#ifdef RUMPCOMP_USERFEATURE_PCI_IOSPACE
int rumpcomp_pci_iospace_init(void);
#endif
263 changes: 263 additions & 0 deletions arch/lkl/drivers/rumpdev_pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
/*
* rumprun PCI access (reused from src-netbsd/.../rumpdev_pci.c)
*/

/*
* Copyright (c) 2013 Antti Kantee. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/io.h>
#include <asm/host_ops.h>

#include "pci_user.h"

struct rump_pci_sysdata {
int domain; /* PCI domain */
};

/* stubs: should not called */
int __weak rumpcomp_pci_confread(unsigned int bus, unsigned int dev,
unsigned int fun,
int reg, unsigned int *value)
{
return 0;
}

int __weak rumpcomp_pci_confwrite(unsigned int bus, unsigned int dev,
unsigned int fun,
int reg, unsigned int value)
{
return 0;
}

void * __weak rumpcomp_pci_map(unsigned long addr, unsigned long len)
{
return NULL;
}

int __weak rumpcomp_pci_irq_map(unsigned int bus, unsigned int device,
unsigned int fun,
int intrline, unsigned int cookie)
{
return 0;
}

void * __weak rumpcomp_pci_irq_establish(unsigned int cookie,
int (*handler)(void *), void *data)
{
return NULL;
}

void __iomem *__pci_ioport_map(struct pci_dev *dev,
unsigned long port, unsigned int nr)
{
/* XXX: no care at the moment */
return rumpcomp_pci_map(port, nr);
}

/* from arch/x86/pci/common.c */
void pcibios_fixup_bus(struct pci_bus *b)
{
pci_read_bridge_bases(b);
}

/* from arch/x86/pci/i386.c */
resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return 0;
}

/* from drivers/pci/access.c
*
* @bus: PCI bus to scan
* @devfn: slot number to scan (must have zero function.)
*/
void *rump_pci_map_bus(struct pci_bus *bus, unsigned int devfn, int where)
{
unsigned long addr;

addr = (1 << 31) | (bus->number << 16) | (PCI_SLOT(devfn) << 11) |
(PCI_FUNC(devfn) << 8) | (where & 0xfc);

/* FIXME: length? */
return rumpcomp_pci_map(addr, 0);
}

int rump_pci_generic_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{

rumpcomp_pci_confread(bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn), where, val);
if (size <= 2)
*val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);

return PCIBIOS_SUCCESSFUL;
}

int rump_pci_generic_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
u32 mask, tmp;

if (size == 4) {
rumpcomp_pci_confwrite(bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn), where, val);
return PCIBIOS_SUCCESSFUL;
}

mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));

/* This brings the way much overhead though I picked this
* code from access.c.. maybe should come up with single
* write method to avoid that.
*/

rumpcomp_pci_confread(bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn), where, &tmp);
tmp &= mask;
tmp |= val << ((where & 0x3) * 8);

rumpcomp_pci_confwrite(bus->number, PCI_SLOT(devfn),
PCI_FUNC(devfn), where, tmp);

return PCIBIOS_SUCCESSFUL;
}


#ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>

void *
pciide_machdep_compat_intr_establish(device_t dev,
const struct pci_attach_args *pa, int chan,
int (*func)(void *), void *arg)
{
pci_intr_handle_t ih;
struct pci_attach_args mypa = *pa;

mypa.pa_intrline = PCIIDE_COMPAT_IRQ(chan);
if (pci_intr_map(&mypa, &ih) != 0)
return NULL;
return rumpcomp_pci_irq_establish(ih, func, arg);
}

__strong_alias(pciide_machdep_compat_intr_disestablish, pci_intr_disestablish);
#endif /* __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH */


/* from drivers/pci/xen-pcifront.c */
static int pci_lib_claim_resource(struct pci_dev *dev, void *data)
{
int i;
struct resource *r;

for (i = 0; i < PCI_NUM_RESOURCES; i++) {
r = &dev->resource[i];

if (!r->parent && r->start && r->flags) {
dev_info(&dev->dev, "claiming resource %s/%d\n",
pci_name(dev), i);
if (pci_claim_resource(dev, i)) {
dev_err(&dev->dev,
"Could not claim resource %s/%d!",
pci_name(dev), i);
}
}
}

return 0;
}

static int rump_trigger_irq(void *arg)
{
struct irq_data *data = arg;

lkl_trigger_irq(data->irq);
return 0;
}

int rump_pci_irq_request(struct irq_data *data)
{
int ret, int_irq;
struct irq_desc *desc = irq_to_desc(data->irq);
const char *name = desc->name ? desc->name : "null"; /* XXX */

static int intr[5] = {9, 10, 11, 14, 15};
static int intnum;

/* setup IRQ */
int_irq = lkl_get_free_irq(name);

ret = rumpcomp_pci_irq_map(0, 0, 0, intr[intnum++], int_irq);
rumpcomp_pci_irq_establish(int_irq, rump_trigger_irq, data);

return 0;
}

void rump_pci_irq_release(struct irq_data *data)
{
/* XXX: NOP */
}

struct pci_ops rump_pci_root_ops = {
.map_bus = rump_pci_map_bus,
.read = rump_pci_generic_read,
.write = rump_pci_generic_write,
};


static int __init rump_pci_init(void)
{
struct pci_bus *bus;
struct rump_pci_sysdata *sd;
int busnum = 0;

sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd)
return -1;

pr_info("PCI: root bus %02x: using default resources\n", busnum);
bus = pci_scan_bus(busnum, &rump_pci_root_ops, sd);
if (!bus) {
kfree(sd);
return -1;
}
pci_walk_bus(bus, pci_lib_claim_resource, NULL);
pci_bus_add_devices(bus);

return 0;
}
subsys_initcall(rump_pci_init);
7 changes: 3 additions & 4 deletions arch/lkl/include/asm/Kbuild
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@ generic-y += current.h
generic-y += delay.h
generic-y += device.h
generic-y += div64.h
generic-y += dma.h
generic-y += emergency-restart.h
generic-y += errno.h
generic-y += exec.h
@@ -39,7 +38,7 @@ generic-y += msgbuf.h
generic-y += page.h
generic-y += param.h
generic-y += parport.h
generic-y += pci.h
generic-y += pci_iomap.h
generic-y += percpu.h
generic-y += pgalloc.h
generic-y += poll.h
@@ -53,7 +52,6 @@ generic-y += segment.h
generic-y += sembuf.h
generic-y += serial.h
generic-y += shmbuf.h
generic-y += signal.h
generic-y += simd.h
generic-y += sizes.h
generic-y += socket.h
@@ -71,6 +69,7 @@ generic-y += tlb.h
generic-y += tlbflush.h
generic-y += topology.h
generic-y += trace_clock.h
generic-y += uaccess.h
generic-y += unaligned.h
generic-y += vga.h
generic-y += word-at-a-time.h
header-y += syscalls.h
12 changes: 12 additions & 0 deletions arch/lkl/include/asm/dma.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef _ASM_LKL_DMA_H
#define _ASM_LKL_DMA_H

#include <asm-generic/dma.h>

#ifdef CONFIG_PCI
extern int isa_dma_bridge_buggy;
#else
#define isa_dma_bridge_buggy (0)
#endif

#endif /* _ASM_LKL_DMA_H */
10 changes: 10 additions & 0 deletions arch/lkl/include/asm/pci.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _ASM_LKL_PCI_H
#define _ASM_LKL_PCI_H

#include <asm-generic/pci.h>

# define pcibios_assign_all_busses() 0
#define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000

#endif /* _ASM_LKL_PCI_H */
3 changes: 3 additions & 0 deletions arch/lkl/include/asm/signal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
void do_signal(struct pt_regs *regs);

#include <asm-generic/signal.h>
1 change: 1 addition & 0 deletions arch/lkl/include/asm/thread_info.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ struct thread_info {
bool dead;
lkl_thread_t tid;
struct task_struct *prev_sched;
void *rump_client; /* for syscall proxy */
unsigned long stackend;
};

70 changes: 70 additions & 0 deletions arch/lkl/include/asm/uaccess.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#ifndef _ASM_LKL_UACCESS_H
#define _ASM_LKL_UACCESS_H

#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/irqflags.h>
#include <linux/string.h>
#include <asm/errno.h>
#include <asm/thread_info.h>

#ifdef ENABLE_SYSPROXY
#include <rump/rumpuser.h>
#endif

#define __access_ok(addr, size) (1)

/* handle rump remote client */
static inline __must_check long __copy_from_user(void *to,
const void __user *from, unsigned long n)
{
int error = 0;
struct thread_info *ti;

ti = current_thread_info();

if (unlikely(from == NULL && n))
return -EFAULT;

if (!ti->rump_client) {
memcpy(to, from, n);
} else if (n) {
#ifdef ENABLE_SYSPROXY
error = rumpuser_sp_copyin(ti->rump_client, from, to, n);
#else
;
#endif
}

return error;
}
#define __copy_from_user(to, from, n) __copy_from_user(to, from, n)

static inline __must_check long __copy_to_user(void __user *to,
const void *from, unsigned long n)
{
int error = 0;
struct thread_info *ti;

ti = current_thread_info();

if (unlikely(to == NULL && n))
return -EFAULT;

if (!ti->rump_client) {
memcpy(to, from, n);
} else if (n) {
#ifdef ENABLE_SYSPROXY
error = rumpuser_sp_copyout(ti->rump_client, from, to, n);
#else
;
#endif
}

return error;
}
#define __copy_to_user(to, from, n) __copy_to_user(to, from, n)

#include <asm-generic/uaccess.h>

#endif /* _ASM_LKL_UACCESS_H */
15 changes: 15 additions & 0 deletions arch/lkl/include/uapi/asm/host_ops.h
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
struct lkl_mutex;
struct lkl_sem;
struct lkl_tls_key;
struct irq_data;
typedef unsigned long lkl_thread_t;
struct lkl_jmp_buf {
unsigned long buf[32];
@@ -123,6 +124,11 @@ struct lkl_host_operations {
int (*iomem_access)(const volatile void *addr, void *val, int size,
int write);

int (*irq_request)(struct irq_data *data);
void (*irq_release)(struct irq_data *data);

int (*getparam)(const char *name, void *buf, int buflen);

long (*gettid)(void);

void (*jmp_buf_set)(struct lkl_jmp_buf *jmpb, void (*f)(void));
@@ -149,4 +155,13 @@ int lkl_is_running(void);
int lkl_printf(const char *, ...);
void lkl_bug(const char *, ...);

/* atomic ops */
int lkl__sync_fetch_and_sub(int *ptr, int value);
int lkl__sync_fetch_and_add(int *ptr, int value);
long lkl__sync_fetch_and_or(long *ptr, long value);
long lkl__sync_fetch_and_and(long *ptr, long value);
void lkl__sync_synchronize(void);
void atomic_ops_init(void);
void atomic_ops_cleanup(void);

#endif
2 changes: 1 addition & 1 deletion arch/lkl/kernel/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
extra-y := vmlinux.lds

obj-y = setup.o threads.o irq.o time.o syscalls.o misc.o console.o \
syscalls_32.o cpu.o
syscalls_32.o cpu.o atomic.o signal.o
97 changes: 97 additions & 0 deletions arch/lkl/kernel/atomic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/host_ops.h>

#if defined(__ARMEL__)
static void *atomic_lock;

long lkl__sync_fetch_and_or(long *ptr, long value)
{
lkl_ops->sem_down(atomic_lock);
*ptr = value;
lkl_ops->sem_up(atomic_lock);
return 0;
}

long lkl__sync_fetch_and_and(long *ptr, long value)
{
int tmp;

lkl_ops->sem_down(atomic_lock);
tmp = *ptr;
*ptr *= value;
lkl_ops->sem_up(atomic_lock);
return tmp;
}

int lkl__sync_fetch_and_add(int *ptr, int value)
{
int tmp;

lkl_ops->sem_down(atomic_lock);
tmp = *ptr;
*ptr += value;
lkl_ops->sem_up(atomic_lock);
return tmp;
}

int lkl__sync_fetch_and_sub(int *ptr, int value)
{
int tmp;

lkl_ops->sem_down(atomic_lock);
tmp = *ptr;
*ptr -= value;
lkl_ops->sem_up(atomic_lock);
return tmp;
}

void lkl__sync_synchronize(void)
{
}

void atomic_ops_init(void)
{
atomic_lock = lkl_ops->sem_alloc(1);
}

void atomic_ops_cleanup(void)
{
lkl_ops->sem_free(atomic_lock);
}

#else
long lkl__sync_fetch_and_or(long *ptr, long value)
{
return __sync_fetch_and_or(ptr, value);
}

long lkl__sync_fetch_and_and(long *ptr, long value)
{
return __sync_fetch_and_and(ptr, value);
}

int lkl__sync_fetch_and_add(int *ptr, int value)
{
return __sync_fetch_and_add(ptr, value);
}

int lkl__sync_fetch_and_sub(int *ptr, int value)
{
return __sync_fetch_and_sub(ptr, value);
}

void lkl__sync_synchronize(void)
{
return __sync_synchronize();
}

void atomic_ops_init(void)
{
}

void atomic_ops_cleanup(void)
{
}
#endif

87 changes: 86 additions & 1 deletion arch/lkl/kernel/console.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/console.h>
#include <asm/host_ops.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/major.h>

static void console_write(struct console *con, const char *str, unsigned len)
{
static char buf[256];
static int verbose;

/* when console isn't NULL (not called from file_write() */
if (con && !verbose) {
if (!lkl_ops->getparam)
verbose = 1;
else if (lkl_ops->getparam("RUMP_VERBOSE", buf, sizeof(buf))
== 0)
if (*buf != 0)
verbose = 1;
}

if (con && !verbose)
return;

if (lkl_ops->print)
lkl_ops->print(str, len);
}
@@ -39,3 +60,67 @@ int __init lkl_console_init(void)
}
core_initcall(lkl_console_init);

static ssize_t file_write(struct file *fp, const char __user *s,
size_t n, loff_t *off)
{
console_write(NULL, s, n);
return n;
}

static ssize_t file_read(struct file *file, char __user *buf, size_t size,
loff_t *ppos)
{
int err = 0;
#ifdef TO_BE_IMPLEMENTED
/* need to use iovread in host_ops (not directly from rump hypercall) */
struct rumpuser_iovec iov;
ssize_t ret;

iov.iov_base = buf;
iov.iov_len = size;

err = rumpuser_iovread(0, &iov, 1, 0, &ret);
if (err == 0)
return ret;

#endif
return -err;
}

static const struct file_operations lkl_stdio_fops = {
.owner = THIS_MODULE,
.write = file_write,
.read = file_read,
};

static int __init lkl_stdio_init(void)
{
int err;

/* prepare /dev/console */
err = register_chrdev(TTYAUX_MAJOR, "console", &lkl_stdio_fops);
if (err < 0) {
pr_err("can't register lkl stdio console.\n");
return err;
}

return 0;
}
/* should be _before_ default_rootfs creation (noinitramfs.c) */
fs_initcall(lkl_stdio_init);

static int __init lkl_memdev_init(void)
{
int err;

/* prepare /dev/null */
err = sys_mknod((const char __user __force *) "/dev/null",
S_IFCHR | 0600, new_encode_dev(MKDEV(MEM_MAJOR, 3)));
if (err < 0) {
pr_err("can't register /dev/null.\n");
return err;
}

return 0;
}
device_initcall(lkl_memdev_init);
8 changes: 4 additions & 4 deletions arch/lkl/kernel/cpu.c
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ static int __cpu_try_get_lock(int n)
{
lkl_thread_t self;

if (__sync_fetch_and_add(&cpu.shutdown_gate, n) >= MAX_THREADS)
if (lkl__sync_fetch_and_add(&cpu.shutdown_gate, n) >= MAX_THREADS)
return -2;

lkl_ops->mutex_lock(cpu.lock);
@@ -89,7 +89,7 @@ static void __cpu_try_get_unlock(int lock_ret, int n)
{
if (lock_ret >= -1)
lkl_ops->mutex_unlock(cpu.lock);
__sync_fetch_and_sub(&cpu.shutdown_gate, n);
lkl__sync_fetch_and_sub(&cpu.shutdown_gate, n);
}

void lkl_cpu_change_owner(lkl_thread_t owner)
@@ -173,7 +173,7 @@ int lkl_cpu_try_run_irq(int irq)

void lkl_cpu_shutdown(void)
{
__sync_fetch_and_add(&cpu.shutdown_gate, MAX_THREADS);
lkl__sync_fetch_and_add(&cpu.shutdown_gate, MAX_THREADS);
}

void lkl_cpu_wait_shutdown(void)
@@ -184,7 +184,7 @@ void lkl_cpu_wait_shutdown(void)

static void lkl_cpu_cleanup(bool shutdown)
{
while (__sync_fetch_and_add(&cpu.shutdown_gate, 0) > MAX_THREADS)
while (lkl__sync_fetch_and_add(&cpu.shutdown_gate, 0) > MAX_THREADS)
;

if (shutdown)
47 changes: 42 additions & 5 deletions arch/lkl/kernel/irq.c
Original file line number Diff line number Diff line change
@@ -27,23 +27,23 @@ static inline unsigned long test_and_clear_irq_index_status(void)
{
if (!irq_index_status)
return 0;
return __sync_fetch_and_and(&irq_index_status, 0);
return lkl__sync_fetch_and_and(&irq_index_status, 0);
}

static inline unsigned long test_and_clear_irq_status(int index)
{
if (!&irq_status[index])
return 0;
return __sync_fetch_and_and(&irq_status[index], 0);
return lkl__sync_fetch_and_and(&irq_status[index], 0);
}

void set_irq_pending(int irq)
{
int index = irq / IRQ_STATUS_BITS;
int bit = irq % IRQ_STATUS_BITS;

__sync_fetch_and_or(&irq_status[index], BIT(bit));
__sync_fetch_and_or(&irq_index_status, BIT(index));
lkl__sync_fetch_and_or(&irq_status[index], BIT(bit));
lkl__sync_fetch_and_or(&irq_index_status, BIT(index));
}

static struct irq_info {
@@ -174,12 +174,49 @@ void arch_local_irq_restore(unsigned long flags)
irqs_enabled = flags;
}

static int lkl_irq_request_resource(struct irq_data *data)
{
if (!lkl_ops->irq_request)
return 0;

return lkl_ops->irq_request(data);
}

static void lkl_irq_release_resource(struct irq_data *data)
{
if (!lkl_ops->irq_release)
return;

return lkl_ops->irq_release(data);
}

static void noop(struct irq_data *data) { }
static unsigned int noop_ret(struct irq_data *data)
{
return 0;
}

struct irq_chip dummy_lkl_irq_chip = {
.name = "lkl_dummy",
.irq_startup = noop_ret,
.irq_shutdown = noop,
.irq_enable = noop,
.irq_disable = noop,
.irq_ack = noop,
.irq_mask = noop,
.irq_unmask = noop,
.irq_request_resources = lkl_irq_request_resource,
.irq_release_resources = lkl_irq_release_resource,
.flags = IRQCHIP_SKIP_SET_WAKE,
};

void init_IRQ(void)
{
int i;

for (i = 0; i < NR_IRQS; i++)
irq_set_chip_and_handler(i, &dummy_irq_chip, handle_simple_irq);
irq_set_chip_and_handler(i, &dummy_lkl_irq_chip,
handle_simple_irq);

pr_info("lkl: irqs initialized\n");
}
2 changes: 2 additions & 0 deletions arch/lkl/kernel/setup.c
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ void __init setup_arch(char **cl)

static void __init lkl_run_kernel(void *arg)
{
atomic_ops_init();
threads_init();
lkl_cpu_get();
start_kernel();
@@ -132,6 +133,7 @@ long lkl_sys_halt(void)

syscalls_cleanup();
threads_cleanup();
atomic_ops_cleanup();
/* Shutdown the clockevents source. */
tick_suspend_local();
free_mem();
16 changes: 16 additions & 0 deletions arch/lkl/kernel/signal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <linux/sched.h>

static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
ksig->ka.sa.sa_handler(ksig->sig);
}

void do_signal(struct pt_regs *regs)
{
struct ksignal ksig;

while (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
handle_signal(&ksig, regs);
}
}
2 changes: 2 additions & 0 deletions arch/lkl/kernel/syscalls.c
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#include <asm/syscalls_32.h>
#include <asm/cpu.h>
#include <asm/sched.h>
#include <asm/signal.h>

static asmlinkage long sys_virtio_mmio_device_add(long base, long size,
unsigned int irq);
@@ -44,6 +45,7 @@ static long run_syscall(long no, long *params)
params[4], params[5]);

task_work_run();
do_signal(NULL);

return ret;
}
12 changes: 9 additions & 3 deletions drivers/base/dd.c
Original file line number Diff line number Diff line change
@@ -51,6 +51,7 @@
static DEFINE_MUTEX(deferred_probe_mutex);
static LIST_HEAD(deferred_probe_pending_list);
static LIST_HEAD(deferred_probe_active_list);
static struct workqueue_struct *deferred_wq;
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);

/*
@@ -174,7 +175,7 @@ static void driver_deferred_probe_trigger(void)
* Kick the re-probe thread. It may already be scheduled, but it is
* safe to kick it again.
*/
schedule_work(&deferred_probe_work);
queue_work(deferred_wq, &deferred_probe_work);
}

/**
@@ -210,10 +211,14 @@ void device_unblock_probing(void)
*/
static int deferred_probe_initcall(void)
{
deferred_wq = create_singlethread_workqueue("deferwq");
if (WARN_ON(!deferred_wq))
return -ENOMEM;

driver_deferred_probe_enable = true;
driver_deferred_probe_trigger();
/* Sort as many dependencies as possible before exiting initcalls */
flush_work(&deferred_probe_work);
flush_workqueue(deferred_wq);
return 0;
}
late_initcall(deferred_probe_initcall);
@@ -477,7 +482,8 @@ int driver_probe_done(void)
void wait_for_device_probe(void)
{
/* wait for the deferred probe workqueue to finish */
flush_work(&deferred_probe_work);
if (driver_deferred_probe_enable)
flush_workqueue(deferred_wq);

/* wait for the known devices to complete their probing */
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
54 changes: 42 additions & 12 deletions tools/lkl/Makefile
Original file line number Diff line number Diff line change
@@ -10,6 +10,9 @@ else
Q = @
endif

OUTPUT_FORMAT=$(shell $(LD) -r -print-output-format)
RUMP_PREFIX?=
RUMP_INCLUDE?=$(RUMP_PREFIX)/
# default target
all:

@@ -19,7 +22,7 @@ all:
# cross toolchain does not use prefixed names
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)$(LD)
AR := $(CROSS_COMPILE)$(AR)
AR := $(CROSS_COMPILE)ar
export CC LD AR

EXESUF :=
@@ -37,18 +40,21 @@ export srctree
# Target build configuration

export CFLAGS += -I$(OUTPUT)/include -Iinclude -Wall -g -O2 -Wextra \
-Wno-unused-parameter \
-Wno-missing-field-initializers -fno-strict-aliasing
-Wno-missing-field-initializers -fno-strict-aliasing \
-Wno-unused-parameter -U_FORTIFY_SOURCE -fno-stack-protector

OUTPUT_FORMAT = $(shell $(LD) -r -print-output-format)
OUTPUT_DEF = $(shell echo | $(CC) -dM -E -)

ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64 elf32-i386 elf64-x86-64-freebsd elf32-littlearm))
OUTPUT_DEF = $(shell echo | $(CC) -dM -E -)
CFLAGS += -fPIC -pthread
ifeq (,$(filter $(OUTPUT_DEF),__ANDROID__))
CFLAGS += -fPIC
ifeq (,$(filter $(OUTPUT_DEF),__ANDROID__ __ARMEL__))
CFLAGS += -pthread
LDLIBS += -lrt -lpthread
endif
export CONFIG_AUTO_LKL_POSIX_HOST=y
export CONFIG_AUTO_LKL_VIRTIO=y
export CONFIG_AUTO_LKL_VIRTIO_NET=y
CFLAGS += -DCONFIG_AUTO_LKL_POSIX_HOST

# Intel DPDK configuration
@@ -73,6 +79,8 @@ else ifneq (,$(filter $(OUTPUT_FORMAT),pe-i386))
EXESUF := .exe
SOSUF := .dll
export CONFIG_AUTO_LKL_NT_HOST=y
export CONFIG_AUTO_LKL_VIRTIO=y
export CONFIG_AUTO_LKL_VIRTIO_NET=n
CFLAGS += -DCONFIG_AUTO_LKL_NT_HOST
else
$(error Unrecognized platform: $(OUTPUT_FORMAT))
@@ -113,6 +121,25 @@ ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64-freebsd))
$(OUTPUT)cptofs$(EXESUF): LDLIBS += -largp
endif

# if there is no rumpuser.h, then skip build
ifeq (,$(wildcard $(RUMP_INCLUDE)/rump/rumpuser.h))
else
buildrump=yes
KOPT+="buildrump="$(buildrump)
export CONFIG_AUTO_LKL_RUMP_HOST=y
export CONFIG_AUTO_LKL_POSIX_HOST=n
export CONFIG_AUTO_LKL_VIRTIO=y
export CONFIG_AUTO_LKL_VIRTIO_NET=y
CFLAGS += -I$(RUMP_INCLUDE) -DRUMPUSER -DLIBRUMPUSER -D_KERNEL
CFLAGS += -UCONFIG_AUTO_LKL_POSIX_HOST

# if rumprun=yes, then skip virtio-host build
ifeq ($(rumprun),yes)
CFLAGS += -DRUMPRUN
export CONFIG_AUTO_LKL_VIRTIO=n
export CONFIG_AUTO_LKL_VIRTIO_NET=n
endif
endif

TEST_TARGETS := test valgrind gdb

@@ -147,12 +174,18 @@ $(OUTPUT)cpfromfs$(EXESUF): cptofs$(EXESUF)
# arm-android neither for the moment
ifneq (,$(filter $(OUTPUT_FORMAT),pe-i386))
all: $(filter-out $(OUTPUT)liblkl-hijack$(SOSUF), $(ALL_LIBRARIES))
else ifneq (,$(filter $(OUTPUT_DEF),__ANDROID__))
install: headers_install libraries_install programs_install
else ifneq (,$(wildcard $(RUMP_INCLUDE)/rump/rumpuser.h))
ALL_LIBRARIES := $(filter-out $(OUTPUT)liblkl-hijack$(SOSUF), $(ALL_LIBRARIES))
all: $(ALL_LIBRARIES)
install: headers_install libraries_install
else ifneq (,$(filter $(OUTPUT_DEF),__ANDROID__ __ARMEL__))
all: $(filter-out $(OUTPUT)liblkl-hijack$(SOSUF), $(ALL_LIBRARIES))
else ifneq (,$(filter $(OUTPUT_FORMAT),elf32-littlearm))
all: $(filter-out $(OUTPUT)liblkl-hijack$(SOSUF), $(ALL_LIBRARIES)) $(ALL_PROGRAMS)
install: headers_install libraries_install programs_install
else
ALL_LIBRARIES := $(ALL_LIBRARIES) $(OUTPUT)liblkl-hijack$(SOSUF)
all: $(ALL_PROGRAMS) $(ALL_LIBRARIES)
install: headers_install libraries_install programs_install
endif

clean:
@@ -184,9 +217,6 @@ programs_install: $(ALL_PROGRAMS)
install -d $(DESTDIR)$(PREFIX)/bin ; \
install -m 755 $(ALL_PROGRAMS) $(DESTDIR)$(PREFIX)/bin

install: headers_install libraries_install programs_install


FORCE: ;
.PHONY: all clean $(TEST_TARGETS) FORCE
.PHONY: headers_install libraries_install programs_install install
17 changes: 12 additions & 5 deletions tools/lkl/lib/Build
Original file line number Diff line number Diff line change
@@ -8,15 +8,22 @@ lkl-y += net.o
lkl-y += jmp_buf.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += posix-host.o
lkl-$(CONFIG_AUTO_LKL_NT_HOST) += nt-host.o
lkl-$(CONFIG_AUTO_LKL_RUMP_HOST) += rump.o
lkl-$(CONFIG_AUTO_LKL_RUMP_HOST) += rump-host.o
lkl-y += utils.o
lkl-y += virtio_blk.o
lkl-y += virtio.o
lkl-y += dbg.o
lkl-y += dbg_handler.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net.o
lkl-$(CONFIG_AUTO_LKL_VIRTIO) += virtio_blk.o
lkl-$(CONFIG_AUTO_LKL_VIRTIO) += virtio.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += dbg.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += dbg_handler.o
lkl-$(CONFIG_AUTO_LKL_VIRTIO_NET) += virtio_net.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_fd.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_tap.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_raw.o
lkl-$(CONFIG_AUTO_LKL_POSIX_HOST) += virtio_net_macvtap.o
lkl-$(CONFIG_AUTO_LKL_VIRTIO_NET_DPDK) += virtio_net_dpdk.o
lkl-$(CONFIG_AUTO_LKL_VIRTIO_NET_VDE) += virtio_net_vde.o

# for frankenlibc
CFLAGS_rump-host.o = -I$(RUMP_PREFIX)/../platform/include \
-I$(RUMP_PREFIX)/../franken/include \
-DCONFIG_AUTO_LKL_POSIX_HOST
10 changes: 10 additions & 0 deletions tools/lkl/lib/endian.h
Original file line number Diff line number Diff line change
@@ -3,6 +3,16 @@

#if defined(__FreeBSD__)
#include <sys/endian.h>
#elif defined(__ARMEL__)
#include <machine/endian.h>
#define le16toh(x) (x)
#define le32toh(x) (x)
#define le64toh(x) (x)
#define htole16(x) htons(x)
#define htole32(x) htonl(x)
#define htobe16(x) htons(x)
#define htobe32(x) htonl(x)
#define be32toh(x) ntohl(x)
#elif defined(__ANDROID__)
#include <sys/endian.h>
#define le16toh(x) letoh16(x)
12 changes: 10 additions & 2 deletions tools/lkl/lib/fs.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <lkl_host.h>

#include "virtio.h"

#ifdef RUMPUSER
#include "rump.h"
#endif

#define MAX_FSTYPE_LEN 50
int lkl_mount_fs(char *fstype)
{
@@ -74,6 +76,12 @@ static int get_node_with_prefix(const char *path, const char *prefix,
return ret;
}

/* rumprun doesn't build virtio.o (of lkl) so stub it */
uint32_t __attribute__((weak)) virtio_get_num_bootdevs(void)
{
return 0;
}

static int encode_dev_from_sysfs(const char *sysfs_path, uint32_t *pdevid)
{
int ret;
85 changes: 85 additions & 0 deletions tools/lkl/lib/iomem.c
Original file line number Diff line number Diff line change
@@ -55,6 +55,9 @@ void unregister_iomem(void *base)

void *lkl_ioremap(long addr, int size)
{
#ifdef RUMPRUN
return (void *)addr;
#else
int index = IOMEM_ADDR_TO_INDEX(addr);
struct iomem_region *iomem = &iomem_regions[index];

@@ -65,10 +68,91 @@ void *lkl_ioremap(long addr, int size)
return IOMEM_INDEX_TO_ADDR(index);

return NULL;
#endif
}

int lkl_iomem_access(const volatile void *addr, void *res, int size, int write)
{
/* FIXME: should be transparent with platform/ */
#ifdef RUMPRUN
uint16_t mem = (unsigned long)addr;
int ret = 0;

if (write) {
if (size == 1) {
#ifdef __x86_64__
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this means that x86-32 is not supported?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LKL does not support x86-32, yet #341

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a messy part of lots of ifdefs and a result of what i personally tried. this can be expanded a platform which is currently not supported (e.g., x86-32).

uint8_t v = *(uint8_t *)res;

asm volatile("outb %0, %1" :: "a"(v), "d"(mem));
#elif __arm__
#endif
return 0;
} else if (size == 2) {
#ifdef __x86_64__
uint16_t v = *(uint16_t *)res;

asm volatile("out %0, %1" :: "a"(v), "d"(mem));
#elif __arm__
#endif
return 0;
} else if (size == 4) {
#ifdef __x86_64__
uint32_t v = *(uint32_t *)res;

asm volatile("outl %0, %1" :: "a"(v), "d"(mem));
#elif __arm__
#endif
return 0;
} else if (size == 8) {
#ifdef __x86_64__
lkl_printf("not implemented yet\n");
lkl_host_ops.panic();
#elif __arm__
#endif
} else {
lkl_printf("not implemented yet\n");
lkl_host_ops.panic();
}
} else {
if (size == 1) {
#ifdef __x86_64__
uint8_t v;

asm volatile("inb %1,%0" : "=a"(v) : "d"(mem));
*(uint8_t *)res = v;
#elif __arm__
#endif
return 0;
} else if (size == 2) {
#ifdef __x86_64__
uint16_t v;

asm volatile("in %1,%0" : "=a"(v) : "d"(mem));
*(uint16_t *)res = v;
#elif __arm__
#endif
return 0;
} else if (size == 4) {
#ifdef __x86_64__
uint32_t v;

asm volatile("inl %1,%0" : "=a"(v) : "d"(mem));
*(uint32_t *)res = v;
#elif __arm__
#endif
return 0;
} else if (size == 8) {
#ifdef __x86_64__
lkl_printf("not implemented yet\n");
lkl_host_ops.panic();
#elif __arm__
#endif
} else {
lkl_printf("not implemented yet\n");
lkl_host_ops.panic();
}
}
#else /* !RUMPRUN */
int index = IOMEM_ADDR_TO_INDEX(addr);
struct iomem_region *iomem = &iomem_regions[index];
int offset = IOMEM_ADDR_TO_OFFSET(addr);
@@ -83,5 +167,6 @@ int lkl_iomem_access(const volatile void *addr, void *res, int size, int write)
else
ret = iomem->ops->read(iomem->data, offset, res, size);

#endif
return ret;
}
6 changes: 5 additions & 1 deletion tools/lkl/lib/net.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#include <string.h>
#include <stdio.h>
#include <string.h>
#include "endian.h"
#include <lkl_host.h>

#ifdef RUMPUSER
#include "rump.h"
#endif

static inline void set_sockaddr(struct lkl_sockaddr_in *sin, unsigned int addr,
unsigned short port)
{
672 changes: 672 additions & 0 deletions tools/lkl/lib/rump-host.c

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions tools/lkl/lib/rump-sysproxy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Rump system call proxy interface for Linux
* Copyright (c) 2015 Hajime Tazaki
*
* Author: Hajime Tazaki <thehajime@gmail.com>
*/

#include <linux/stddef.h>
#include <linux/types.h>
#include <generated/utsrelease.h>

#ifdef ENABLE_SYSPROXY
#include "rump.h"

int rump_init_server(const char *url)
{
return rumpuser_sp_init(url, "Linux", UTS_RELEASE, "libos");
}

void rump_sysproxy_init(void)
{
rump_init_server("unix:///tmp/rump-server");
}

void rump_sysproxy_fini(void)
{
rumpuser_sp_fini(NULL);
}
#endif
234 changes: 234 additions & 0 deletions tools/lkl/lib/rump.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* Rump hypercall interface for Linux
* Copyright (c) 2015 Hajime Tazaki
*
* Author: Hajime Tazaki <thehajime@gmail.com>
*/

#include <stdint.h>
#include <sys/types.h>

#include "rump.h"

#include <lkl.h>
#include <lkl_host.h>

static struct lwp *rump_lkl_lwproc_curlwp(void);
static int rump_lkl_lwproc_newlwp(pid_t pid);
static void rump_lkl_lwproc_switch(struct lwp *newlwp);
static void rump_lkl_lwproc_release(void);
static int rump_lkl_lwproc_rfork(void *priv, int flags, const char *comm);

void
rump_schedule(void)
{
}

void
rump_unschedule(void)
{
}

int
rump_daemonize_begin(void)
{
return 0;
}

int
rump_daemonize_done(int error)
{
return 0;
}


int
rump_pub_lwproc_rfork(int arg1)
{
int rv = 0;

rump_schedule();
// rv = rump_lkl_lwproc_rfork(arg1);
rump_unschedule();

return rv;
}

int
rump_pub_lwproc_newlwp(pid_t arg1)
{
int rv;

rump_schedule();
rv = rump_lkl_lwproc_newlwp(arg1);
rump_unschedule();

return rv;
}

void
rump_pub_lwproc_switch(struct lwp *arg1)
{

rump_schedule();
rump_lkl_lwproc_switch(arg1);
rump_unschedule();
}

void
rump_pub_lwproc_releaselwp(void)
{

rump_schedule();
rump_lkl_lwproc_release();
rump_unschedule();
}

struct lwp *
rump_pub_lwproc_curlwp(void)
{
struct lwp *rv;

rump_schedule();
rv = rump_lkl_lwproc_curlwp();
rump_unschedule();

return rv;
}

int
rump_syscall(int num, void *data, size_t dlen, long *retval)
{
int ret = 0;

ret = lkl_syscall(num, (long *)data);
/* FIXME: need better err translation */
if (ret < 0) {
retval[0] = -ret;
ret = -1;
}
return ret;
}


static int
rump_lkl_hyp_syscall(int num, void *arg, long *retval)
{
return rump_syscall(num, arg, 0, retval);
}

static int
rump_lkl_lwproc_rfork(void *priv, int flags, const char *comm)
{
#ifdef ENABLE_SYSPROXY
/* FIXME: needs new task_struct instead of get_current() */
struct thread_info *ti = task_thread_info(get_current());

/* store struct spc_client */
ti->rump_client = priv;

rumpuser_curlwpop(RUMPUSER_LWP_CREATE, (struct lwp *)ti);
rumpuser_curlwpop(RUMPUSER_LWP_SET, (struct lwp *)ti);
#endif
return 0;
}

static void
rump_lkl_lwproc_release(void)
{
struct thread_info *ti = (struct thread_info *)rumpuser_curlwp();

rumpuser_curlwpop(RUMPUSER_LWP_CLEAR, (struct lwp *)ti);
}

static void
rump_lkl_lwproc_switch(struct lwp *newlwp)
{
struct thread_info *ti = (struct thread_info *)rumpuser_curlwp();

rumpuser_curlwpop(RUMPUSER_LWP_CLEAR, (struct lwp *)ti);
rumpuser_curlwpop(RUMPUSER_LWP_SET, (struct lwp *)ti);
}

/* find rump_task created by rfork */
static int
rump_lkl_lwproc_newlwp(pid_t pid)
{
#ifdef FIXME
/* find rump_task */
struct thread_info *ti = NULL;
struct task_struct *p;

for_each_process(p) {
if (p->pid == pid) {
ti = task_thread_info(p);
break;
}
}

if (!ti) {
pr_warn("newlwp: could not find pid %d\n", pid);
ti = current_thread_info();
/* FIXME */
// return ESRCH;
}

/* set to currnet */
rumpuser_curlwpop(RUMPUSER_LWP_SET, (struct lwp *)ti);

#endif /* FIXME */
return 0;
}

static struct lwp *
rump_lkl_lwproc_curlwp(void)
{
return rumpuser_curlwp();
}

static void
rump_lkl_hyp_lwpexit(void)
{
struct thread_info *ti = (struct thread_info *)rumpuser_curlwp();

rumpuser_curlwpop(RUMPUSER_LWP_DESTROY, (struct lwp *)ti);
#ifdef FIXME
free_thread_info(ti);
#endif
}

static pid_t
rump_lkl_hyp_getpid(void)
{
#ifdef FIXME
struct thread_info *ti = (struct thread_info *)rumpuser_curlwp();

return ti->task->pid;
#endif
return -1;
}

static void rump_lkl_user_unschedule(int nlocks, int *countp,
void *interlock) {}
static void rump_lkl_user_schedule(int nlocks, void *interlock) {}
static void rump_lkl_hyp_execnotify(const char *comm) {}

const struct rumpuser_hyperup hyp = {
.hyp_schedule = rump_schedule,
.hyp_unschedule = rump_unschedule,
.hyp_backend_unschedule = rump_lkl_user_unschedule,
.hyp_backend_schedule = rump_lkl_user_schedule,

.hyp_lwproc_switch = rump_lkl_lwproc_switch,
.hyp_lwproc_release = rump_lkl_lwproc_release,
.hyp_lwproc_newlwp = rump_lkl_lwproc_newlwp,
.hyp_lwproc_curlwp = rump_lkl_lwproc_curlwp,

.hyp_getpid = rump_lkl_hyp_getpid,
.hyp_syscall = rump_lkl_hyp_syscall,
.hyp_lwproc_rfork = rump_lkl_lwproc_rfork,
.hyp_lwpexit = rump_lkl_hyp_lwpexit,
.hyp_execnotify = rump_lkl_hyp_execnotify,
};


23 changes: 23 additions & 0 deletions tools/lkl/lib/rump.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Rump hypercall interface for Linux
* Copyright (c) 2015 Hajime Tazaki
*
* Author: Hajime Tazaki <thehajime@gmail.com>
*/

#define __dead
#define __printflike(x, y)
#include <rump/rumpuser.h>

struct irq_data;

void rump_sysproxy_init(void);
void rump_sysproxy_fini(void);

extern const struct rumpuser_hyperup hyp;
#ifdef ENABLE_SYSPROXY
extern struct rump_sysproxy_ops rump_sysproxy_ops;
#endif

int rump_pci_irq_request(struct irq_data *data);
void rump_pci_irq_release(struct irq_data *data);
4 changes: 4 additions & 0 deletions tools/lkl/lib/utils.c
Original file line number Diff line number Diff line change
@@ -3,6 +3,10 @@
#include <string.h>
#include <lkl_host.h>

#ifdef RUMPUSER
#include "rump.h"
#endif

static const char * const lkl_err_strings[] = {
"Success",
"Operation not permitted",
4 changes: 4 additions & 0 deletions tools/lkl/lib/virtio.c
Original file line number Diff line number Diff line change
@@ -66,6 +66,10 @@ struct _virtio_req {
};


#if defined(__ARMEL__)
#define __sync_synchronize(x) lkl__sync_synchronize(x)
#endif

static inline uint16_t virtio_get_used_event(struct virtio_queue *q)
{
return q->avail->ring[q->num];
3 changes: 3 additions & 0 deletions tools/lkl/lib/virtio.h
Original file line number Diff line number Diff line change
@@ -89,4 +89,7 @@ void virtio_set_queue_max_merge_len(struct virtio_dev *dev, int q, int len);
#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - __builtin_offsetof(type, member))

/* XXX: must be provided by another way */
void franken_recv_thread(int fd, void *thrid);

#endif /* _LKL_LIB_VIRTIO_H */
15 changes: 15 additions & 0 deletions tools/lkl/lib/virtio_net.c
Original file line number Diff line number Diff line change
@@ -258,6 +258,21 @@ int lkl_netdev_add(struct lkl_netdev *nd, struct lkl_netdev_args* args)
if (dev->poll_tid == 0)
goto out_cleanup_dev;

/* XXX: only for rump: need to use this semantics for franken_poll(2) */
#ifdef LIBRUMPUSER
{
struct lkl_netdev_rumpfd {
struct lkl_netdev dev;
/* TAP device */
int fd;
};

struct lkl_netdev_rumpfd *nd_rumpfd =
container_of(nd, struct lkl_netdev_rumpfd, dev);
franken_recv_thread(nd_rumpfd->fd, (void *)dev->poll_tid);
}
#endif /* LIBRUMPUSER */

ret = dev_register(dev);
if (ret < 0)
goto out_cleanup_dev;
2 changes: 1 addition & 1 deletion tools/lkl/tests/Makefile
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ endef

QUICK?=0
VALGRIND_TEXT?=0
FS_TYPES?=ext4 btrfs vfat xfs
FS_TYPES?=ext4 vfat xfs

# The hijack tests are very time consuming, so run with `QUICK=1 make
# test` if you want to stick to the unit tests
2 changes: 1 addition & 1 deletion tools/lkl/tests/boot.c
Original file line number Diff line number Diff line change
@@ -180,7 +180,7 @@ int test_creat(char *str, int len)

snprintf(str, len, "%ld", ret);

if (ret == 0)
if (ret == 3) /* 0/1/2 are already opened */
return TEST_SUCCESS;

return TEST_FAILURE;