dde_linux: remove legacy lx_kit and lx_emul

All good things must come to an end.

issue #5104
This commit is contained in:
Sebastian Sumpf 2024-02-08 21:03:40 +01:00 committed by Christian Helmuth
parent 8aa3967201
commit 97f8179f90
71 changed files with 0 additions and 6975 deletions

View File

@ -1,121 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** asm/cmpxchg.h **
*******************/
#define cmpxchg(ptr, o, n) ({ \
typeof(*ptr) prev = *ptr; \
*ptr = (*ptr == o) ? n : *ptr; \
prev;\
})
#define xchg(ptr, x) ({ \
typeof(*ptr) old = *ptr; \
*ptr = x; \
old; \
})
#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
/******************
** asm/atomic.h **
******************/
#include <asm-generic/atomic64.h>
#define ATOMIC_INIT(i) { (i) }
typedef struct atomic { int counter; } atomic_t;
typedef struct { long counter; } atomic_long_t;
static inline int atomic_read(const atomic_t *p) { return p->counter; }
static inline void atomic_set(atomic_t *p, int i) { p->counter = i; }
static inline void atomic_sub(int i, atomic_t *p) { p->counter -= i; }
static inline void atomic_add(int i, atomic_t *p) { p->counter += i; }
static inline int atomic_sub_return(int i, atomic_t *p) { p->counter -= i; return p->counter; }
static inline int atomic_add_return(int i, atomic_t *p) { p->counter += i; return p->counter; }
static inline int atomic_sub_and_test(int i, atomic_t *p) { return atomic_sub_return(i, p) == 0; }
static inline void atomic_dec(atomic_t *p) { atomic_sub(1, p); }
static inline void atomic_inc(atomic_t *p) { atomic_add(1, p); }
static inline int atomic_dec_return(atomic_t *p) { return atomic_sub_return(1, p); }
static inline int atomic_inc_return(atomic_t *p) { return atomic_add_return(1, p); }
static inline int atomic_dec_and_test(atomic_t *p) { return atomic_sub_and_test(1, p); }
static inline int atomic_inc_not_zero(atomic_t *p) { return p->counter ? atomic_inc_return(p) : 0; }
static inline void atomic_long_inc(atomic_long_t *p) { p->counter += 1; }
static inline void atomic_long_sub(long i, atomic_long_t *p) { p->counter -= i; }
static inline long atomic_long_add_return(long i, atomic_long_t *p) { p->counter += i; return p->counter; }
static inline long atomic_long_read(atomic_long_t *p) { return p->counter; }
static inline int atomic_cmpxchg(atomic_t *v, int old, int n)
{
return cmpxchg(&v->counter, old, n);
}
static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
{
int val, c = hint;
/* sanity test, should be removed by compiler if hint is a constant */
if (!hint)
return atomic_inc_not_zero(v);
do {
val = atomic_cmpxchg(v, c, c + 1);
if (val == c)
return 1;
c = val;
} while (c);
return 0;
}
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;
(void)flags;
ret = v->counter;
if (ret != u)
v->counter += a;
return ret != u;
}
static inline int atomic_dec_if_positive(atomic_t *v)
{
int c = atomic_read(v);
if (c >= 0)
atomic_dec(v);
return c - 1;
}
#define smp_mb__before_atomic_dec()
/*******************************
** asm-generic/atomic-long.h **
*******************************/
#define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)

View File

@ -1,121 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************************
** asm-generic/bitsperlong.h **
*******************************/
#define BITS_PER_LONG (__SIZEOF_LONG__ * 8)
/**********************************
** linux/bitops.h, asm/bitops.h **
**********************************/
#define BITS_PER_BYTE 8
#define BIT(nr) (1UL << (nr))
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define BIT_ULL(nr) (1ULL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#include <asm-generic/bitops/non-atomic.h>
#define test_and_clear_bit(nr, addr) \
__test_and_clear_bit(nr, (volatile unsigned long *)(addr))
#define test_and_set_bit(nr, addr) \
__test_and_set_bit(nr, (volatile unsigned long *)(addr))
#define set_bit(nr, addr) \
__set_bit(nr, (volatile unsigned long *)(addr))
#define clear_bit(nr, addr) \
__clear_bit(nr, (volatile unsigned long *)(addr))
#define smp_mb__before_clear_bit()
#define smp_mb__after_clear_bit() smp_mb()
/**
* Find first zero bit (limit to machine word size)
*/
long find_next_zero_bit_le(const void *addr,
unsigned long size, unsigned long offset);
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/fls64.h>
static inline unsigned fls_long(unsigned long l)
{
if (sizeof(l) == 4)
return fls(l);
return fls64(l);
}
static inline unsigned long __ffs64(u64 word)
{
#if BITS_PER_LONG == 32
if (((u32)word) == 0UL)
return __ffs((u32)(word >> 32)) + 32;
#elif BITS_PER_LONG != 64
#error BITS_PER_LONG not 32 or 64
#endif
return __ffs((unsigned long)word);
}
#include <linux/log2.h>
#define for_each_set_bit(bit, addr, size) \
for ((bit) = find_first_bit((addr), (size)); \
(bit) < (size); \
(bit) = find_next_bit((addr), (size), (bit) + 1))
#define for_each_clear_bit(bit, addr, size) \
for ((bit) = find_first_zero_bit((addr), (size)); \
(bit) < (size); \
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
static inline int get_bitmask_order(unsigned int count) {
return __builtin_clz(count) ^ 0x1f; }
static inline __s32 sign_extend32(__u32 value, int index)
{
__u8 shift = 31 - index;
return (__s32)(value << shift) >> shift;
}
static inline __u32 rol32(__u32 word, unsigned int shift)
{
return (word << shift) | (word >> (32 - shift));
}
static inline __u32 ror32(__u32 word, unsigned int shift)
{
return (word >> shift) | (word << (32 - shift));
}
static inline __u16 ror16(__u16 word, unsigned int shift)
{
return (word >> shift) | (word << (16 - shift));
}
#define BITS_PER_LONG_LONG (sizeof(long long) * 8)
#define GENMASK_ULL(h, l) \
(((~0ULL) - (1ULL << (l)) + 1) & \
(~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))

View File

@ -1,54 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/***************
** asm/bug.h **
***************/
extern void lx_sleep_forever() __attribute__((noreturn));
#define WARN_ON(condition) ({ \
int ret = !!(condition); \
if (ret) lx_printf("[%s] WARN_ON(%s) \n", __func__, #condition); \
ret; })
#define WARN(condition, fmt, arg...) ({ \
int ret = !!(condition); \
if (ret) lx_printf("[%s] *WARN* " fmt " \n", __func__ , ##arg); \
ret; })
#define BUG() do { \
lx_printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
lx_sleep_forever(); \
} while (0)
#define WARN_ON_ONCE WARN_ON
#define WARN_ONCE WARN
#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
#define BUILD_BUG_ON_MSG(cond,msg) ({ \
extern int __attribute__((error(msg))) build_bug(); \
if (cond) { build_bug(); } })
#define BUILD_BUG() BUILD_BUG_ON_MSG(1,"BUILD_BUG failed")
#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))

View File

@ -1,50 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*************************************
** linux/byteorder/little_endian.h **
*************************************/
#include <uapi/linux/byteorder/little_endian.h>
/*******************************
** linux/byteorder/generic.h **
*******************************/
#define le16_to_cpu __le16_to_cpu
#define be16_to_cpu __be16_to_cpu
#define le32_to_cpu __le32_to_cpu
#define be32_to_cpu __be32_to_cpu
#define le16_to_cpus __le16_to_cpus
#define cpu_to_le16p __cpu_to_le16p
#define cpu_to_be16p __cpu_to_be16p
#define cpu_to_le16 __cpu_to_le16
#define cpu_to_le16s __cpu_to_le16s
#define cpu_to_be16 __cpu_to_be16
#define cpu_to_le32 __cpu_to_le32
#define cpu_to_le32p __cpu_to_le32p
#define cpu_to_be32 __cpu_to_be32
#define cpu_to_be32p __cpu_to_be32p
#define cpu_to_le32s __cpu_to_le32s
#define cpu_to_le64 __cpu_to_le64
#define le16_to_cpup __le16_to_cpup
#define be16_to_cpup __be16_to_cpup
#define le32_to_cpup __le32_to_cpup
#define le32_to_cpus __le32_to_cpus
#define be32_to_cpup __be32_to_cpup
#define le64_to_cpu __le64_to_cpu

View File

@ -1,92 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/**********************
** linux/compiler.h **
**********************/
#define likely
#define unlikely
#define __user
#define __iomem
#define __rcu
#define __percpu
#define __must_check
#define __force
#define __read_mostly
#define __releases(x) /* needed by usb/core/devio.c */
#define __acquires(x) /* needed by usb/core/devio.c */
#define __force
#define __maybe_unused
#define __bitwise
# define __acquire(x) (void)0
# define __release(x) (void)0
#define __must_check
#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
#define __attribute_const__
#undef __always_inline
#define __always_inline inline
#undef __unused
#define noinline __attribute__((noinline))
#define __printf(a, b) __attribute__((format(printf, a, b)))
#define __always_unused
#define __read_mostly
#define __noreturn __attribute__((noreturn))
#define WRITE_ONCE(x, val) \
({ \
barrier(); \
union { typeof(x) v; char c[1]; } u = \
{ .v = (typeof(x)) (val) }; \
__builtin_memcpy((void *)&(x), (const void *)u.c, sizeof(x)); \
barrier(); \
})
/* XXX alpha, powerpc, blackfin needs proper implementation */
#define smp_read_barrier_depends() do { } while (0)
#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); barrier(); } while (0)
#ifndef __compiletime_object_size
# define __compiletime_object_size(obj) -1
#endif
/**************************
** linux/compiler-gcc.h **
**************************/
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#define __weak __attribute__((weak))
#define __aligned(x) __attribute__((aligned(x)))
#define uninitialized_var(x) x = x
#define unreachable() \
do { __builtin_unreachable(); } while (0)

View File

@ -1,33 +0,0 @@
/*
* \brief Linux kernel API
* \author Sebastian Sumpf
* \date 2016-03-31
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/************************
** linux/completion.h **
************************/
struct completion;
void complete(struct completion *);
void complete_all(struct completion *);
void init_completion(struct completion *c);
bool try_wait_for_completion(struct completion *);
void wait_for_completion(struct completion *c);
unsigned long wait_for_completion_timeout(struct completion *c,
unsigned long timeout);
int wait_for_completion_interruptible(struct completion *c);
long wait_for_completion_interruptible_timeout(struct completion *c,
unsigned long timeout);

View File

@ -1,134 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************************
** linux/errno.h and friends **
*******************************/
/**
* Error codes
*
* Note that the codes do not correspond to those of the Linux kernel.
*/
enum {
/*
* The following numbers correspond to FreeBSD
*/
EPERM = 1,
ENOENT = 2,
ESRCH = 3,
EINTR = 4,
EIO = 5,
ENXIO = 6,
E2BIG = 7,
ENOEXEC = 8,
EBADF = 9,
EDEADLK = 11,
ENOMEM = 12,
EACCES = 13,
EFAULT = 14,
EBUSY = 16,
EEXIST = 17,
EXDEV = 18,
ENODEV = 19,
EINVAL = 22,
ENFILE = 23,
ENOTTY = 25,
EFBIG = 27,
ENOSPC = 28,
ESPIPE = 29,
EPIPE = 32,
EDOM = 33,
ERANGE = 34,
EAGAIN = 35,
EINPROGRESS = 36,
EALREADY = 37,
ENOTSOCK = 38,
EDESTADDRREQ = 39,
EMSGSIZE = 40,
ENOPROTOOPT = 42,
EPROTONOSUPPORT = 43,
ESOCKTNOSUPPORT = 44,
EOPNOTSUPP = 45,
EPFNOSUPPORT = 46,
EAFNOSUPPORT = 47,
EADDRINUSE = 48,
EADDRNOTAVAIL = 49,
ENETDOWN = 50,
ENETUNREACH = 51,
ECONNABORTED = 53,
ECONNRESET = 54,
ENOBUFS = 55,
EISCONN = 56,
ENOTCONN = 57,
ETIMEDOUT = 60,
ECONNREFUSED = 61,
ENAMETOOLONG = 63,
EHOSTDOWN = 64,
EHOSTUNREACH = 65,
ENOSYS = 78,
ENOMSG = 83,
EOVERFLOW = 84,
ECANCELED = 85,
EILSEQ = 86,
EBADMSG = 89,
ENOLINK = 91,
EPROTO = 92,
/*
* The following numbers correspond to nothing
*/
EREMOTEIO = 200,
ERESTARTSYS = 201,
ENODATA = 202,
ETOOSMALL = 203,
ENOIOCTLCMD = 204,
ENONET = 205,
ENOTSUPP = 206,
ENOTUNIQ = 207,
ERFKILL = 208,
ETIME = 209,
EPROBE_DEFER = 210,
EL3RST = 211,
ENOKEY = 212,
ECHRNG = 213,
MAX_ERRNO = 4095,
};
/*****************
** linux/err.h **
*****************/
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)(0UL-MAX_ERRNO))
static inline bool IS_ERR(void const *ptr) {
return (unsigned long)(ptr) >= (unsigned long)(0UL-MAX_ERRNO); }
static inline void * ERR_PTR(long error) {
return (void *) error; }
static inline void * ERR_CAST(const void *ptr) {
return (void *) ptr; }
static inline long IS_ERR_OR_NULL(const void *ptr) {
return !ptr || IS_ERR_VALUE((unsigned long)ptr); }
static inline long PTR_ERR(const void *ptr) { return (long) ptr; }

View File

@ -1,33 +0,0 @@
/*
* \brief Include before including Linux headers in C++
* \author Christian Helmuth
* \date 2014-08-21
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifdef __cplusplus
#define extern_c_begin
extern "C" {
/* some warnings should only be switched of for Linux headers */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-arith"
#pragma GCC diagnostic ignored "-Wsign-compare"
/* deal with C++ keywords used for identifiers etc. */
#define private private_
#define class class_
#define new new_
#define delete delete_
#define namespace namespace_
#define virtual virtual_
#endif /* __cplusplus */

View File

@ -1,27 +0,0 @@
/*
* \brief Include after including Linux headers in C++
* \author Christian Helmuth
* \date 2014-08-21
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifdef __cplusplus
#undef delete
#undef new
#undef class
#undef private
#undef namespace
#undef virtual
#pragma GCC diagnostic pop
} /* extern "C" */
#endif /* __cplusplus */

View File

@ -1,61 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*****************
** linux/gfp.h **
*****************/
enum {
__GFP_DMA = 0x00000001u,
__GFP_HIGHMEM = 0x00000002u,
__GFP_DMA32 = 0x00000004u,
__GFP_MOVABLE = 0x00000008u,
__GFP_RECLAIMABLE = 0x00000010u,
__GFP_HIGH = 0x00000020u,
__GFP_IO = 0x00000040u,
__GFP_FS = 0x00000080u,
__GFP_NOWARN = 0x00000200u,
__GFP_RETRY_MAYFAIL = 0x00000400u,
__GFP_NOFAIL = 0x00000800u,
__GFP_NORETRY = 0x00001000u,
__GFP_MEMALLOC = 0x00002000u,
__GFP_COMP = 0x00004000u,
__GFP_ZERO = 0x00008000u,
__GFP_NOMEMALLOC = 0x00010000u,
__GFP_HARDWALL = 0x00020000u,
__GFP_THISNODE = 0x00040000u,
__GFP_ATOMIC = 0x00080000u,
__GFP_ACCOUNT = 0x00100000u,
__GFP_DIRECT_RECLAIM = 0x00200000u,
__GFP_WRITE = 0x00800000u,
__GFP_KSWAPD_RECLAIM = 0x01000000u,
GFP_LX_DMA = 0x80000000u,
__GFP_RECLAIM = __GFP_DIRECT_RECLAIM | __GFP_KSWAPD_RECLAIM,
GFP_ATOMIC = (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM),
GFP_DMA = __GFP_DMA,
GFP_DMA32 = __GFP_DMA32,
GFP_KERNEL = __GFP_RECLAIM | __GFP_IO | __GFP_FS,
/*
GFP_TEMPORARY = __GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_RECLAIMABLE,
*/
GFP_USER = __GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL,
GFP_HIGHUSER = GFP_USER | __GFP_HIGHMEM,
};
#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)

View File

@ -1,144 +0,0 @@
/*
* \brief Implementation of linux/completion.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kint includes */
#include <legacy/lx_kit/env.h>
#include <legacy/lx_kit/internal/task.h>
typedef Lx::Task::List_element Wait_le;
typedef Lx::Task::List Wait_list;
void init_waitqueue_head(wait_queue_head_t *wq)
{
static_assert(sizeof(wq->wait_list_reserved) >= sizeof(Wait_list));
Genode::construct_at<Wait_list>(wq->wait_list_reserved);
wq->list = &wq->wait_list_reserved;
}
void add_wait_queue(wait_queue_head_t *q, wait_queue_entry_t *wait)
{
printk("%s called\n", __func__);
}
void remove_wait_queue(wait_queue_head_t *wq, wait_queue_entry_t *wait)
{
printk("%s called\n", __func__);
}
int waitqueue_active(wait_queue_head_t *wq)
{
Wait_list *list = static_cast<Wait_list*>(wq->list);
if (!list) { return 0; }
return list->first() ? 1 : 0;
}
void __wake_up(wait_queue_head_t *wq, bool all)
{
Wait_list *list = static_cast<Wait_list *>(wq->list);
if (!list) { return; }
Wait_le *le = list->first();
do {
if (!le) { return; }
le->object()->unblock();
} while (all && (le = le->next()));
}
void wake_up_interruptible_sync_poll(wait_queue_head_t *wq, int)
{
__wake_up(wq, false);
}
void ___wait_event(wait_queue_head_t *wq)
{
Wait_list *list = static_cast<Wait_list *>(wq->list);
if (!list) {
init_waitqueue_head(wq);
list = static_cast<Wait_list *>(wq->list);
}
Lx::Task *task = Lx::scheduler().current();
task->wait_enqueue(list);
task->block_and_schedule();
task->wait_dequeue(list);
}
void init_completion(struct completion *work)
{
work->done = 0;
}
void complete(struct completion *work)
{
if (work->done != UINT_MAX)
work->done++;
Lx::Task *task = static_cast<Lx::Task*>(work->task);
if (task) { task->unblock(); }
}
void complete_all(struct completion *work)
{
work->done = UINT_MAX;
Lx::Task *task = static_cast<Lx::Task*>(work->task);
if (task) { task->unblock(); }
}
bool try_wait_for_completion(struct completion *work)
{
int ret = 1;
if (!work->done)
ret = 0;
else if (work->done != UINT_MAX)
work->done--;
return ret;
}
unsigned long wait_for_completion_timeout(struct completion *work,
unsigned long timeout)
{
return __wait_completion(work, timeout);
}
int wait_for_completion_interruptible(struct completion *work)
{
__wait_completion(work, 0);
return 0;
}
long wait_for_completion_interruptible_timeout(struct completion *work,
unsigned long timeout)
{
return __wait_completion(work, timeout);
}
void wait_for_completion(struct completion *work)
{
__wait_completion(work, 0);
}

View File

@ -1,64 +0,0 @@
/*
* \brief Implementation of linux/delay.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*
* Disable preprocessor macros that are incompatible to Genode headers for this
* file.
*/
#pragma push_macro("max")
#pragma push_macro("min")
#undef max
#undef min
/* Genode includes */
#include <timer_session/connection.h>
#include <legacy/lx_kit/env.h>
#include <legacy/lx_kit/timer.h>
/*
* XXX "We may consider to use the Lx::Timer instead of opening a dedicated
* timer session" which I tried during the deprecation warning removal
* but it did not work out. At least the intel_fb at that point got stuck
* because the workqueue task got mutex blocked.
*/
static Genode::Constructible<Timer::Connection> _delay_timer;
static inline void __delay_timer(unsigned long usecs)
{
if (!_delay_timer.constructed()) {
_delay_timer.construct(Lx_kit::env().env());
}
_delay_timer->usleep(usecs);
}
void udelay(unsigned long usecs)
{
__delay_timer(usecs);
Lx::timer_update_jiffies();
}
void msleep(unsigned int msecs)
{
__delay_timer(1000 * msecs);
Lx::timer_update_jiffies();
}
void mdelay(unsigned long msecs) { msleep(msecs); }
#pragma pop_macro("max")
#pragma pop_macro("min")

View File

@ -1,70 +0,0 @@
/*
* \brief Implementation of linux/gfp.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/addr_to_page_mapping.h>
#include <legacy/lx_kit/backend_alloc.h>
#include <legacy/lx_kit/malloc.h>
#include <legacy/lx_kit/env.h>
struct page *alloc_pages(gfp_t const gfp_mask, unsigned int order)
{
using Genode::Cache;
struct page *page = (struct page *)kzalloc(sizeof(struct page), 0);
size_t size = PAGE_SIZE << order;
gfp_t const dma_mask = (GFP_DMA | GFP_LX_DMA | GFP_DMA32);
Cache const cache = (gfp_mask & dma_mask) ? Genode::UNCACHED
: Genode::CACHED;
Genode::Ram_dataspace_capability ds_cap = Lx::backend_alloc(size, cache);
page->addr = Lx_kit::env().rm().attach(ds_cap);
page->paddr = Lx::backend_dma_addr(ds_cap);
if (!page->addr) {
Genode::error("alloc_pages: ", size, " failed");
kfree(page);
return 0;
}
Lx::Addr_to_page_mapping::insert(page, ds_cap);
return page;
}
void free_pages(unsigned long addr, unsigned int order)
{
page * page = Lx::Addr_to_page_mapping::find_page(addr);
if (!page) return;
Genode::Ram_dataspace_capability cap =
Lx::Addr_to_page_mapping::remove(page);
if (cap.valid())
Lx::backend_free(cap);
kfree(page);
}
void get_page(struct page *page)
{
atomic_inc(&page->_count);
}
void put_page(struct page *page)
{
TRACE;
}

View File

@ -1,42 +0,0 @@
/*
* \brief Implementation of linux/kernel.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <format/snprintf.h>
int sprintf(char *str, const char *format, ...)
{
enum { BUFFER_LEN = 128 };
va_list list;
va_start(list, format);
Format::String_console sc(str, BUFFER_LEN);
sc.vprintf(format, list);
va_end(list);
return sc.len();
}
int snprintf(char *buf, size_t size, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
Format::String_console sc(buf, size);
sc.vprintf(fmt, args);
va_end(args);
return sc.len();
}

View File

@ -1,127 +0,0 @@
/*
* \brief Implementation of linux/mutex.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/scheduler.h>
#include <legacy/lx_kit/env.h>
enum { MUTEX_UNLOCKED = 1, MUTEX_LOCKED = 0, MUTEX_WAITERS = -1 };
void mutex_init(struct mutex *m)
{
static unsigned id = 0;
m->state = MUTEX_UNLOCKED;
m->holder = nullptr;
m->waiters = nullptr;
m->id = ++id;
m->counter = 0;
}
void mutex_destroy(struct mutex *m)
{
Lx::Task::List *waiters = static_cast<Lx::Task::List *>(m->waiters);
/* FIXME potentially blocked tasks are not unblocked */
if (waiters && waiters->first()) {
Genode::error(__func__, "destroying non-empty waiters list");
}
Genode::destroy(&Lx_kit::env().heap(), waiters);
m->holder = nullptr;
m->waiters = nullptr;
m->id = 0;
m->counter = 0;
}
static inline void __check_or_initialize_mutex(struct mutex *m)
{
if (!m->waiters) {
m->waiters = new (&Lx_kit::env().heap()) Lx::Task::List;
}
}
void mutex_lock(struct mutex *m)
{
__check_or_initialize_mutex(m);
while (1) {
if (m->state == MUTEX_UNLOCKED) {
m->state = MUTEX_LOCKED;
m->holder = Lx::scheduler().current();
break;
}
Lx::Task *t = reinterpret_cast<Lx::Task *>(m->holder);
if (t == Lx::scheduler().current()) {
m->counter++;
return;
}
/* notice that a task waits for the mutex to be released */
m->state = MUTEX_WAITERS;
/* block until the mutex is released (and retry then) */
Lx::scheduler().current()->mutex_block(static_cast<Lx::Task::List *>(m->waiters));
Lx::scheduler().current()->schedule();
}
}
void mutex_unlock(struct mutex *m)
{
if (m->state == MUTEX_UNLOCKED) {
Genode::error("bug: multiple mutex unlock detected");
Genode::sleep_forever();
}
if (m->holder != Lx::scheduler().current()) {
Genode::error("bug: mutex unlock by task not holding the mutex");
Genode::sleep_forever();
}
if (m->counter) {
m->counter--;
return;
}
Lx::Task::List *waiters = static_cast<Lx::Task::List *>(m->waiters);
if (m->state == MUTEX_WAITERS)
while (Lx::Task::List_element *le = waiters->first())
le->object()->mutex_unblock(waiters);
m->state = MUTEX_UNLOCKED;
m->holder = nullptr;
}
int mutex_is_locked(struct mutex *m)
{
return m->state != MUTEX_UNLOCKED;
}
int mutex_trylock(struct mutex *m)
{
if (mutex_is_locked(m))
return false;
mutex_lock(m);
return true;
}

View File

@ -1,49 +0,0 @@
/*
* \brief Implementation of linux/sched.h
* \author Norman Feske
* \author Stefan Kalkowski
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/scheduler.h>
struct process_timer {
struct timer_list timer;
Lx::Task &task;
process_timer(Lx::Task &task) : task(task) {}
};
static void process_timeout(struct timer_list *list)
{
struct process_timer *timeout = from_timer(timeout, list, timer);
timeout->task.unblock();
}
signed long schedule_timeout(signed long timeout)
{
Lx::Task & cur_task = *Lx::scheduler().current();
struct process_timer timer { cur_task };
timer_setup(&timer.timer, process_timeout, 0);
unsigned long expire = timeout + jiffies;
mod_timer(&timer.timer, expire);
cur_task.block_and_schedule();
del_timer(&timer.timer);
timeout = (expire - jiffies);
return timeout < 0 ? 0 : timeout;
}

View File

@ -1,214 +0,0 @@
/*
* \brief Implementation of linux/slab.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/malloc.h>
void *kmalloc(size_t size, gfp_t flags)
{
if (flags & __GFP_DMA)
Genode::warning("GFP_DMA memory (below 16 MiB) requested "
"(", __builtin_return_address(0), ")");
if (flags & __GFP_DMA32)
Genode::warning("GFP_DMA32 memory (below 4 GiB) requested"
"(", __builtin_return_address(0), ")");
void *addr = nullptr;
addr = (flags & GFP_LX_DMA)
? Lx::Malloc::dma().alloc(size)
: Lx::Malloc::mem().alloc(size);
if (!addr)
return 0;
if ((Genode::addr_t)addr & 0x3)
Genode::error("unaligned kmalloc ", (Genode::addr_t)addr);
if (flags & __GFP_ZERO)
Genode::memset(addr, 0, size);
return addr;
}
void *kzalloc(size_t size, gfp_t flags)
{
return kmalloc(size, flags | __GFP_ZERO);
}
void *kvzalloc(size_t size, gfp_t flags)
{
return kmalloc(size, flags | __GFP_ZERO);
}
void *kzalloc_node(size_t size, gfp_t flags, int node)
{
return kzalloc(size, 0);
}
void *kcalloc(size_t n, size_t size, gfp_t flags)
{
if (size != 0 && n > (~0UL / size))
return 0;
return kzalloc(n * size, flags);
}
void kfree(void const *p)
{
if (!p) return;
if (Lx::Malloc::mem().inside((Genode::addr_t)p))
Lx::Malloc::mem().free(p);
else if (Lx::Malloc::dma().inside((Genode::addr_t)p))
Lx::Malloc::dma().free(p);
else
Genode::error(__func__, ": unknown block at ", p, ", "
"called from ", __builtin_return_address(0));
}
static size_t _ksize(void *p)
{
size_t size = 0;
if (Lx::Malloc::mem().inside((Genode::addr_t)p))
size = Lx::Malloc::mem().size(p);
else if (Lx::Malloc::dma().inside((Genode::addr_t)p))
size = Lx::Malloc::dma().size(p);
else
Genode::error(__func__, ": unknown block at ", p);
return size;
}
size_t ksize(void *p)
{
return _ksize(p);
}
void kzfree(void const *p)
{
if (!p) return;
size_t len = ksize(const_cast<void*>(p));
Genode::memset((void*)p, 0, len);
kfree(p);
}
void *kmalloc_node_track_caller(size_t size, gfp_t flags, int node)
{
return kmalloc(size, flags);
}
void *krealloc(void *p, size_t size, gfp_t flags)
{
/* XXX handle short-cut where size == old_size */
void *addr = kmalloc(size, flags);
if (addr && p) {
size_t old_size = _ksize(p);
Genode::memcpy(addr, p, old_size);
kfree(p);
}
return addr;
}
void *kmemdup(const void *src, size_t size, gfp_t flags)
{
void *addr = kmalloc(size, flags);
if (addr)
Genode::memcpy(addr, src, size);
return addr;
}
struct kmem_cache : Lx::Slab_alloc
{
size_t _object_size;
void (*ctor)(void *);
kmem_cache(size_t object_size, bool dma, void (*ctor)(void *))
:
Lx::Slab_alloc(object_size, dma ? Lx::Slab_backend_alloc::dma()
: Lx::Slab_backend_alloc::mem()),
_object_size(object_size),
ctor(ctor)
{ }
size_t size() const { return _object_size; }
};
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
unsigned long flags, void (*ctor)(void *))
{
/*
* Copied from wifi_drv.
*
* XXX SLAB_LX_DMA is never used anywhere else, remove it?
*/
enum { SLAB_LX_DMA = 0x80000000ul, };
return new (Lx::Malloc::mem()) kmem_cache(size, flags & SLAB_LX_DMA, ctor);
}
struct kmem_cache *kmem_cache_create_usercopy(const char *name, size_t size,
size_t align, slab_flags_t flags,
size_t useroffset, size_t usersize,
void (*ctor)(void *))
{
/* XXX copied from above */
enum { SLAB_LX_DMA = 0x80000000ul, };
return new (Lx::Malloc::mem()) kmem_cache(size, flags & SLAB_LX_DMA, ctor);
}
void kmem_cache_destroy(struct kmem_cache *cache)
{
destroy(Lx::Malloc::mem(), cache);
}
void * kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
{
void * const ptr = cache->alloc_element();
if (ptr && cache->ctor)
cache->ctor(ptr);
return ptr;
}
void kmem_cache_free(struct kmem_cache *cache, void *objp)
{
cache->free(objp);
}

View File

@ -1,17 +0,0 @@
/*
* \brief Implementation of linux/spinlock.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
void spin_lock_init(spinlock_t *lock) { TRACE; }
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags) { }
void spin_unlock(spinlock_t *lock) { TRACE; }
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) { }

View File

@ -1,95 +0,0 @@
/*
* \brief Implementation of linux/timer.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/timer.h>
int mod_timer(struct timer_list *timer, unsigned long expires)
{
if (!Lx::timer().find(timer))
Lx::timer().add(timer, Lx::Timer::LIST);
return Lx::timer().schedule(timer, expires);
}
void timer_setup(struct timer_list *timer,
void (*function)(struct timer_list *),
unsigned int flags)
{
timer->function = function;
timer->flags = flags;
/*
* For compatibility with 4.4.3 drivers, the 'data' member is passed as
* argument to the callback function. Since the 4.16.3 callback function
* interface has a 'timer_list' pointer as argument, the 'data' member
* points to the 'timer_list' object itself when set up with this
* function.
*/
timer->data = (unsigned long)timer;
}
int timer_pending(const struct timer_list *timer)
{
bool pending = Lx::timer().pending(timer);
return pending;
}
int del_timer(struct timer_list *timer)
{
int rv = Lx::timer().del(timer);
Lx::timer().schedule_next();
return rv;
}
void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode) { }
int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long delta_ns, const enum hrtimer_mode mode)
{
unsigned long expires = tim / ((1000/HZ) * NSEC_PER_MSEC);
/*
* Prevent truncation through rounding the values by adding 1 jiffy
* in this case.
*/
expires += (expires == jiffies);
if (!Lx::timer().find(timer))
Lx::timer().add(timer, Lx::Timer::HR);
return Lx::timer().schedule(timer, expires);
}
bool hrtimer_active(const struct hrtimer *timer)
{
return Lx::timer().find(timer);
}
int hrtimer_cancel(struct hrtimer *timer)
{
int rv = Lx::timer().del(timer);
Lx::timer().schedule_next();
return rv;
}

View File

@ -1,184 +0,0 @@
/*
* \brief Implementation of linux/usb.h
* \author Stefan Kalkowski
* \date 2018-08-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/usb.h>
static DECLARE_WAIT_QUEUE_HEAD(lx_emul_urb_wait);
static int wait_for_free_urb(unsigned int timeout_jiffies)
{
int ret = 0;
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&lx_emul_urb_wait, &wait);
ret = schedule_timeout(timeout_jiffies);
remove_wait_queue(&lx_emul_urb_wait, &wait);
return ret;
}
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value,
__u16 index, void *data, __u16 size, int timeout)
{
Usb::Connection *usb;
Sync_ctrl_urb *scu;
urb *u;
usb_ctrlrequest *dr;
unsigned int timeout_jiffies;
int ret;
dr = (usb_ctrlrequest*)kmalloc(sizeof(usb_ctrlrequest), GFP_KERNEL);
if (!dr) return -ENOMEM;
dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(size);
u = (urb*) usb_alloc_urb(0, GFP_KERNEL);
if (!u) {
ret = -ENOMEM;
goto err_urb;
}
scu = (Sync_ctrl_urb *)kzalloc(sizeof(Sync_ctrl_urb), GFP_KERNEL);
if (!scu) {
ret = -ENOMEM;
goto err_scu;
}
usb_fill_control_urb(u, dev, pipe, (unsigned char *)dr, data,
size, nullptr, nullptr);
if (!dev->bus || !dev->bus->controller) {
ret = -ENODEV;
goto err_fill;
}
/*
* If this function is called with a timeout of 0 to wait forever,
* we wait in pieces of 10s each as 'schedule_timeout' might trigger
* immediately otherwise. The intend to wait forever is reflected
* back nonetheless when sending the urb.
*/
timeout_jiffies = timeout ? msecs_to_jiffies(timeout)
: msecs_to_jiffies(10000u);
usb = (Usb::Connection*)(dev->bus->controller);
for (;;) {
if (usb->source()->ready_to_submit(1))
try {
Genode::construct_at<Sync_ctrl_urb>(scu, *usb, *u);
break;
} catch (...) { }
timeout_jiffies = wait_for_free_urb(timeout_jiffies);
if (!timeout_jiffies && timeout) {
ret = -ETIMEDOUT;
goto err_fill;
}
}
scu->send(timeout ? jiffies_to_msecs(timeout_jiffies) : 0);
ret = u->status >= 0 ? u->actual_length : u->status;
err_fill:
kfree(scu);
err_scu:
usb_free_urb(u);
err_urb:
kfree(dr);
return ret;
}
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{
struct urb *urb = (struct urb*)
kmalloc(sizeof(struct urb) +
iso_packets * sizeof(struct usb_iso_packet_descriptor),
GFP_KERNEL);
if (!urb) return NULL;
Genode::memset(urb, 0, sizeof(*urb));
INIT_LIST_HEAD(&urb->anchor_list);
return urb;
}
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
if (!urb->dev->bus || !urb->dev->bus->controller)
return -ENODEV;
Urb * u = (Urb *)kzalloc(sizeof(Urb), mem_flags);
if (!u)
return 1;
Usb::Connection &usb = *(Usb::Connection*)(urb->dev->bus->controller);
for (;;) {
if (usb.source()->ready_to_submit(1))
try {
Genode::construct_at<Urb>(u, usb, *urb);
break;
} catch (...) { }
(void)wait_for_free_urb(msecs_to_jiffies(10000u));
}
/*
* Self-destruction of the 'Urb' object in its completion function
* would not work if the 'Usb' session gets closed before the
* completion function was called. So we store the pointer in the
* otherwise unused 'hcpriv' member and free it in a following
* 'usb_submit_urb()' or 'usb_free_urb()' call.
*/
if (urb->hcpriv) {
Urb *prev_urb = (Urb*)urb->hcpriv;
prev_urb->~Urb();
kfree(urb->hcpriv);
}
urb->hcpriv = u;
u->send();
return 0;
}
void usb_free_urb(struct urb *urb)
{
if (!urb)
return;
/* free 'Urb' object */
if (urb->hcpriv) {
Urb *u = (Urb*)urb->hcpriv;
/* URB is not fred through packet stream */
if (u->completed() == false) return;
u->~Urb();
kfree(urb->hcpriv);
}
kfree(urb);
wake_up(&lx_emul_urb_wait);
}

View File

@ -1,43 +0,0 @@
/*
* \brief Implementation of linux/wait.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/scheduler.h>
void prepare_to_wait(wait_queue_head_t *q, wait_queue_entry_t *, int)
{
if (!q) { return; }
Wait_list *list = static_cast<Wait_list *>(q->list);
Lx::Task *task = Lx::scheduler().current();
task->wait_enqueue(list);
}
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_entry_t *, int)
{
prepare_to_wait(q, 0, 0);
}
void finish_wait(wait_queue_head_t *q, wait_queue_entry_t *)
{
if (!q) { return; }
Wait_list *list = static_cast<Wait_list *>(q->list);
Lx::Task *task = Lx::scheduler().current();
task->wait_dequeue(list);
}

View File

@ -1,111 +0,0 @@
/*
* \brief Implementation of linux/workqueue.h
* \author Stefan Kalkowski
* \date 2015-10-26
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <legacy/lx_kit/scheduler.h>
#include <legacy/lx_kit/work.h>
int schedule_work(struct work_struct *work)
{
queue_work(work->wq ? work->wq : system_wq, work);
return 1;
}
bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
{
work->wq = wq;
/* a invalid func pointer will lead to pagefault with ip=0 sp=0 */
if (!work || !work->func) {
Genode::error("invalid work, called from ",
__builtin_return_address(0));
return false;
}
/* check for separate work queue task */
if (wq && wq->task) {
Lx::Work *lx_work = (Lx::Work *)wq->task;
lx_work->schedule(work);
lx_work->unblock();
} else {
Lx::Work::work_queue().schedule(work);
Lx::Work::work_queue().unblock();
}
return true;
}
void delayed_work_timer_fn(struct timer_list *t)
{
struct delayed_work *dwork = from_timer(dwork, t, timer);
queue_work(dwork->wq, &dwork->work);
}
bool queue_delayed_work(struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay)
{
dwork->wq = wq;
/* treat delayed work without delay like any other work */
if (delay == 0) {
delayed_work_timer_fn(&dwork->timer);
} else {
timer_setup(&dwork->timer, delayed_work_timer_fn, 0);
mod_timer(&dwork->timer, jiffies + delay);
}
return true;
}
int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
{
return queue_delayed_work(dwork->wq ? dwork->wq : system_wq, dwork, delay);
}
bool cancel_work_sync(struct work_struct *work)
{
/* check for separate work queue task */
if (work->wq && work->wq->task) {
Lx::Work *lx_work = (Lx::Work *)work->wq->task;
return lx_work->cancel_work(work, true);
}
return false;
}
bool cancel_delayed_work(struct delayed_work *dwork)
{
int pending = timer_pending(&dwork->timer);
del_timer(&dwork->timer);
/* if the timer is still pending dwork was not executed */
return pending;
}
bool cancel_delayed_work_sync(struct delayed_work *dwork)
{
bool pending = cancel_delayed_work(dwork);
if (pending) {
dwork->work.func(&dwork->work);
}
return pending;
}

View File

@ -1,82 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/********************
** linux/ioport.h **
********************/
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_MEM 0x00000200
#define IORESOURCE_IRQ 0x00000400
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
struct resource
{
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
};
/* helpers to define resources */
#define DEFINE_RES_NAMED(_start, _size, _name, _flags) \
{ \
.start = (_start), \
.end = (_start) + (_size) - 1, \
.name = (_name), \
.flags = (_flags), \
}
#define DEFINE_RES_MEM_NAMED(_start, _size, _name) \
DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_MEM)
#define DEFINE_RES_MEM(_start, _size) \
DEFINE_RES_MEM_NAMED((_start), (_size), NULL)
struct device;
struct resource *request_region(resource_size_t start, resource_size_t n,
const char *name);
struct resource *request_mem_region(resource_size_t start, resource_size_t n,
const char *name);
struct resource * devm_request_mem_region(struct device *dev, resource_size_t start,
resource_size_t n, const char *name);
void release_region(resource_size_t start, resource_size_t n);
void release_mem_region(resource_size_t start, resource_size_t n);
static inline resource_size_t resource_size(const struct resource *res)
{
return res->end - res->start + 1;
}
static inline unsigned long resource_type(const struct resource *res)
{
return res->flags & IORESOURCE_TYPE_BITS;
}
/* True iff r1 completely contains r2 */
static inline bool resource_contains(struct resource *r1, struct resource *r2)
{
if (resource_type(r1) != resource_type(r2))
return false;
if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET)
return false;
return r1->start <= r2->start && r1->end >= r2->end;
}

View File

@ -1,33 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/***********************
** linux/irqreturn.h **
***********************/
typedef enum irqreturn {
IRQ_NONE = 0,
IRQ_HANDLED = 1,
IRQ_WAKE_THREAD = 2,
} irqreturn_t;
/***********************
** linux/interrupt.h **
***********************/
typedef irqreturn_t (*irq_handler_t)(int, void *);

View File

@ -1,51 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*********************
** linux/jiffies.h **
*********************/
#include <base/fixed_stdint.h>
#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1)
extern unsigned long jiffies;
enum {
JIFFIES_TICK_MS = 1000/HZ,
JIFFIES_TICK_US = 1000*1000/HZ,
JIFFIES_TICK_NS = 1000ULL*1000*1000/HZ,
};
static inline unsigned long msecs_to_jiffies(const genode_uint64_t m) { return m / JIFFIES_TICK_MS; }
static inline unsigned long usecs_to_jiffies(const genode_uint64_t u) { return u / JIFFIES_TICK_US; }
static inline genode_uint64_t jiffies_to_msecs(const unsigned long j) { return j * JIFFIES_TICK_MS; }
static inline genode_uint64_t jiffies_to_nsecs(const unsigned long j) { return (u64)j * JIFFIES_TICK_NS; }
clock_t jiffies_to_clock_t(unsigned long x);
static inline clock_t jiffies_delta_to_clock_t(long delta)
{
return jiffies_to_clock_t(max(0L, delta));
}
#define time_after(a,b) ((long)((b) - (a)) < 0)
#define time_after_eq(a,b) ((long)((a) - (b)) >= 0)
#define time_before(a,b) time_after(b,a)
#define time_before_eq(a,b) time_after_eq(b,a)
#define time_is_after_jiffies(a) time_before(jiffies, a)

View File

@ -1,190 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*********************
** linux/kconfig.h **
*********************/
#define __ARG_PLACEHOLDER_1 0,
#define __take_second_arg(__ignored, val, ...) val
#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
#define __is_defined(x) ___is_defined(x)
#define IS_BUILTIN(option) __is_defined(option)
#define IS_ENABLED(option) IS_BUILTIN(option)
#define IS_REACHABLE(option) IS_BUILTIN(option)
/********************
** linux/kernel.h **
********************/
/*
* Log tags
*/
#define KERN_ALERT "ALERT: "
#define KERN_CRIT "CRTITCAL: "
#define KERN_DEBUG "DEBUG: "
#define KERN_EMERG "EMERG: "
#define KERN_ERR "ERROR: "
#define KERN_INFO "INFO: "
#define KERN_NOTICE "NOTICE: "
#define KERN_WARNING "WARNING: "
#define KERN_WARN "WARNING: "
struct va_format
{
const char *fmt;
va_list *va;
};
static inline int _printk(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
lx_vprintf(fmt, args);
va_end(args);
return 0;
}
/*
* Debug macros
*/
#if DEBUG_LINUX_PRINTK
#define printk _printk
#define vprintk lx_vprintf
#else
#define printk(...)
#define vprintk(...)
#endif
extern void lx_sleep_forever() __attribute__((noreturn));
static inline __printf(1, 2) void panic(const char *fmt, ...) __noreturn;
static inline void panic(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
lx_vprintf(fmt, args);
va_end(args);
lx_printf("\npanic()\n");
lx_sleep_forever();
}
/*
* Bits and types
*/
/* needed by linux/list.h */
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
/* normally provided by linux/stddef.h, needed by linux/list.h */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define max_t(type, x, y) ({ \
type __max1 = (x); \
type __max2 = (y); \
__max1 > __max2 ? __max1: __max2; })
#define max(x, y) ({ \
typeof(x) _max1 = (x); \
typeof(y) _max2 = (y); \
_max1 > _max2 ? _max1 : _max2; })
#define min_t(type, x, y) ({ \
type __min1 = (x); \
type __min2 = (y); \
__min1 < __min2 ? __min1: __min2; })
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
_min1 > _min2 ? _min2 : _min1; })
#define abs(x) ( { \
typeof (x) _x = (x); \
_x < 0 ? -_x : _x; })
#define lower_32_bits(n) ((u32)(n))
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
#define roundup(x, y) ( \
{ \
const typeof(y) __y = y; \
(((x) + (__y - 1)) / __y) * __y; \
})
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#define round_down(x, y) ((x) & ~__round_mask(x, y))
#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)
#define clamp_val(val, min, max) ({ \
typeof(val) __val = (val); \
typeof(val) __min = (min); \
typeof(val) __max = (max); \
__val = __val < __min ? __min: __val; \
__val > __max ? __max: __val; })
#define clamp_t(type, val, min, max) ({ \
type __val = (val); \
type __min = (min); \
type __max = (max); \
__val = __val < __min ? __min: __val; \
__val > __max ? __max: __val; })
#define DIV_ROUND_CLOSEST(x, divisor)( \
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
(((typeof(x))-1) > 0 || \
((typeof(divisor))-1) > 0 || (__x) > 0) ? \
(((__x) + ((__d) / 2)) / (__d)) : \
(((__x) - ((__d) / 2)) / (__d)); \
})
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define BUILD_BUG_ON(condition)
#define _RET_IP_ (unsigned long)__builtin_return_address(0)
void might_sleep();
#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0)
#define INT_MAX ((int)(~0U>>1))
#define UINT_MAX (~0U)
#define INT_MIN (-INT_MAX - 1)
#define USHRT_MAX ((u16)(~0U))
#define LONG_MAX ((long)(~0UL>>1))
#define SHRT_MAX ((s16)(USHRT_MAX>>1))
#define SHRT_MIN ((s16)(-SHRT_MAX - 1))
#define ULONG_MAX (~0UL)
#define swap(a, b) \
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
#define max3(x, y, z) max((typeof(x))max(x, y), z)

View File

@ -1,57 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/******************
** linux/kref.h **
******************/
struct kref { atomic_t refcount; };
void kref_init(struct kref *kref);
void kref_get(struct kref *kref);
int kref_put(struct kref *kref, void (*release) (struct kref *kref));
int kref_get_unless_zero(struct kref *kref);
int kref_put_mutex(struct kref *kref,
void (*release)(struct kref *kref),
struct mutex *lock);
/*********************
** linux/kobject.h **
*********************/
struct kobject
{
struct kset *kset;
struct kobj_type *ktype;
struct kobject *parent;
const char *name;
};
struct kobj_uevent_env
{
char buf[32];
int buflen;
};
struct kobj_uevent_env;
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
void kobject_put(struct kobject *);
const char *kobject_name(const struct kobject *kobj);
char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask);
struct kobject * kobject_create_and_add(const char *, struct kobject *);

View File

@ -1,44 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/********************
** linux/poison.h **
********************/
/*
* In list.h, LIST_POISON1 and LIST_POISON2 are assigned to 'struct list_head
* *' as well as 'struct hlist_node *' pointers. Consequently, C++ compiler
* produces an error "cannot convert... in assignment". To compile 'list.h'
* included by C++ source code, we have to define these macros to the only
* value universally accepted for pointer assigments.h
*/
#ifdef __cplusplus
#define LIST_POISON1 nullptr
#define LIST_POISON2 nullptr
#else
#define LIST_POISON1 ((void *)0x00000100)
#define LIST_POISON2 ((void *)0x00000200)
#endif /* __cplusplus */
#define POISON_INUSE 0x5a
/******************
** linux/list.h **
******************/
#include <linux/list.h>

View File

@ -1,33 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/**********************
** asm-generic/io.h **
**********************/
#define iowmb dma_wmb
#define iormb dma_rmb
#define writeq(value, addr) ({ iowmb(); *(volatile uint64_t *)(addr) = (value); })
#define writel(value, addr) ({ iowmb(); *(volatile uint32_t *)(addr) = (value); })
#define writew(value, addr) ({ iowmb(); *(volatile uint16_t *)(addr) = (value); })
#define writeb(value, addr) ({ iowmb(); *(volatile uint8_t *)(addr) = (value); })
#define readq(addr) ({ uint64_t const r = *(volatile uint64_t *)(addr); iormb(); r; })
#define readl(addr) ({ uint32_t const r = *(volatile uint32_t *)(addr); iormb(); r; })
#define readw(addr) ({ uint16_t const r = *(volatile uint16_t *)(addr); iormb(); r; })
#define readb(addr) ({ uint8_t const r = *(volatile uint8_t *)(addr); iormb(); r; })

View File

@ -1,73 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/******************
** linux/init.h **
******************/
#define __init
#define __exit
#define __devinitconst
#define _SETUP_CONCAT(a, b) __##a##b
#define SETUP_CONCAT(a, b) _SETUP_CONCAT(a, b)
#define __setup(str, fn) static void SETUP_CONCAT(fn, SETUP_SUFFIX)(void *addrs) { fn(addrs); }
#define core_initcall(fn) void core_##fn(void) { fn(); }
#define subsys_initcall(fn) void subsys_##fn(void) { fn(); }
#define pure_initcall(fd) void pure_##fn(void) { printk("PURE_INITCALL"); fn(); }
/********************
** linux/module.h **
********************/
#define EXPORT_SYMBOL(x)
#define EXPORT_SYMBOL_GPL(x)
#define MODULE_LICENSE(x)
#define MODULE_NAME_LEN (64 - sizeof(long))
#define MODULE_ALIAS(name)
#define MODULE_AUTHOR(name)
#define MODULE_DESCRIPTION(desc)
#define MODULE_VERSION(version)
#define THIS_MODULE 0
#define MODULE_FIRMWARE(_firmware)
#define MODULE_DEVICE_TABLE(type, name)
struct module;
#define module_init(fn) int module_##fn(void) { return fn(); }
#define module_exit(fn) void module_exit_##fn(void) { fn(); }
void module_put_and_exit(int);
void module_put(struct module *);
void __module_get(struct module *module);
int try_module_get(struct module *);
/*************************
** linux/moduleparam.h **
*************************/
#define module_param(name, type, perm)
#define module_param_named(name, value, type, perm)
#define module_param_unsafe(name, type, perm)
#define module_param_named_unsafe(name, value, type, perm)
#define MODULE_PARM_DESC(_parm, desc)
#define kparam_block_sysfs_write(name)
#define kparam_unblock_sysfs_write(name)

View File

@ -1,62 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Christian Helmuth
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** linux/mutex.h **
*******************/
struct mutex
{
int state;
void *holder;
void *waiters;
unsigned counter;
unsigned id; /* for debugging */
};
#define DEFINE_MUTEX(mutexname) \
struct mutex lx_mutex_ ## mutexname; \
void lx_mutex_init_ ## mutexname(void) \
{ mutex_init(&lx_mutex_ ## mutexname); }
/*
* Note, you must define a rename for 'mutexname' in lx_emul.h and explicitly
* call the LX_MUTEX_INIT() initializer on startup.
*
* lx_emul.h:
*
* LX_MUTEX_INIT_DECLARE(mutexname)
* #define mutexname LX_MUTEX(mutexname)
*
* lx_emul.cc:
*
* LX_MUTEX_INIT(mutexname);
*/
#define LX_MUTEX(mutexname) lx_mutex_ ## mutexname
#define LX_MUTEX_INIT(mutexname) lx_mutex_init_ ## mutexname()
#define LX_MUTEX_INIT_DECLARE(mutexname) extern void LX_MUTEX_INIT(mutexname)
void mutex_init(struct mutex *m);
void mutex_destroy(struct mutex *m);
void mutex_lock(struct mutex *m);
void mutex_unlock(struct mutex *m);
int mutex_trylock(struct mutex *m);
int mutex_is_locked(struct mutex *m);
/* special case in net/wireless/util.c:1357 */
#define mutex_lock_nested(lock, subclass) mutex_lock(lock)

View File

@ -1,152 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*****************
** linux/pci.h **
*****************/
#include <linux/pci_ids.h>
#include <uapi/linux/pci_regs.h>
enum {
PCI_DMA_BIDIRECTIONAL = 0,
PCI_DMA_TODEVICE,
PCI_DMA_FROMDEVICE,
PCI_DMA_NONE
};
enum { PCI_ANY_ID = ~0U };
typedef enum {
PCI_D0 = 0,
PCI_D1 = 1,
PCI_D2 = 2,
PCI_D3hot = 3,
PCI_D3cold = 4,
} pci_power_t;
/*
* PCI types
*/
struct pci_bus;
struct pci_dev;
struct pci_driver {
char *name;
const struct pci_device_id *id_table;
int (*probe) (struct pci_dev *dev,
const struct pci_device_id *id);
void (*remove) (struct pci_dev *dev);
void (*shutdown) (struct pci_dev *dev);
struct device_driver driver;
};
static inline uint32_t PCI_DEVFN(unsigned slot, unsigned func) {
return ((slot & 0x1f) << 3) | (func & 0x07); }
static inline uint32_t PCI_FUNC(unsigned devfn) { return devfn & 0x07; }
static inline uint32_t PCI_SLOT(unsigned devfn) { return ((devfn) >> 3) & 0x1f; }
int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val);
int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val);
int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val);
static inline
int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val) {
return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); }
static inline
int pci_read_config_word(struct pci_dev *dev, int where, u16 *val) {
return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); }
static inline
int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val) {
return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); }
static inline
int pci_write_config_byte(struct pci_dev *dev, int where, u8 val) {
return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val); }
static inline
int pci_write_config_word(struct pci_dev *dev, int where, u16 val) {
return pci_bus_write_config_word(dev->bus, dev->devfn, where, val); }
static inline
int pci_write_config_dword(struct pci_dev *dev, int where, u32 val) {
return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); }
size_t pci_resource_len(struct pci_dev *dev, unsigned bar);
size_t pci_resource_start(struct pci_dev *dev, unsigned bar);
size_t pci_resource_end(struct pci_dev *dev, unsigned bar);
void pci_dev_put(struct pci_dev *dev);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from);
int pci_enable_device(struct pci_dev *dev);
void pci_disable_device(struct pci_dev *dev);
int pci_register_driver(struct pci_driver *driver);
void pci_unregister_driver(struct pci_driver *driver);
const char *pci_name(const struct pci_dev *pdev);
bool pci_dev_run_wake(struct pci_dev *dev);
unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar);
void pci_set_master(struct pci_dev *dev);
int pci_set_mwi(struct pci_dev *dev);
bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
int pci_find_capability(struct pci_dev *dev, int cap);
struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
int pci_request_regions(struct pci_dev *dev, const char *res_name);
void pci_release_regions(struct pci_dev *dev);
void *pci_ioremap_bar(struct pci_dev *pdev, int bar);
void pci_disable_link_state(struct pci_dev *pdev, int state);
int pci_enable_msi(struct pci_dev *dev);
void pci_disable_msi(struct pci_dev *dev);
#define DEFINE_PCI_DEVICE_TABLE(_table) \
const struct pci_device_id _table[] __devinitconst
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
int pci_register_driver(struct pci_driver *driver);
int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val);
void *pci_get_drvdata(struct pci_dev *pdev);
#define dev_is_pci(d) (1)
int pci_num_vf(struct pci_dev *dev);
/* XXX will this cast ever work? */
#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf((struct pci_dev *)d) : 0))
/**********************
** linux/pci-aspm.h **
**********************/
#define PCIE_LINK_STATE_L0S 1
#define PCIE_LINK_STATE_L1 2
#define PCIE_LINK_STATE_CLKPM 4

View File

@ -1,56 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/****************
** linux/pm.h **
****************/
struct device;
typedef struct pm_message { int event; } pm_message_t;
struct dev_pm_info
{
pm_message_t power_state;
bool is_prepared:1;
bool is_suspended:1;
atomic_t usage_count;
};
struct dev_pm_ops {
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
};
#define PMSG_IS_AUTO(msg) 0
enum { PM_EVENT_AUTO_SUSPEND = 0x402 };
#define PM_EVENT_FREEZE 0x0001
#define PM_EVENT_SUSPEND 0x0002

View File

@ -1,32 +0,0 @@
/*
* \brief Debugging utilities
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
void lx_printf(char const *, ...) __attribute__((format(printf, 1, 2)));
void lx_vprintf(char const *, va_list);
#define lx_printfln(args...) \
do { \
lx_printf(args); \
lx_printf("\n"); \
} while (0);
#define lx_log(doit, msg...) \
do { \
if (doit) { \
lx_printf("%s(): ", __func__); \
lx_printf(msg); \
lx_printf("\n"); \
} \
} while(0)

View File

@ -1,98 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*************************
** linux/scatterlist.h **
*************************/
enum {
SG_MITER_TO_SG = 2,
SG_MITER_FROM_SG = 4,
};
struct scatterlist {
unsigned long page_link;
unsigned int offset;
unsigned int length;
dma_addr_t dma_address;
int last;
};
struct sg_table
{
struct scatterlist *sgl; /* the list */
unsigned int nents; /* number of mapped entries */
unsigned int orig_nents;
};
struct sg_page_iter
{
struct scatterlist *sg;
unsigned int sg_pgoffset; /* page offset within the sg */
unsigned int __nents;
int __pg_advance;
};
struct sg_mapping_iter
{
void *addr;
size_t length;
struct sg_page_iter piter;
};
struct page;
#define sg_is_chain(sg) ((sg)->page_link & 0x01)
#define sg_chain_ptr(sg) \
((struct scatterlist *) ((sg)->page_link & ~0x03))
void sg_init_table(struct scatterlist *, unsigned int);
void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen);
void sg_set_page(struct scatterlist *sg, struct page *page,
unsigned int len, unsigned int offset);
struct page *sg_page(struct scatterlist *sg);
void *sg_virt(struct scatterlist *sg);
struct scatterlist *sg_next(struct scatterlist *);
int sg_nents(struct scatterlist *sg);
size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen);
size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen);
bool __sg_page_iter_next(struct sg_page_iter *piter);
void __sg_page_iter_start(struct sg_page_iter *piter,
struct scatterlist *sglist, unsigned int nents,
unsigned long pgoffset);
#define for_each_sg(sglist, sg, nr, __i) \
for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
#define for_each_sg_page(sglist, piter, nents, pgoffset) \
for (__sg_page_iter_start((piter), (sglist), (nents), (pgoffset)); \
__sg_page_iter_next(piter);)
#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
unsigned int nents, unsigned int flags);
bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset);
bool sg_miter_next(struct sg_mapping_iter *miter);
void sg_miter_stop(struct sg_mapping_iter *miter);

View File

@ -1,35 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** linux/rwsem.h **
*******************/
struct rw_semaphore { int dummy; };
#define DECLARE_RWSEM(name) \
struct rw_semaphore name = { 0 }
#define init_rwsem(sem) do { (void)sem; } while (0)
void down_read(struct rw_semaphore *sem);
void up_read(struct rw_semaphore *sem);
void down_write(struct rw_semaphore *sem);
void up_write(struct rw_semaphore *sem);
int down_write_killable(struct rw_semaphore *);
#define __RWSEM_INITIALIZER(name) { 0 }

View File

@ -1,48 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/**********************
** linux/spinlock.h **
**********************/
typedef struct spinlock { unsigned unused; } spinlock_t;
typedef struct raw_spinlock { unsigned dummy; } raw_spinlock_t;
#define DEFINE_SPINLOCK(name) spinlock_t name
void spin_lock(spinlock_t *lock);
void spin_lock_nested(spinlock_t *lock, int subclass);
void spin_lock_irqsave_nested(spinlock_t *lock, unsigned flags, int subclass);
void spin_unlock(spinlock_t *lock);
void spin_lock_init(spinlock_t *lock);
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
void spin_lock_irqrestore(spinlock_t *lock, unsigned long flags);
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
void spin_lock_irq(spinlock_t *lock);
void spin_unlock_irq(spinlock_t *lock);
void assert_spin_locked(spinlock_t *lock);
void spin_lock_bh(spinlock_t *lock);
void spin_unlock_bh(spinlock_t *lock);
int spin_trylock(spinlock_t *lock);
void raw_spin_lock_init(raw_spinlock_t *);
#define __RAW_SPIN_LOCK_UNLOCKED(raw_spinlock_t) {0}
/****************************
** linux/spinlock_types.h **
****************************/
#define __SPIN_LOCK_UNLOCKED(x) {0}

View File

@ -1,43 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/********************
** linux/string.h **
********************/
#undef memcpy
void *memcpy(void *d, const void *s, size_t n);
void *memset(void *s, int c, size_t n);
int memcmp(const void *, const void *, size_t);
void *memscan(void *addr, int c, size_t size);
char *strcat(char *dest, const char *src);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *cs, const char *ct, size_t count);
char *strcpy(char *to, const char *from);
char *strncpy(char *, const char *, size_t);
char *strchr(const char *, int);
char *strrchr(const char *,int);
size_t strlcat(char *dest, const char *src, size_t n);
size_t strlcpy(char *dest, const char *src, size_t size);
size_t strlen(const char *);
size_t strnlen(const char *, size_t);
char * strsep(char **,const char *);
char *strstr(const char *, const char *);
char *kstrdup(const char *s, gfp_t gfp);
void *kmemdup(const void *src, size_t len, gfp_t gfp);
void *memmove(void *, const void *, size_t);
void * memchr(const void *, int, size_t);

View File

@ -1,112 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/******************
** linux/time.h **
******************/
struct timespec {
__kernel_time_t tv_sec;
long tv_nsec;
};
struct timeval
{
__kernel_time_t tv_sec;
__kernel_suseconds_t tv_usec;
};
struct timespec current_kernel_time(void);
void do_gettimeofday(struct timeval *tv);
#define CURRENT_TIME (current_kernel_time())
enum {
CLOCK_REALTIME = 0,
CLOCK_MONOTONIC = 1,
NSEC_PER_USEC = 1000L,
NSEC_PER_MSEC = 1000000L,
NSEC_PER_SEC = 1000L * NSEC_PER_MSEC,
};
/*******************
** linux/ktime.h **
*******************/
typedef s64 ktime_t;
static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
{
if (cmp1 < cmp2)
return -1;
if (cmp1 > cmp2)
return 1;
return 0;
}
static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
{
return ktime_compare(cmp1, cmp2) < 0;
}
ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
{
return ktime_add_ns(kt, usec * 1000);
}
static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec)
{
return ktime_add_ns(kt, msec * NSEC_PER_MSEC);
}
static inline ktime_t ktime_get(void)
{
return (ktime_t){ (s64)jiffies * (1000/HZ) * NSEC_PER_MSEC /* ns */ };
}
static inline ktime_t ktime_set(const long sec, const unsigned long nsec)
{
return (ktime_t){ (s64)sec * NSEC_PER_SEC + (s64)nsec /* ns */ };
}
static inline ktime_t ktime_add(const ktime_t a, const ktime_t b)
{
return (ktime_t){ a + b /* ns */ };
}
s64 ktime_ms_delta(const ktime_t, const ktime_t);
s64 ktime_us_delta(const ktime_t later, const ktime_t earlier);
static inline struct timeval ktime_to_timeval(const ktime_t kt)
{
struct timeval tv;
tv.tv_sec = kt / NSEC_PER_SEC;
tv.tv_usec = (kt - (tv.tv_sec * NSEC_PER_SEC)) / NSEC_PER_USEC;
return tv;
}
ktime_t ktime_get_real(void);
ktime_t ktime_sub(const ktime_t, const ktime_t);
ktime_t ktime_get_monotonic_offset(void);
ktime_t ktime_get_boottime(void);

View File

@ -1,82 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Stefan Kalkowski
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** linux/timer.h **
*******************/
struct tvec_base;
extern struct tvec_base boot_tvec_bases; /* needed by 'dwc_common_linux.c' */
struct timer_list
{
unsigned long expires;
void (*function)(struct timer_list*);
unsigned int flags;
/*
* For compatibility with 4.4.3 drivers, the 'data' member is kept and
* passed as argument to the callback function. Since the 4.16.3 callback
* function interface has a 'timer_list' pointer as argument, the 'data'
* member points to the 'timer_list' object itself when set up with the
* 'timer_setup()' function.
*/
unsigned long data;
};
int mod_timer(struct timer_list *timer, unsigned long expires);
int del_timer(struct timer_list * timer);
void timer_setup(struct timer_list *timer,
void (*callback)(struct timer_list *), unsigned int flags);
int timer_pending(const struct timer_list * timer);
unsigned long round_jiffies(unsigned long j);
unsigned long round_jiffies_relative(unsigned long j);
unsigned long round_jiffies_up(unsigned long j);
static inline void add_timer(struct timer_list *timer) {
mod_timer(timer, timer->expires); }
static inline int del_timer_sync(struct timer_list * timer) {
return del_timer(timer); }
/*********************
** linux/hrtimer.h **
*********************/
enum hrtimer_mode {
HRTIMER_MODE_ABS = 0,
HRTIMER_MODE_REL = 0x1,
HRTIMER_MODE_REL_PINNED = 0x03,
};
enum hrtimer_restart {
HRTIMER_NORESTART,
HRTIMER_RESTART,
};
struct hrtimer
{
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer *data;
void *timer;
};
int hrtimer_start_range_ns(struct hrtimer *, ktime_t,
unsigned long, const enum hrtimer_mode);
void hrtimer_init(struct hrtimer *, clockid_t, enum hrtimer_mode);
int hrtimer_cancel(struct hrtimer *);
bool hrtimer_active(const struct hrtimer *);

View File

@ -1,110 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** linux/types.h **
*******************/
typedef genode_int8_t int8_t;
typedef genode_uint8_t uint8_t;
typedef genode_int16_t int16_t;
typedef genode_uint16_t uint16_t;
typedef genode_int32_t int32_t;
typedef genode_uint32_t uint32_t;
typedef __SIZE_TYPE__ size_t;
typedef genode_int64_t int64_t;
typedef genode_uint64_t uint64_t;
typedef uint32_t uint;
typedef unsigned long ulong;
typedef int8_t s8;
typedef uint8_t u8;
typedef int16_t s16;
typedef uint16_t u16;
typedef int32_t s32;
typedef uint32_t u32;
typedef int64_t s64;
typedef uint64_t u64;
typedef int8_t __s8;
typedef uint8_t __u8;
typedef int16_t __s16;
typedef uint16_t __u16;
typedef int32_t __s32;
typedef uint32_t __u32;
typedef int64_t __s64;
typedef uint64_t __u64;
struct list_head {
struct list_head *next, *prev;
};
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#ifndef __cplusplus
typedef _Bool bool;
enum { true = 1, false = 0 };
#endif /* __cplusplus */
#ifndef NULL
#ifdef __cplusplus
#define NULL nullptr
#else
#define NULL ((void *)0)
#endif /* __cplusplus */
#endif /* NULL */
typedef unsigned gfp_t;
typedef unsigned long dma_addr_t;
typedef unsigned long pgoff_t;
typedef long long loff_t;
typedef long ssize_t;
typedef unsigned long uintptr_t;
typedef int dev_t;
typedef size_t resource_size_t;
typedef long off_t;
typedef int pid_t;
typedef unsigned fmode_t;
typedef u32 uid_t;
typedef u32 gid_t;
typedef unsigned kuid_t;
typedef unsigned kgid_t;
typedef size_t __kernel_size_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef unsigned short umode_t;
typedef __u16 __be16;
typedef __u32 __be32;
typedef long clock_t;
#ifndef __cplusplus
typedef u16 wchar_t;
#endif
/*
* XXX 'mode_t' is 'unsigned int' on x86_64
*/
typedef unsigned short mode_t;
typedef unsigned slab_flags_t;

View File

@ -1,237 +0,0 @@
/*
* \brief Linux kernel API
* \author Norman Feske
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2014-08-21
*
* Based on the prototypes found in the Linux kernel's 'include/'.
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/***********************
** linux/workqueue.h **
***********************/
enum {
WQ_UNBOUND = 1 << 1,
WQ_FREEZABLE = 1 << 2,
WQ_MEM_RECLAIM = 1 << 3,
WQ_HIGHPRI = 1 << 4,
WQ_CPU_INTENSIVE = 1 << 5,
};
struct work_struct;
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
atomic_long_t data;
work_func_t func;
struct list_head entry;
struct workqueue_struct *wq;
};
struct workqueue_struct { void *task; };
struct delayed_work {
struct timer_list timer;
struct work_struct work;
struct workqueue_struct *wq;
};
bool cancel_work_sync(struct work_struct *work);
bool cancel_delayed_work_sync(struct delayed_work *work);
bool cancel_delayed_work(struct delayed_work *dwork);
int schedule_delayed_work(struct delayed_work *work, unsigned long delay);
int schedule_work(struct work_struct *work);
void flush_scheduled_work(void);
bool flush_work(struct work_struct *work);
bool flush_work_sync(struct work_struct *work);
void delayed_work_timer_fn(struct timer_list *t);
#define PREPARE_WORK(_work, _func) \
do { (_work)->func = (_func); } while (0)
#define PREPARE_DELAYED_WORK(_work, _func) \
PREPARE_WORK(&(_work)->work, (_func))
#define __INIT_WORK(_work, _func, on_stack) \
do { \
INIT_LIST_HEAD(&(_work)->entry); \
PREPARE_WORK((_work), (_func)); \
} while (0)
#define INIT_WORK(_work, _func)\
do { __INIT_WORK((_work), (_func), 0); } while (0)
#define INIT_DELAYED_WORK(_work, _func) \
do { \
INIT_WORK(&(_work)->work, (_func)); \
timer_setup(&(_work)->timer, delayed_work_timer_fn, 0); \
} while (0)
/* dummy for queue_delayed_work call in storage/usb.c */
#define system_freezable_wq 0
struct workqueue_struct *create_singlethread_workqueue(const char *name);
struct workqueue_struct *alloc_ordered_workqueue(const char *fmt, unsigned int flags, ...) __printf(1, 3);
struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags,
int max_active, ...) __printf(1, 4);
void destroy_workqueue(struct workqueue_struct *wq);
void flush_workqueue(struct workqueue_struct *wq);
bool queue_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long);
bool flush_delayed_work(struct delayed_work *dwork);
bool queue_work(struct workqueue_struct *wq, struct work_struct *work);
struct work_struct *current_work(void);
void drain_workqueue(struct workqueue_struct *);
#define DECLARE_DELAYED_WORK(n, f) \
struct delayed_work n = { .work = { .func = f }, .timer = { .function = 0 } }
bool mod_delayed_work(struct workqueue_struct *, struct delayed_work *,
unsigned long);
static inline struct delayed_work *to_delayed_work(struct work_struct *work)
{
return container_of(work, struct delayed_work, work);
}
extern struct workqueue_struct *system_wq;
extern struct workqueue_struct *system_unbound_wq;
extern struct workqueue_struct *system_long_wq;
enum {
WORK_STRUCT_STATIC = 0,
WORK_STRUCT_COLOR_SHIFT = 4,
WORK_STRUCT_COLOR_BITS = 4,
WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT + WORK_STRUCT_COLOR_BITS,
WORK_OFFQ_FLAG_BASE = WORK_STRUCT_FLAG_BITS,
WORK_OFFQ_FLAG_BITS = 1,
WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,
WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT,
WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31,
WORK_OFFQ_POOL_NONE = (1LU << WORK_OFFQ_POOL_BITS) - 1,
WORK_STRUCT_NO_POOL = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT,
};
#define WORK_DATA_STATIC_INIT() \
ATOMIC_LONG_INIT(WORK_STRUCT_NO_POOL | WORK_STRUCT_STATIC)
#define __WORK_INIT_LOCKDEP_MAP(n, k)
#define __WORK_INITIALIZER(n, f) { \
.data = WORK_DATA_STATIC_INIT(), \
.entry = { &(n).entry, &(n).entry }, \
.func = (f), \
__WORK_INIT_LOCKDEP_MAP(#n, &(n)) \
}
#define DECLARE_WORK(n, f) \
struct work_struct n = __WORK_INITIALIZER(n, f)
/******************
** linux/wait.h **
******************/
typedef struct wait_queue_entry wait_queue_entry_t;
typedef int (*wait_queue_func_t)(wait_queue_entry_t *, unsigned, int, void *);
typedef struct wait_queue_head {
spinlock_t lock;
void *list;
/*
* Reserve memory for a 'Wait_list' object, which needs to be
* freed together with the 'wait_queue_head_t' object.
*
* This implementation relies on the currently given fact that
* 'Wait_list' does not need to have a destructor called.
*/
char wait_list_reserved[8];
} wait_queue_head_t;
struct wait_queue_entry {
unsigned int flags;
void *private;
wait_queue_func_t func;
struct list_head entry;
};
void init_wait_entry(struct wait_queue_entry *, int);
#define DEFINE_WAIT(name) \
wait_queue_entry_t name;
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { 0 }
#define DECLARE_WAITQUEUE(name, tsk) \
wait_queue_entry_t name
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#define DEFINE_WAIT_FUNC(name, function) \
wait_queue_entry_t name
/* simplified signature */
void __wake_up(wait_queue_head_t *q, bool all);
#define wake_up(x) __wake_up(x, false)
#define wake_up_all(x) __wake_up(x, true)
#define wake_up_all_locked(x) __wake_up(x, true)
#define wake_up_interruptible(x) __wake_up(x, false)
#define wake_up_interruptible_all(x) __wake_up(x, true)
void init_waitqueue_head(wait_queue_head_t *);
int waitqueue_active(wait_queue_head_t *);
/* void wake_up_interruptible(wait_queue_head_t *); */
void wake_up_interruptible_sync_poll(wait_queue_head_t *, int);
void wake_up_interruptible_poll(wait_queue_head_t *, int);
void prepare_to_wait(wait_queue_head_t *, wait_queue_entry_t *, int);
void prepare_to_wait_exclusive(wait_queue_head_t *, wait_queue_entry_t *, int);
void finish_wait(wait_queue_head_t *, wait_queue_entry_t *);
int autoremove_wake_function(wait_queue_entry_t *, unsigned, int, void *);
void add_wait_queue(wait_queue_head_t *, wait_queue_entry_t *);
void add_wait_queue_exclusive(wait_queue_head_t *, wait_queue_entry_t *);
void remove_wait_queue(wait_queue_head_t *, wait_queue_entry_t *);
/* our wait event implementation - it's okay as value */
void ___wait_event(wait_queue_head_t*);
#define __wait_event(wq) ___wait_event(&wq)
#define _wait_event(wq, condition) while (!(condition)) { __wait_event(wq); }
#define wait_event(wq, condition) ({ _wait_event(wq, condition); })
#define wait_event_interruptible(wq, condition) ({ _wait_event(wq, condition); 0; })
#define wait_event_interruptible_locked(wq, condition) ({ _wait_event(wq, condition); 0; })
#define _wait_event_timeout(wq, condition, timeout) \
({ int res = 1; \
prepare_to_wait(&wq, 0, 0); \
while (1) { \
if ((condition) || !res) { \
break; \
} \
res = schedule_timeout(timeout); \
} \
finish_wait(&wq, 0); \
res; \
})
#define wait_event_timeout(wq, condition, timeout) \
({ \
int ret = _wait_event_timeout(wq, (condition), timeout); \
ret; \
})

View File

@ -1,84 +0,0 @@
/*
* \brief Address-to-page mapping helper
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__ADDR_TO_PAGE_MAPPING_H_
#define _LX_KIT__ADDR_TO_PAGE_MAPPING_H_
/* Linux emulation environment includes */
#include <legacy/lx_kit/internal/list.h>
#include <legacy/lx_kit/malloc.h>
namespace Lx { class Addr_to_page_mapping; }
class Lx::Addr_to_page_mapping : public Lx_kit::List<Addr_to_page_mapping>::Element
{
private:
unsigned long _addr { 0 };
struct page *_page { 0 };
Genode::Ram_dataspace_capability _cap;
static Genode::List<Addr_to_page_mapping> *_list()
{
static Genode::List<Addr_to_page_mapping> _l;
return &_l;
}
public:
static void insert(struct page *page,
Genode::Ram_dataspace_capability cap)
{
Addr_to_page_mapping *m = (Addr_to_page_mapping*)
Lx::Malloc::mem().alloc(sizeof (Addr_to_page_mapping));
m->_addr = (unsigned long)page->addr;
m->_page = page;
m->_cap = cap;
_list()->insert(m);
}
static Genode::Ram_dataspace_capability remove(struct page *page)
{
Genode::Ram_dataspace_capability cap;
Addr_to_page_mapping *mp = 0;
for (Addr_to_page_mapping *m = _list()->first(); m; m = m->next())
if (m->_page == page)
mp = m;
if (mp) {
cap = mp->_cap;
_list()->remove(mp);
Lx::Malloc::mem().free(mp);
}
return cap;
}
static struct page* find_page(unsigned long addr)
{
for (Addr_to_page_mapping *m = _list()->first(); m; m = m->next())
if (m->_addr == addr)
return m->_page;
return 0;
}
static struct page* find_page_by_paddr(unsigned long paddr);
};
#endif /* _LX_KIT__ADDR_TO_PAGE_MAPPING_H_ */

View File

@ -1,35 +0,0 @@
/*
* \brief Back-end allocator
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__BACKEND_ALLOC_H_
#define _LX_KIT__BACKEND_ALLOC_H_
/* Linux emulation environment includes */
#include <legacy/lx_kit/types.h>
namespace Lx {
using namespace Genode;
Ram_dataspace_capability backend_alloc(addr_t size, Cache);
void backend_free(Ram_dataspace_capability cap);
addr_t backend_dma_addr(Ram_dataspace_capability);
}
#endif /* _LX_KIT__BACKEND_ALLOC_H_ */

View File

@ -1,49 +0,0 @@
/*
* \brief Helper class to make the Genode Env globally available
* \author Sebastian Sumpf
* \date 2016-06-21
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__ENV_H_
#define _LX_KIT__ENV_H_
#include <base/attached_rom_dataspace.h>
#include <base/env.h>
#include <base/heap.h>
#include <util/reconstructible.h>
namespace Lx_kit {
class Env;
Env &env();
Env &construct_env(Genode::Env &env);
}
class Lx_kit::Env
{
private:
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Genode::Attached_rom_dataspace _config { _env, "config" };
public:
Env(Genode::Env &env) : _env(env) { }
Genode::Env &env() { return _env; }
Genode::Heap &heap() { return _heap; }
Genode::Attached_rom_dataspace &config_rom() { return _config; }
Genode::Ram_allocator &ram() { return _env.ram(); }
Genode::Region_map &rm() { return _env.rm(); }
};
#endif /* _LX_KIT__ENV_H_ */

View File

@ -1,87 +0,0 @@
/*
* \brief I/O port access helper
* \author Sebastian Sumpf
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__INTERNAL__IO_PORT_H_
#define _LX_KIT__INTERNAL__IO_PORT_H_
/* Genode includes */
#include <util/reconstructible.h>
#include <io_port_session/client.h>
namespace Lx { class Io_port; }
class Lx::Io_port
{
private:
unsigned _base = 0;
unsigned _size = 0;
Genode::Io_port_session_capability _cap;
Genode::Constructible<Genode::Io_port_session_client> _port;
bool _valid(unsigned port) {
return _cap.valid() && port >= _base && port < _base + _size; }
public:
~Io_port()
{
if (_cap.valid())
_port.destruct();
}
void session(unsigned base, unsigned size, Genode::Io_port_session_capability cap)
{
_base = base;
_size = size;
_cap = cap;
_port.construct(_cap);
}
template<typename POD>
bool out(unsigned port, POD val)
{
if (!_valid(port))
return false;
switch (sizeof(POD)) {
case 1: _port->outb(port, val); break;
case 2: _port->outw(port, val); break;
case 4: _port->outl(port, val); break;
default:
return false;
}
return true;
}
template<typename POD>
bool in(unsigned port, POD *val)
{
if (!_valid(port))
return false;
switch (sizeof(POD)) {
case 1: *val = _port->inb(port); break;
case 2: *val = _port->inw(port); break;
case 4: *val = _port->inl(port); break;
default:
return false;
}
return true;
}
};
#endif /* _LX_KIT__INTERNAL__IO_PORT_H_ */

View File

@ -1,102 +0,0 @@
/*
* \brief Slightly improved list
* \author Christian Helmuth
* \date 2014-09-25
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__INTERNAL__LIST_H_
#define _LX_KIT__INTERNAL__LIST_H_
#include <util/list.h>
namespace Lx_kit {
template <typename> class List;
template <typename> class List_element;
}
template <typename LT>
class Lx_kit::List : private Genode::List<LT>
{
private:
typedef Genode::List<LT> Base;
public:
using Base::Element;
void append(LT const *le)
{
LT *at = nullptr;
for (LT *l = first(); l; l = l->next())
at = l;
Base::insert(le, at);
}
void prepend(LT const *le)
{
Base::insert(le);
}
void insert_before(LT const *le, LT const *at)
{
if (at == first()) {
prepend(le);
return;
} else if (!at) {
append(le);
return;
}
for (LT *l = first(); l; l = l->next())
if (l->next() == at)
at = l;
Base::insert(le, at);
}
/****************************
** Genode::List interface **
****************************/
LT *first() { return Base::first(); }
LT const *first() const { return Base::first(); }
void insert(LT const *le, LT const *at = 0)
{
Base::insert(le, at);
}
void remove(LT const *le)
{
Base::remove(le);
}
};
template <typename T>
class Lx_kit::List_element : public Lx_kit::List<List_element<T> >::Element
{
private:
T *_object;
public:
List_element(T *object) : _object(object) { }
T *object() const { return _object; }
};
#endif /* _LX_KIT__INTERNAL__LIST_H_ */

View File

@ -1,71 +0,0 @@
/*
* \brief Slab allocator using our back-end allocator
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__INTERAL__SLAB_ALLOC_H_
#define _LX_KIT__INTERAL__SLAB_ALLOC_H_
/* Genode includes */
#include <base/slab.h>
#include <util/misc_math.h>
/* Linux emulation environment includes */
#include <legacy/lx_kit/internal/slab_backend_alloc.h>
#include <legacy/lx_kit/types.h>
namespace Lx { class Slab_alloc; }
class Lx::Slab_alloc : public Genode::Slab
{
public:
typedef Genode::size_t size_t;
private:
size_t const _object_size;
/*
* Each slab block in the slab contains about 8 objects (slab entries)
* as proposed in the paper by Bonwick and block sizes are multiples of
* page size.
*/
static size_t _calculate_block_size(size_t object_size)
{
size_t block_size = 16*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Slab_backend_alloc &allocator)
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
void *alloc_element()
{
return Slab::try_alloc(_object_size).convert<void *>(
[&] (void *ptr) { return ptr; },
[&] (Alloc_error) { return (void *)nullptr; });
}
void free(void *ptr)
{
Slab::free(ptr, _object_size);
}
};
#endif /* _LX_KIT__INTERAL__SLAB_ALLOC_H_ */

View File

@ -1,64 +0,0 @@
/*
* \brief Back-end allocator for Genode's slab allocator
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__INTERAL__SLAB_BACKEND_ALLOC_H_
#define _LX_KIT__INTERAL__SLAB_BACKEND_ALLOC_H_
/* Genode includes */
#include <base/allocator_avl.h>
/* Linux emulation environment includes */
#include <legacy/lx_kit/types.h>
namespace Lx {
using Lx_kit::addr_t;
class Slab_backend_alloc;
}
class Lx::Slab_backend_alloc : public Genode::Allocator
{
public:
/**
* Allocate
*/
virtual Alloc_result try_alloc(Genode::size_t size) = 0;
virtual void free(void *addr) = 0;
/**
* Return phys address for given virtual addr.
*/
virtual addr_t phys_addr(addr_t addr) = 0;
/**
* Translate given physical address to virtual address
*
* \return virtual address, or 0 if no translation exists
*/
virtual addr_t virt_addr(addr_t phys) = 0;
virtual addr_t start() const = 0;
virtual addr_t end() const = 0;
static Slab_backend_alloc &mem();
static Slab_backend_alloc &dma();
};
#endif /* _LX_KIT__INTERAL__SLAB_BACKEND_ALLOC_H_ */

View File

@ -1,255 +0,0 @@
/*
* \brief Lx::Task represents a cooperatively scheduled thread of control
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__INTERNAL__TASK_H_
#define _LX_KIT__INTERNAL__TASK_H_
/* Genode includes */
#include <base/log.h>
#include <base/thread.h>
#include <base/sleep.h>
/* Linux emulation environment includes */
#include <legacy/lx_kit/internal/list.h>
#include <lx_kit/arch_execute.h>
namespace Lx {
class Task;
}
/**
* Allows pseudo-parallel execution of functions
*/
class Lx::Task : public Lx_kit::List<Lx::Task>::Element
{
public:
/**
* TODO generalize - higher is more important
*/
enum Priority { PRIORITY_0, PRIORITY_1, PRIORITY_2, PRIORITY_3 };
/**
* Runtime state
*
* INIT
* |
* [run]
* v
* BLOCKED <--[block]--- RUNNING ---[mutex_block]--> MUTEX_BLOCKED
* --[unblock]-> <-[mutex_unblock]--
*
* Transitions between BLOCKED and MUTEX_BLOCKED are not possible.
*/
enum State { STATE_INIT, STATE_RUNNING, STATE_BLOCKED, STATE_MUTEX_BLOCKED, STATE_WAIT_BLOCKED };
/**
* List element type
*/
typedef Lx_kit::List_element<Lx::Task> List_element;
/**
* List type
*/
typedef Lx_kit::List<List_element> List;
private:
bool verbose = false;
State _state = STATE_INIT;
/* sub-classes may overwrite the runnable condition */
virtual bool _runnable() const
{
switch (_state) {
case STATE_INIT: return true;
case STATE_RUNNING: return true;
case STATE_BLOCKED: return false;
case STATE_MUTEX_BLOCKED: return false;
case STATE_WAIT_BLOCKED: return false;
}
Genode::error("state ", (int)_state, " not handled by switch");
Genode::sleep_forever();
}
void *_stack = nullptr; /* stack pointer */
jmp_buf _env; /* execution state */
jmp_buf _saved_env; /* saved state of thread calling run() */
Priority _priority;
Scheduler &_scheduler; /* scheduler this task is attached to */
void (*_func)(void *); /* function to call*/
void *_arg; /* argument for function */
char const *_name; /* name of task */
List_element _mutex_le { this }; /* list element for mutex_blocked state */
List *_wait_list { 0 };
List_element _wait_le { this };
bool _wait_le_enqueued { false };
public:
Task(void (*func)(void*), void *arg, char const *name,
Priority priority, Scheduler &scheduler);
virtual ~Task();
State state() const { return _state; }
Priority priority() const { return _priority; }
void wait_enqueue(List *list)
{
if (_wait_le_enqueued && _wait_list == list) return;
if (_wait_le_enqueued) {
Genode::error(this, " already queued in ", _wait_list);
Genode::sleep_forever();
}
_wait_le_enqueued = true;
_wait_list = list;
_wait_list->append(&_wait_le);
}
void wait_dequeue(List *list)
{
if (!_wait_le_enqueued) {
Genode::error(this, " not queued");
Genode::sleep_forever();
}
if (_wait_list != list) {
Genode::error("especially not in list ", list);
Genode::sleep_forever();
}
_wait_list->remove(&_wait_le);
_wait_list = 0;
_wait_le_enqueued = false;
}
/*******************************
** Runtime state transitions **
*******************************/
void block()
{
if (_state == STATE_RUNNING) {
_state = STATE_BLOCKED;
}
}
void unblock()
{
if (_state == STATE_BLOCKED) {
_state = STATE_RUNNING;
}
}
void mutex_block(List *list)
{
if (_state == STATE_RUNNING) {
_state = STATE_MUTEX_BLOCKED;
list->append(&_mutex_le);
}
}
void mutex_unblock(List *list)
{
if (_state == STATE_MUTEX_BLOCKED) {
_state = STATE_RUNNING;
list->remove(&_mutex_le);
}
}
/**
* Run task until next preemption point
*
* \return true if run, false if not runnable
*/
bool run()
{
if (!_runnable())
return false;
/*
* Save the execution environment. The scheduled task returns to this point
* after execution, i.e., at the next preemption point.
*/
if (_setjmp(_saved_env))
return true;
if (_state == STATE_INIT) {
/* setup execution environment and call task's function */
_state = STATE_RUNNING;
Genode::Thread *th = Genode::Thread::myself();
enum { STACK_SIZE = 32 * 1024 }; /* FIXME make stack size configurable */
_stack = th->alloc_secondary_stack(_name, STACK_SIZE);
/* switch stack and call '_func(_arg)' */
arch_execute(_stack, (void *)_func, _arg);
} else {
/* restore execution environment */
_longjmp(_env, 1);
}
/* never reached */
Genode::error("unexpected return of task");
Genode::sleep_forever();
}
/**
* Request scheduling (of other tasks)
*
* Note, this task may not be blocked when calling schedule() depending
* on the use case.
*/
void schedule()
{
/*
* Save the execution environment. The task will resume from here on next
* schedule.
*/
if (_setjmp(_env))
return;
/* return to thread calling run() */
_longjmp(_saved_env, 1);
}
/**
* Shortcut to enter blocking state and request scheduling
*/
void block_and_schedule()
{
block();
schedule();
}
/**
* Return the name of the task (mainly for debugging purposes)
*/
char const *name() { return _name; }
};
#endif /* _LX_KIT__INTERNAL__TASK_H_ */

View File

@ -1,54 +0,0 @@
/*
* \brief Signal context for IRQ's
* \author Josef Soentgen
* \author Christian Helmuth
* \author Stefan Kalkowski
* \date 2014-10-14
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__IRQ_H_
#define _LX_KIT__IRQ_H_
/* Genode includes */
#include <base/allocator.h>
#include <irq_session/capability.h>
namespace Lx { class Irq; }
class Lx::Irq
{
public:
static Irq &irq(Genode::Entrypoint *ep = nullptr,
Genode::Allocator *alloc = nullptr);
/**
* Request an IRQ
*/
virtual void request_irq(Genode::Irq_session_capability cap,
unsigned int irq,
irq_handler_t handler, void *dev_id,
irq_handler_t thread_fn = 0) = 0;
virtual void inject_irq(unsigned int irq) = 0;
/**
* Disable an IRQ
*/
virtual void disable_irq(unsigned int irq) = 0;
/**
* Enable an IRQ
*/
virtual void enable_irq(unsigned int irq) = 0;
};
#endif /* _LX_KIT__IRQ_H_ */

View File

@ -1,78 +0,0 @@
/*
* \brief Linux kernel memory allocator
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__MALLOC_H_
#define _LX_KIT__MALLOC_H_
/* Linux emulation environment includes */
#include <legacy/lx_kit/types.h>
#include <legacy/lx_kit/internal/slab_alloc.h>
#include <legacy/lx_kit/internal/slab_backend_alloc.h>
namespace Lx {
class Malloc;
void malloc_init(Genode::Env &env, Genode::Allocator &md_alloc);
}
class Lx::Malloc : public Genode::Allocator
{
public:
typedef Genode::size_t size_t;
enum { MAX_SIZE_LOG2 = 16 /* 64 KiB */ };
/**
* Alloc in slabs
*/
virtual void *malloc(Genode::size_t size, int align = 0, Genode::addr_t *phys = 0) = 0;
virtual void free(void const *a) = 0;
virtual void *alloc_large(size_t size) = 0;
virtual void free_large(void *ptr) = 0;
virtual size_t size(void const *a) = 0;
virtual Genode::addr_t phys_addr(void *a) = 0;
virtual Genode::addr_t virt_addr(Genode::addr_t phys) = 0;
/**
* Belongs given address to this allocator
*/
virtual bool inside(addr_t const addr) const = 0;
/**
* Genode alllocator interface
*/
bool need_size_for_free() const override { return false; }
size_t overhead(size_t size) const override { return 0; }
Alloc_result try_alloc(size_t size) override { return malloc(size); }
void free(void *addr, size_t size) override { free(addr); }
static Malloc &mem();
static Malloc &dma();
};
#endif /* _LX_KIT__MALLOC_H_ */

View File

@ -1,33 +0,0 @@
/*
* \brief Representation of a locally-mapped MMIO range
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__MAPPED_IO_MEM_RANGE_H_
#define _LX_KIT__MAPPED_IO_MEM_RANGE_H_
/* Genode includes */
#include <dataspace/capability.h>
/* Linux emulation environment includes */
#include <legacy/lx_kit/types.h>
namespace Lx {
using namespace Genode;
void *ioremap(addr_t, unsigned long, Cache);
void iounmap(volatile void*);
Dataspace_capability ioremap_lookup(addr_t, Genode::size_t);
}
#endif /* _LX_KIT__MAPPED_IO_MEM_RANGE_H_ */

View File

@ -1,27 +0,0 @@
/*
* \brief PCI backend
* \author Josef Soentgen
* \date 2017-02-12
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__PCI_H_
#define _LX_KIT__PCI_H_
/* Genode includes */
#include <base/env.h>
#include <base/allocator.h>
namespace Lx {
void pci_init(Genode::Env&, Genode::Ram_allocator&, Genode::Allocator&);
}
#endif /* _LX_KIT__PCI_H_ */

View File

@ -1,78 +0,0 @@
/*
* \brief Scheduler for executing Lx::Task objects
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__SCHEDULER_H_
#define _LX_KIT__SCHEDULER_H_
/* Genode includes */
#include <base/env.h>
namespace Lx {
class Task;
class Scheduler;
/**
* Return singleton instance of the scheduler
*
* Implementation must be provided by the driver.
*/
Scheduler &scheduler(Genode::Env *env = nullptr);
}
class Lx::Scheduler
{
public:
/**
* Return currently scheduled task
*/
virtual Task *current() = 0;
/**
* Return true if a task is currently running
*/
virtual bool active() const = 0;
/**
* Add new task to the present list
*/
virtual void add(Task *task) = 0;
/**
* Remove a task
*/
virtual void remove(Task *task) = 0;
/**
* Schedule all present tasks
*
* Returns if no task is runnable.
*/
virtual void schedule() = 0;
/**
* Log current state of tasks in present list (debug)
*
* Log lines are prefixed with 'prefix'.
*/
virtual void log_state(char const *prefix) = 0;
};
#include <legacy/lx_kit/internal/task.h>
#endif /* _LX_KIT__SCHEDULER_H_ */

View File

@ -1,93 +0,0 @@
/*
* \brief Timer
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__TIMER_H_
#define _LX_KIT__TIMER_H_
/* Genode includes */
#include <base/entrypoint.h>
#include <base/allocator.h>
namespace Lx {
class Timer;
/**
* Return singleton instance of timer
*
* \param ep entrypoint used handle timeout signals,
* to be specified at the first call of the function,
* which implicitly initializes the timer
* \param jiffies_ptr pointer to jiffies counter to be periodically
* updated
*/
Timer &timer(Genode::Env *env = nullptr,
Genode::Entrypoint *ep = nullptr,
Genode::Allocator *md_alloc = nullptr,
unsigned long *jiffies_ptr = nullptr);
void timer_update_jiffies();
}
class Lx::Timer
{
public:
enum Type { LIST, HR };
/**
* Add new linux timer
*/
virtual void add(void *timer, Type type) = 0;
/**
* Delete linux timer
*/
virtual int del(void *timer) = 0;
/**
* Initial scheduling of linux timer
*/
virtual int schedule(void *timer, unsigned long expires) = 0;
/**
* Schedule next linux timer
*/
virtual void schedule_next() = 0;
/**
* Check if the timer is currently pending
*/
virtual bool pending(void const *timer) = 0;
/**
* Check if the timer is already present
*/
virtual bool find(void const *timer) const = 0;
/**
* Update jiffie counter
*/
virtual void update_jiffies() = 0;
/**
* Suspend calling thread
*/
virtual void usleep(Genode::uint64_t us) = 0;
};
#endif /* _LX_KIT__TIMER_H_ */

View File

@ -1,25 +0,0 @@
/*
* \brief Linux kit types
* \author Josef Soentgen
* \date 2016-03-18
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__TYPES_H_
#define _LX_KIT__TYPES_H_
/* Genode includes */
#include <base/stdint.h>
namespace Lx_kit {
typedef Genode::size_t size_t;
typedef Genode::addr_t addr_t;
}
#endif /* _LX_KIT__TYPES_H_ */

View File

@ -1,177 +0,0 @@
/*
* \brief USB URB implementation
* \author Stefan Kalkowski
* \date 2018-06-13
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__USB_H_
#define _LX_KIT__USB_H_
/* Genode includes */
#include <usb_session/client.h>
#include <util/string.h>
class Urb : public Usb::Completion
{
protected:
Usb::Session_client & _usb;
urb & _urb;
Usb::Packet_descriptor _packet {
_usb.alloc_packet(_urb.transfer_buffer_length) };
bool _completed { false };
public:
Urb(Usb::Session_client &usb, urb & urb) : _usb(usb), _urb(urb)
{
_packet.completion = this;
switch(usb_pipetype(_urb.pipe)) {
case PIPE_INTERRUPT:
{
struct usb_host_endpoint *ep =
usb_pipe_endpoint(_urb.dev, _urb.pipe);
_packet.type = Usb::Packet_descriptor::IRQ;
_packet.transfer.polling_interval = _urb.interval;
_packet.transfer.ep = ep->desc.bEndpointAddress;
return;
}
case PIPE_CONTROL:
{
usb_ctrlrequest * ctrl = (usb_ctrlrequest *)
_urb.setup_packet;
_packet.type = Usb::Packet_descriptor::CTRL;
_packet.control.request = ctrl->bRequest;
_packet.control.request_type = ctrl->bRequestType;
_packet.control.value = ctrl->wValue;
_packet.control.index = ctrl->wIndex;
if (!(ctrl->bRequestType & USB_DIR_IN))
Genode::memcpy(_usb.source()->packet_content(_packet),
_urb.transfer_buffer, _urb.transfer_buffer_length);
return;
}
case PIPE_BULK:
{
struct usb_host_endpoint *ep =
usb_pipe_endpoint(_urb.dev, _urb.pipe);
_packet.type = Usb::Packet_descriptor::BULK;
_packet.transfer.ep = ep->desc.bEndpointAddress;
if (usb_pipeout(_urb.pipe))
Genode::memcpy(_usb.source()->packet_content(_packet),
_urb.transfer_buffer, _urb.transfer_buffer_length);
return;
}
default:
Genode::error("unknown URB requested");
};
}
~Urb()
{
if (!_completed)
_usb.source()->release_packet(_packet);
}
void send()
{
_usb.source()->submit_packet(_packet);
}
void complete(Usb::Packet_descriptor & packet) override
{
if (packet.succeded) {
bool ctrl = (usb_pipetype(_urb.pipe) == PIPE_CONTROL);
_urb.status = 0;
_urb.actual_length = ctrl ? packet.control.actual_size
: packet.transfer.actual_size;
if (_urb.actual_length && _urb.transfer_buffer &&
(_urb.transfer_buffer_length >= _urb.actual_length))
Genode::memcpy(_urb.transfer_buffer,
_usb.source()->packet_content(packet),
_urb.actual_length);
} else {
_urb.actual_length = 0;
switch (packet.error) {
case Usb::Packet_descriptor::NO_ERROR:
Genode::error(__func__, ": got NO_ERROR code in error path");
_urb.status = -EIO;
break;
case Usb::Packet_descriptor::INTERFACE_OR_ENDPOINT_ERROR:
_urb.status = -ENOENT;
break;
case Usb::Packet_descriptor::MEMORY_ERROR:
_urb.status = -ENOMEM;
break;
case Usb::Packet_descriptor::NO_DEVICE_ERROR:
_urb.status = -ESHUTDOWN;
break;
case Usb::Packet_descriptor::PACKET_INVALID_ERROR:
_urb.status = -EINVAL;
break;
case Usb::Packet_descriptor::PROTOCOL_ERROR:
_urb.status = -EPROTO;
break;
case Usb::Packet_descriptor::STALL_ERROR:
_urb.status = -EPIPE;
break;
case Usb::Packet_descriptor::TIMEOUT_ERROR:
_urb.status = -ETIMEDOUT;
break;
case Usb::Packet_descriptor::UNKNOWN_ERROR:
Genode::error(__func__, ": got UNKNOWN_ERROR code");
_urb.status = -EIO;
break;
}
}
_completed = true;
if (_urb.complete) _urb.complete(&_urb);
}
bool completed() const { return _completed; }
};
class Sync_ctrl_urb : public Urb
{
private:
completion _comp;
public:
Sync_ctrl_urb(Usb::Session_client & usb, urb & urb) : Urb(usb, urb) {
init_completion(&_comp); }
void complete(Usb::Packet_descriptor &p) override
{
Urb::complete(p);
::complete(&_comp);
}
void send(int timeout)
{
_packet.completion = this;
_packet.control.timeout = timeout;
Urb::send();
wait_for_completion(&_comp);
}
};
#endif /* _LX_KIT__USB_H_ */

View File

@ -1,80 +0,0 @@
/*
* \brief Work queue implementation
* \author Josef Soentgen
* \author Stefan Kalkowski
* \date 2015-10-26
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_KIT__WORK_H_
#define _LX_KIT__WORK_H_
#include <base/allocator.h>
namespace Lx {
class Work;
class Task;
}
class Lx::Work
{
public:
virtual ~Work() { }
/**
* Unblock corresponding task
*/
virtual void unblock() = 0;
/**
* Execute all queued work items
*
* The calling task is woken up afterwards.
*/
virtual void flush(Task &) = 0;
/**
* Wakeup calling task after work item was executed
*/
virtual void wakeup_for(void const * const, Task &) = 0;
/**
* Schedule work
*/
virtual void schedule(struct ::work_struct *) = 0;
/**
* Schedule delayed work
*/
virtual void schedule_tasklet(struct ::tasklet_struct *) = 0;
/**
* Cancel work item
*/
virtual bool cancel_work(struct ::work_struct *, bool sync = false) = 0;
/**
* Check if work is currently queued
*/
virtual bool work_queued(void const * const) = 0;
/**
* Return task name
*/
virtual char const *task_name() = 0;
static Work &work_queue(Genode::Allocator *alloc = nullptr);
static Work *alloc_work_queue(Genode::Allocator *alloc, char const *name);
static void free_work_queue(Work *W);
};
#endif /* _LX_KIT__WORK_H_ */

View File

@ -1,37 +0,0 @@
/*
* \brief ARMv6-specific part of the Linux API emulation
* \author Christian Prochaska
* \date 2014-05-28
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************************************
** source/arch/arm/include/asm/barrier.h **
*******************************************/
#define dsb() asm volatile ("mcr p15, 0, %0, c7, c10, 4": : "r" (0) : "memory")
#define dmb() asm volatile ("mcr p15, 0, %0, c7, c10, 5": : "r" (0) : "memory")
#define mb() dsb()
#define rmb() mb()
#define wmb() dsb()
#define dma_wmb() dmb()
#define dma_rmb() dmb()
/*
* This is the "safe" implementation as needed for a configuration
* with SMP enabled.
*/
#define smp_mb() dmb()
#define smp_rmb() smp_mb()
#define smp_wmb() dmb()
static inline void barrier() { asm volatile ("": : :"memory"); }

View File

@ -1,34 +0,0 @@
/*
* \brief ARMv7-specific part of the Linux API emulation
* \author Christian Prochaska
* \date 2014-05-28
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** asm/barrier.h **
*******************/
#define mb() asm volatile ("dsb": : :"memory")
#define rmb() mb()
#define wmb() asm volatile ("dsb st": : :"memory")
#define dma_wmb() asm volatile ("dmb oshst": : : "memory")
#define dma_rmb() asm volatile ("dmb osh": : : "memory")
/*
* This is the "safe" implementation as needed for a configuration
* with bufferable DMA memory and SMP enabled.
*/
#define smp_mb() asm volatile ("dmb ish": : :"memory")
#define smp_rmb() smp_mb()
#define smp_wmb() asm volatile ("dmb ishst": : :"memory")
static inline void barrier() { asm volatile ("": : :"memory"); }

View File

@ -1,34 +0,0 @@
/*
* \brief ARMv8-specific part of the Linux API emulation
* \author Christian Prochaska
* \date 2014-05-28
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/*******************
** asm/barrier.h **
*******************/
#define mb() asm volatile ("dsb ld": : :"memory")
#define rmb() mb()
#define wmb() asm volatile ("dsb st": : :"memory")
#define dma_wmb() __asm__ __volatile__ ("dmb oshst" : : : "memory")
#define dma_rmb() __asm__ __volatile__ ("dmb oshld" : : : "memory")
/*
* This is the "safe" implementation as needed for a configuration
* with bufferable DMA memory and SMP enabled.
*/
#define smp_mb() asm volatile ("dmb ish": : :"memory")
#define smp_rmb() smp_mb()
#define smp_wmb() asm volatile ("dmb ishst": : :"memory")
static inline void barrier() { asm volatile ("": : :"memory"); }

View File

@ -1,22 +0,0 @@
/*******************
** asm/barrier.h **
*******************/
#define mb() asm volatile ("mfence": : :"memory")
#define rmb() asm volatile ("lfence": : :"memory")
#define wmb() asm volatile ("sfence": : :"memory")
#define dma_wmb() barrier()
#define dma_rmb() barrier()
/*
* This is the "safe" implementation as needed for a configuration
* with SMP enabled.
*/
#define smp_mb() mb()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
static inline void barrier() { asm volatile ("": : :"memory"); }

View File

@ -1,26 +0,0 @@
/*
* \brief C ABI for panicking / blocking forever
* \author Norman Feske
* \date 2021-03-08
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/sleep.h>
/* Linux emulation environment includes */
#include <legacy/lx_emul/extern_c_begin.h>
#include <legacy/lx_emul/bug.h>
#include <legacy/lx_emul/extern_c_end.h>
extern "C" void lx_sleep_forever()
{
Genode::sleep_forever();
}

View File

@ -1,30 +0,0 @@
/*
* \brief Usb::Env initialization
* \author Sebastian Sumpf
* \date 2016-06-23
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <legacy/lx_kit/env.h>
static Lx_kit::Env *_env_ptr;
Lx_kit::Env &Lx_kit::env()
{
return *_env_ptr;
}
Lx_kit::Env &Lx_kit::construct_env(Genode::Env &env)
{
static Lx_kit::Env _env(env);
_env_ptr = &_env;
return _env;
}

View File

@ -1,289 +0,0 @@
/*
* \brief Signal context for IRQ's
* \author Josef Soentgen
* \author Christian Helmuth
* \author Stefan Kalkowski
* \date 2014-10-14
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/entrypoint.h>
#include <base/tslab.h>
#include <irq_session/client.h>
/* format-string includes */
#include <format/snprintf.h>
/* Linux emulation environment */
#include <lx_emul.h>
/* Linux kit includes */
#include <legacy/lx_kit/irq.h>
#include <legacy/lx_kit/scheduler.h>
namespace Lx_kit { class Irq; }
class Lx_kit::Irq : public Lx::Irq
{
private:
/**
* Helper utilty for composing IRQ related names
*/
struct Name_composer
{
char name[16];
Name_composer(unsigned number)
{
Format::snprintf(name, sizeof(name),
"irq_%02x", number);
}
};
/**
* This contains the Linux-driver handlers
*/
class Handler : public Lx_kit::List<Handler>::Element
{
private:
void *_dev; /* Linux device */
unsigned int _irq; /* Linux IRQ number */
irq_handler_t _handler; /* Linux handler */
irq_handler_t _thread_fn; /* Linux thread function */
public:
Handler(void *dev, unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn)
: _dev(dev), _irq(irq), _handler(handler),
_thread_fn(thread_fn) { }
bool handle()
{
if (!_handler) {
/* on Linux, having no handler implies IRQ_WAKE_THREAD */
_thread_fn(_irq, _dev);
return true;
}
switch (_handler(_irq, _dev)) {
case IRQ_WAKE_THREAD:
_thread_fn(_irq, _dev);
case IRQ_HANDLED:
return true;
case IRQ_NONE:
break;
}
return false;
}
};
public:
/**
* Context encapsulates the handling of an IRQ
*/
class Context : public Lx_kit::List<Context>::Element
{
private:
Name_composer _name;
unsigned int _irq;
Genode::Irq_session_client _irq_sess;
Lx_kit::List<Handler> _handler;
Lx::Task _task;
bool _irq_enabled;
bool _irq_ack_pending;
Genode::Signal_handler<Context> _dispatcher;
static void _run_irq(void *args)
{
Context *ctx = static_cast<Context*>(args);
while (1) {
Lx::scheduler().current()->block_and_schedule();
ctx->handle_irq();
}
}
public:
/**
* Constructor
*/
Context(Genode::Entrypoint &ep,
Genode::Irq_session_capability cap,
unsigned int irq)
:
_name(irq),
_irq(irq),
_irq_sess(cap),
_task(_run_irq, this, _name.name, Lx::Task::PRIORITY_3, Lx::scheduler()),
_irq_enabled(true),
_irq_ack_pending(false),
_dispatcher(ep, *this, &Context::unblock)
{
_irq_sess.sigh(_dispatcher);
/* initial ack to receive further IRQ signals */
_irq_sess.ack_irq();
}
/**
* Unblock this context, e.g., as result of an IRQ signal
*/
void unblock()
{
_task.unblock();
/* kick off scheduling */
Lx::scheduler().schedule();
}
/**
* Handle IRQ
*/
void handle_irq()
{
if (_irq_enabled) {
/* report IRQ to all clients */
for (Handler *h = _handler.first(); h; h = h->next())
h->handle();
_irq_sess.ack_irq();
} else {
/*
* IRQs are disabled by not acknowledging, so one IRQ
* can still occur in the 'disabled' state. It must be
* acknowledged later by 'enable_irq()'.
*/
_irq_ack_pending = true;
}
}
/**
* Add linux handler to context
*/
void add_handler(Handler *h) { _handler.append(h); }
bool irq(unsigned int irq) {
return (irq == _irq); }
void disable_irq()
{
_irq_enabled = false;
}
void enable_irq()
{
if (_irq_enabled)
return;
if (_irq_ack_pending) {
_irq_sess.ack_irq();
_irq_ack_pending = false;
}
_irq_enabled = true;
}
};
private:
using Context_slab = Genode::Tslab<Context, 3 * sizeof(Context)>;
using Handler_slab = Genode::Tslab<Handler, 3 * sizeof(Handler)>;
Genode::Entrypoint &_ep;
Lx_kit::List<Context> _list;
Context_slab _context_alloc;
Handler_slab _handler_alloc;
/**
* Find context for given IRQ number
*/
Context *_find_context(unsigned int irq)
{
for (Context *i = _list.first(); i; i = i->next())
if (i->irq(irq)) return i;
return nullptr;
}
Irq(Genode::Entrypoint &ep, Genode::Allocator &alloc)
: _ep(ep),
_context_alloc(&alloc),
_handler_alloc(&alloc) { }
public:
static Irq &irq(Genode::Entrypoint &ep, Genode::Allocator &alloc)
{
static Irq inst(ep, alloc);
return inst;
}
/***********************
** Lx::Irq interface **
***********************/
void request_irq(Genode::Irq_session_capability cap,
unsigned int irq,
irq_handler_t handler,
void * dev_id,
irq_handler_t thread_fn = 0) override
{
Context *ctx = _find_context(irq);
/* if this IRQ is not registered */
if (!ctx) {
ctx = new (&_context_alloc) Context(_ep, cap, irq);
_list.insert(ctx);
}
/* register Linux handler */
Handler *h = new (&_handler_alloc)
Handler(dev_id, irq, handler, thread_fn);
ctx->add_handler(h);
}
void inject_irq(unsigned int irq)
{
Context *ctx = _find_context(irq);
if (ctx) ctx->unblock();
}
void disable_irq(unsigned int irq)
{
Context *ctx = _find_context(irq);
if (ctx) ctx->disable_irq();
}
void enable_irq(unsigned int irq)
{
Context *ctx = _find_context(irq);
if (ctx) ctx->enable_irq();
}
};
/****************************
** Lx::Irq implementation **
****************************/
Lx::Irq &Lx::Irq::irq(Genode::Entrypoint *ep, Genode::Allocator *alloc) {
return Lx_kit::Irq::irq(*ep, *alloc); }

View File

@ -1,382 +0,0 @@
/*
* \brief Linux kit memory allocator
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/allocator_avl.h>
#include <base/env.h>
#include <base/slab.h>
#include <dataspace/client.h>
#include <rm_session/connection.h>
#include <region_map/client.h>
/* Linux kit includes */
#include <legacy/lx_kit/types.h>
#include <legacy/lx_kit/backend_alloc.h>
#include <legacy/lx_kit/malloc.h>
namespace Lx_kit {
class Slab_backend_alloc;
class Slab_alloc;
class Malloc;
}
class Lx_kit::Slab_backend_alloc : public Lx::Slab_backend_alloc,
public Genode::Rm_connection,
public Genode::Region_map_client
{
private:
enum {
VM_SIZE = 64 * 1024 * 1024, /* size of VM region to reserve */
P_BLOCK_SIZE = 2 * 1024 * 1024, /* 2 MB physical contiguous */
V_BLOCK_SIZE = P_BLOCK_SIZE * 2, /* 2 MB virtual used, 2 MB virtual left free to avoid that Allocator_avl merges virtual contiguous regions which are physically non-contiguous */
ELEMENTS = VM_SIZE / V_BLOCK_SIZE, /* MAX number of dataspaces in VM */
};
addr_t _base; /* virt. base address */
Genode::Cache _cache; /* non-/cached RAM */
Genode::Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */
addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */
int _index; /* current index in ds_cap */
Genode::Allocator_avl _range; /* manage allocations */
bool _alloc_block()
{
if (_index == ELEMENTS) {
Genode::error("slab backend exhausted!");
return false;
}
try {
_ds_cap[_index] = Lx::backend_alloc(P_BLOCK_SIZE, _cache);
/* attach at index * V_BLOCK_SIZE */
Region_map_client::attach_at(_ds_cap[_index], _index * V_BLOCK_SIZE, P_BLOCK_SIZE, 0);
/* lookup phys. address */
_ds_phys[_index] = Lx::backend_dma_addr(_ds_cap[_index]);
} catch (...) { return false; }
/* return base + offset in VM area */
addr_t block_base = _base + (_index * V_BLOCK_SIZE);
++_index;
_range.add_range(block_base, P_BLOCK_SIZE);
return true;
}
public:
Slab_backend_alloc(Genode::Env &env, Genode::Allocator &md_alloc,
Genode::Cache cache)
:
Rm_connection(env),
Region_map_client(Rm_connection::create(VM_SIZE)),
_cache(cache), _index(0), _range(&md_alloc)
{
/* reserver attach us, anywere */
_base = env.rm().attach(dataspace());
}
/**************************************
** Lx::Slab_backend_alloc interface **
**************************************/
Alloc_result try_alloc(size_t size) override
{
Alloc_result result = _range.try_alloc(size);
if (result.ok())
return result;
if (!_alloc_block()) {
Genode::error("backend allocator exhausted");
return Alloc_error::DENIED;
}
return _range.alloc(size);
}
void free(void *addr) {
_range.free(addr); }
void free(void *addr, size_t size) override { _range.free(addr, size); }
size_t overhead(size_t size) const override { return 0; }
bool need_size_for_free() const override { return false; }
addr_t phys_addr(addr_t addr)
{
if (addr < _base || addr >= (_base + VM_SIZE))
return ~0UL;
int index = (addr - _base) / V_BLOCK_SIZE;
/* physical base of dataspace */
addr_t phys = _ds_phys[index];
if (!phys)
return ~0UL;
/* add offset */
phys += (addr - _base - (index * V_BLOCK_SIZE));
return phys;
}
addr_t virt_addr(addr_t phys)
{
for (unsigned i = 0; i < ELEMENTS; i++) {
if (_ds_cap[i].valid() &&
phys >= _ds_phys[i] && phys < _ds_phys[i] + P_BLOCK_SIZE)
return _base + i * V_BLOCK_SIZE + phys - _ds_phys[i];
}
Genode::warning("virt_addr(", Genode::Hex(phys), ") - no translation");
return 0;
}
addr_t start() const { return _base; }
addr_t end() const { return _base + VM_SIZE - 1; }
};
class Lx_kit::Malloc : public Lx::Malloc
{
private:
enum {
SLAB_START_LOG2 = 3, /* 8 B */
SLAB_STOP_LOG2 = MAX_SIZE_LOG2,
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
};
typedef Genode::addr_t addr_t;
typedef Lx::Slab_alloc Slab_alloc;
typedef Lx::Slab_backend_alloc Slab_backend_alloc;
Slab_backend_alloc &_back_allocator;
Genode::Constructible<Slab_alloc> _allocator[NUM_SLABS];
Genode::Cache _cache; /* cached or un-cached memory */
addr_t _start; /* VM region of this allocator */
addr_t _end;
/**
* Set 'value' at 'addr'
*/
void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; }
/**
* Retrieve slab index belonging to given address
*/
unsigned _slab_index(Genode::addr_t **addr)
{
using namespace Genode;
/* get index */
addr_t index = *(*addr - 1);
/*
* If index large, we use aligned memory, retrieve beginning of slab entry
* and read index from there
*/
if (index > 32) {
*addr = (addr_t *)*(*addr - 1);
index = *(*addr - 1);
}
return index;
}
/**
* Get the originally requested size of the allocation
*/
size_t _get_orig_size(Genode::addr_t **addr)
{
using namespace Genode;
addr_t index = *(*addr - 1);
if (index > 32) {
*addr = (addr_t *) * (*addr - 1);
}
return *(*addr - 2);
}
public:
Malloc(Slab_backend_alloc &alloc, Genode::Cache cache)
:
_back_allocator(alloc), _cache(cache), _start(alloc.start()),
_end(alloc.end())
{
/* init slab allocators */
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++)
_allocator[i - SLAB_START_LOG2].construct(1U << i, alloc);
}
/**************************
** Lx::Malloc interface **
**************************/
void *malloc(Genode::size_t size, int align = 0, Genode::addr_t *phys = 0)
{
using namespace Genode;
/* save requested size */
size_t orig_size = size;
size += sizeof(addr_t);
/* += slab index + aligment size */
size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0);
int msb = Genode::log2(size);
if (size > (1U << msb))
msb++;
if (size < (1U << SLAB_START_LOG2))
msb = SLAB_STOP_LOG2;
if (msb > SLAB_STOP_LOG2) {
Genode::error("slab too large ",
1UL << msb, " requested ", size, " cached ", (int)_cache);
return 0;
}
addr_t addr = (addr_t)_allocator[msb - SLAB_START_LOG2]->alloc_element();
if (!addr) {
Genode::error("failed to get slab for ", 1 << msb);
return 0;
}
_set_at(addr, orig_size);
addr += sizeof(addr_t);
_set_at(addr, msb - SLAB_START_LOG2);
addr += sizeof(addr_t);
if (align > 2) {
/* save */
addr_t ptr = addr;
addr_t align_val = (1U << align);
addr_t align_mask = align_val - 1;
/* align */
addr = (addr + align_val) & ~align_mask;
/* write start address before aligned address */
_set_at(addr - sizeof(addr_t), ptr);
}
if (phys)
*phys = _back_allocator.phys_addr(addr);
return (addr_t *)addr;
}
void free(void const *a)
{
using namespace Genode;
addr_t *addr = (addr_t *)a;
/* XXX changes addr */
unsigned nr = _slab_index(&addr);
/* we need to decrease addr by 2, orig_size and index come first */
_allocator[nr]->free((void *)(addr - 2));
}
void *alloc_large(size_t size)
{
return _back_allocator.try_alloc(size).convert<void *>(
[&] (void *ptr) {
return ptr; },
[&] (Alloc_error) {
Genode::error("large back end allocation failed (", size, " bytes)");
return (void *)nullptr; });
}
void free_large(void *ptr)
{
_back_allocator.free(ptr);
}
size_t size(void const *a)
{
using namespace Genode;
addr_t *addr = (addr_t *)a;
/* XXX changes addr */
return _get_orig_size(&addr);
}
Genode::addr_t phys_addr(void *a) {
return _back_allocator.phys_addr((addr_t)a); }
Genode::addr_t virt_addr(Genode::addr_t phys) {
return _back_allocator.virt_addr(phys); }
bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); }
};
/*******************************
** Lx::Malloc implementation **
*******************************/
static Lx_kit::Slab_backend_alloc *_mem_backend_alloc_ptr;
static Lx_kit::Slab_backend_alloc *_dma_backend_alloc_ptr;
static Lx_kit::Malloc *_mem_alloc_ptr;
static Lx_kit::Malloc *_dma_alloc_ptr;
void Lx::malloc_init(Genode::Env &env, Genode::Allocator &md_alloc)
{
static Lx_kit::Slab_backend_alloc mem_backend_alloc(env, md_alloc, Genode::CACHED);
static Lx_kit::Slab_backend_alloc dma_backend_alloc(env, md_alloc, Genode::UNCACHED);
_mem_backend_alloc_ptr = &mem_backend_alloc;
_dma_backend_alloc_ptr = &dma_backend_alloc;
static Lx_kit::Malloc mem_alloc(mem_backend_alloc, Genode::CACHED);
static Lx_kit::Malloc dma_alloc(dma_backend_alloc, Genode::UNCACHED);
_mem_alloc_ptr = &mem_alloc;
_dma_alloc_ptr = &dma_alloc;
}
/**
* Cached memory backend allocator
*/
Lx::Slab_backend_alloc &Lx::Slab_backend_alloc::mem() {
return *_mem_backend_alloc_ptr; }
/**
* DMA memory backend allocator
*/
Lx::Slab_backend_alloc &Lx::Slab_backend_alloc::dma() {
return *_dma_backend_alloc_ptr; }
/**
* Cached memory allocator
*/
Lx::Malloc &Lx::Malloc::mem() { return *_mem_alloc_ptr; }
/**
* DMA memory allocator
*/
Lx::Malloc &Lx::Malloc::dma() { return *_dma_alloc_ptr; }

View File

@ -1,442 +0,0 @@
/*
* \brief Linux kit printf backend
* \author Sebastian Sumpf
* \date 2016-04-20
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <util/string.h>
/* local includes */
#include <lx_emul.h>
namespace Lx {
class Console;
class Format_command;
}
/**
* Format string command representation
*/
class Lx::Format_command
{
public:
enum Type { INT, UINT, STRING, CHAR, PTR, PERCENT, VA_FORMAT, MAC,
IPV4, INVALID };
enum Length { DEFAULT, LONG, SIZE_T, LONG_LONG };
private:
/**
* Read decimal value from string
*/
int decode_decimal(const char *str, int *consumed)
{
int res = 0;
while (1) {
char c = str[*consumed];
if (!c || c < '0' || c > '0' + 9)
return res;
res = (res * 10) + c - '0';
(*consumed)++;
}
}
public:
Type type = INVALID; /* format argument type */
Length length = DEFAULT; /* format argument length */
int padding = 0; /* min number of characters to print */
int base = 10; /* base of numeric arguments */
bool zeropad = false; /* pad with zero instead of space */
bool uppercase = false; /* use upper case for hex numbers */
bool prefix = false; /* prefix with 0x */
int consumed = 0; /* nb of consumed format string chars */
/**
* Constructor
*
* \param format begin of command in format string
*/
explicit Format_command(const char *format)
{
/* check for command begin and eat the character */
if (format[consumed] != '%') return;
if (!format[++consumed]) return;
/* check for %$x syntax */
prefix = (format[consumed] == '#') || (format[consumed] == '.');
if (prefix && !format[++consumed]) return;
/* heading zero indicates zero-padding */
zeropad = (format[consumed] == '0');
/* read decimal padding value */
padding = decode_decimal(format, &consumed);
if (!format[consumed]) return;
/* decode length */
switch (format[consumed]) {
case 'l':
{
/* long long ints are marked by a subsequenting 'l' character */
bool is_long_long = (format[consumed + 1] == 'l');
length = is_long_long ? LONG_LONG : LONG;
consumed += is_long_long ? 2 : 1;
break;
}
case 'z':
case 'Z':
length = SIZE_T;
consumed++;
break;
case 'p':
length = LONG;
break;
default: break;
}
if (!format[consumed]) return;
/* decode type */
switch (format[consumed]) {
case 'd':
case 'i': type = INT; base = 10; break;
case 'o': type = UINT; base = 8; break;
case 'u': type = UINT; base = 10; break;
case 'x': type = UINT; base = 16; break;
case 'X': type = UINT; base = 16; uppercase = 1; break;
case 'p': type = PTR; base = 16; break;
case 'c': type = CHAR; break;
case 's': type = STRING; break;
case '%': type = PERCENT; break;
case 0: return;
default: break;
}
/* eat type character */
consumed++;
if (type != PTR || !format[consumed])
return;
switch (format[consumed]) {
case 'V': type = VA_FORMAT; break;
case 'M': type = MAC; base = 16; padding = 2; break;
case 'I':
if (format[consumed + 1] != '4') break;
consumed++;
type = IPV4; base = 10;
break;
default: return;
}
consumed++;
}
int numeric()
{
return (type == INT || type == UINT || type == PTR);
}
};
/**
* Convert digit to ASCII value
*/
static char ascii(int digit, int uppercase = 0)
{
if (digit > 9)
return digit + (uppercase ? 'A' : 'a') - 10;
return digit + '0';
}
class Lx::Console
{
private:
enum { BUF_SIZE = 216 };
char _buf[BUF_SIZE + 1];
unsigned _idx = 0;
void _flush()
{
if (!_idx)
return;
_buf[_idx] = 0;
Genode::log(Genode::Cstring(_buf));
_idx = 0;
}
/**
* Output signed value with the specified base
*/
template <typename T>
void _out_signed(T value, unsigned base)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
/* set flag if value is negative */
int neg = value < 0 ? 1 : 0;
/* get absolute value */
value = value < 0 ? -value : value;
int i = 0;
/* handle zero as special case */
if (value == 0)
buf[i++] = ascii(0);
/* fill buffer starting with the least significant digits */
else
for (; value > 0; value /= base)
buf[i++] = ascii(value % base);
/* add sign to buffer for negative values */
if (neg)
_out_char('-');
/* output buffer in reverse order */
for (; i--; )
_out_char(buf[i]);
}
/**
* Output unsigned value with the specified base and padding
*/
template <typename T>
void _out_unsigned(T value, unsigned base, int pad)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
int i = 0;
/* handle zero as special case */
if (value == 0) {
buf[i++] = ascii(0);
pad--;
}
/* fill buffer starting with the least significant digits */
for (; value > 0; value /= base, pad--)
buf[i++] = ascii(value % base);
/* add padding zeros */
for (; pad-- > 0; )
_out_char(ascii(0));
/* output buffer in reverse order */
for (; i--; )
_out_char(buf[i]);
}
protected:
void _out_char(char c)
{
if (c == '\n' || _idx == BUF_SIZE || c == 0)
_flush();
else
_buf[_idx++] = c;
}
void _out_string(const char *str)
{
if (str)
while (*str) _out_char(*str++);
else
_flush();
}
public:
static Console &c()
{
static Console _inst;
return _inst;
}
void vprintf(const char *format, va_list list)
{
while (*format) {
/* eat and output plain characters */
if (*format != '%') {
_out_char(*format++);
continue;
}
/* parse format argument descriptor */
Format_command cmd(format);
/* read numeric argument from va_list */
long long numeric_arg = 0;
if (cmd.numeric()) {
switch (cmd.length) {
case Format_command::LONG_LONG:
numeric_arg = va_arg(list, long long);
break;
case Format_command::LONG:
numeric_arg = (cmd.type == Format_command::UINT) ?
(long long)va_arg(list, unsigned long) : va_arg(list, long);
break;
case Format_command::SIZE_T:
numeric_arg = va_arg(list, size_t);
break;
case Format_command::DEFAULT:
numeric_arg = (cmd.type == Format_command::UINT) ?
(long long)va_arg(list, unsigned int) : va_arg(list, int);
break;
}
}
/* call type-specific output routines */
switch (cmd.type) {
case Format_command::INT:
if (cmd.length == Format_command::LONG_LONG)
_out_signed<long long>(numeric_arg, cmd.base);
else
_out_signed<long>(numeric_arg, cmd.base);
break;
case Format_command::UINT:
if (cmd.prefix && cmd.base == 16)
_out_string("0x");
if (cmd.length == Format_command::LONG_LONG) {
_out_unsigned<unsigned long long>(numeric_arg, cmd.base, cmd.padding);
break;
}
/* fall through */
case Format_command::PTR:
_out_unsigned<unsigned long>(numeric_arg, cmd.base, cmd.padding);
break;
case Format_command::CHAR:
_out_char(va_arg(list, int));
break;
case Format_command::STRING:
_out_string(va_arg(list, const char *));
break;
case Format_command::PERCENT:
_out_char('%');
break;
case Format_command::VA_FORMAT: /* %pV */
{
va_list va;
va_format *vf = va_arg(list, va_format *);
va_copy(va, *vf->va);
vprintf(vf->fmt, va);
va_end(va);
}
break;
case Format_command::MAC: /* %pM */
{
unsigned char const *mac = va_arg(list, unsigned char const *);
for (int i = 0; i < 6; i++) {
if (i) _out_char(':');
_out_unsigned<unsigned char>(mac[i], cmd.base, cmd.padding);
}
break;
}
case Format_command::IPV4: /* %pI4 */
{
unsigned char const *ip = va_arg(list, unsigned char const *);
for (int i = 0; i < 4; i++) {
if (i) _out_char('.');
_out_unsigned<unsigned char>(ip[i], cmd.base, cmd.padding);
}
}
break;
case Format_command::INVALID:
_out_string("<warning: unsupported format string argument>");
/* consume the argument of the unsupported command */
va_arg(list, long);
break;
}
/* proceed with format string after command */
format += cmd.consumed;
}
}
};
void lx_printf(char const *fmt, ...)
{
va_list va;
va_start(va, fmt);
Lx::Console::c().vprintf(fmt, va);
va_end(va);
}
void lx_vprintf(char const *fmt, va_list va) {
Lx::Console::c().vprintf(fmt, va); }

View File

@ -1,228 +0,0 @@
/*
* \brief Scheduler for executing Lx::Task objects
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/env.h>
#include <base/log.h>
#include <base/sleep.h>
#include <base/thread.h>
#include <timer_session/connection.h>
/* Linux emulation environment includes */
#include <legacy/lx_kit/scheduler.h>
#include <legacy/lx_kit/timer.h>
namespace Lx_kit {
class Scheduler;
}
class Lx_kit::Scheduler : public Lx::Scheduler
{
private:
bool verbose = false;
Lx_kit::List<Lx::Task> _present_list;
Lx::Task *_current = nullptr; /* currently scheduled task */
bool _run_task(Lx::Task *);
/*
* Support for logging
*/
static inline char const *_ansi_esc_reset() { return "\033[00m"; }
static inline char const *_ansi_esc_black() { return "\033[30m"; }
static inline char const *_ansi_esc_red() { return "\033[31m"; }
static inline char const *_ansi_esc_yellow() { return "\033[33m"; }
static inline char const *_state_color(Lx::Task::State state)
{
switch (state) {
case Lx::Task::STATE_INIT: return _ansi_esc_reset();
case Lx::Task::STATE_RUNNING: return _ansi_esc_red();
case Lx::Task::STATE_BLOCKED: return _ansi_esc_yellow();
case Lx::Task::STATE_MUTEX_BLOCKED: return _ansi_esc_yellow();
case Lx::Task::STATE_WAIT_BLOCKED: return _ansi_esc_yellow();
}
return _ansi_esc_black();
}
struct Logger : Genode::Thread
{
Timer::Connection _timer;
Lx::Scheduler &_scheduler;
Genode::uint64_t const _interval;
Logger(Genode::Env &env, Lx::Scheduler &scheduler,
Genode::uint64_t interval_seconds)
:
Genode::Thread(env, "logger", 0x4000),
_timer(env), _scheduler(scheduler),
_interval(interval_seconds)
{
start();
}
void entry()
{
_timer.msleep(1000 * _interval);
while (true) {
_scheduler.log_state("LOGGER");
_timer.msleep(2000);
}
}
};
Genode::Constructible<Logger> _logger;
public:
Scheduler(Genode::Env &env)
{
if (verbose) { _logger.construct(env, *this, 10); }
}
/*****************************
** Lx::Scheduler interface **
*****************************/
Lx::Task *current() override
{
if (!_current) {
Genode::error("BUG: _current is zero!");
Genode::sleep_forever();
}
return _current;
}
bool active() const override {
return _current != nullptr; }
void add(Lx::Task *task) override
{
Lx::Task *p = _present_list.first();
for ( ; p; p = p->next()) {
if (p->priority() <= task->priority()) {
_present_list.insert_before(task, p);
break;
}
}
if (!p)
_present_list.append(task);
}
void remove(Lx::Task *task) override
{
_present_list.remove(task);
}
void schedule() override
{
bool at_least_one = false;
/*
* Iterate over all tasks and run first runnable.
*
* (1) If one runnable tasks was run start over from beginning of
* list.
*
* (2) If no task is runnable quit scheduling (break endless
* loop).
*/
while (true) {
/* update jiffies before running task */
Lx::timer_update_jiffies();
bool was_run = false;
for (Lx::Task *t = _present_list.first(); t; t = t->next()) {
/* update current before running task */
_current = t;
if ((was_run = t->run())) {
at_least_one = true;
break;
}
}
if (!was_run)
break;
}
if (!at_least_one) {
Genode::warning("schedule() called without runnable tasks");
log_state("SCHEDULE");
}
/* clear current as no task is running */
_current = nullptr;
}
void log_state(char const *prefix) override
{
unsigned i;
Lx::Task *t;
for (i = 0, t = _present_list.first(); t; t = t->next(), ++i) {
Genode::log(prefix, " [", i, "] "
"prio: ", (int)t->priority(), " "
"state: ", _state_color(t->state()), (int)t->state(),
_ansi_esc_reset(), " ",
t->name());
}
}
};
/*****************************
** Lx::Task implementation **
*****************************/
Lx::Task::Task(void (*func)(void*), void *arg, char const *name,
Priority priority, Scheduler &scheduler)
:
_priority(priority), _scheduler(scheduler),
_func(func), _arg(arg), _name(name)
{
scheduler.add(this);
if (verbose)
Genode::log("name: '", name, "' " "func: ", func, " "
"arg: ", arg, " prio: ", (int)priority, " t: ", this);
}
Lx::Task::~Task()
{
_scheduler.remove(this);
if (_stack)
Genode::Thread::myself()->free_secondary_stack(_stack);
}
/**********************************
** Lx::Scheduler implementation **
**********************************/
Lx::Scheduler &Lx::scheduler(Genode::Env *env)
{
static Lx_kit::Scheduler inst { *env };
return inst;
}

View File

@ -1,317 +0,0 @@
/*
* \brief Timer
* \author Sebastian Sumpf
* \author Josef Soentgen
* \author Norman Feske
* \date 2014-10-10
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/tslab.h>
#include <timer_session/connection.h>
/* Linux kit includes */
#include <legacy/lx_kit/internal/list.h>
#include <legacy/lx_kit/scheduler.h>
/* Linux emulation environment includes */
#include <lx_emul.h>
#include <legacy/lx_kit/timer.h>
namespace Lx_kit { class Timer; }
class Lx_kit::Timer : public Lx::Timer
{
public:
/**
* Context encapsulates a regular linux timer_list
*/
struct Context : public Lx_kit::List<Context>::Element
{
enum { INVALID_TIMEOUT = ~0UL };
Type type;
void *timer;
bool pending { false };
unsigned long timeout { INVALID_TIMEOUT }; /* absolute in jiffies */
Context(struct timer_list *timer) : type(LIST), timer(timer) { }
Context(struct hrtimer *timer) : type(HR), timer(timer) { }
void expires(unsigned long e)
{
if (type == LIST)
static_cast<timer_list *>(timer)->expires = e;
}
void function()
{
switch (type) {
case LIST:
{
timer_list *t = static_cast<timer_list *>(timer);
if (t->function) {
/*
* Pass 't->data' instead of 't' for compatibility
* with 4.4.3 drivers. When set up with
* 'timer_setup()', 't->data' matches 't'.
*/
t->function((struct timer_list*)t->data);
}
}
break;
case HR:
{
hrtimer *t = static_cast<hrtimer *>(timer);
if (t->function)
t->function(t);
}
break;
}
}
};
private:
unsigned long &_jiffies;
::Timer::Connection _timer_conn;
::Timer::Connection _timer_conn_modern;
Lx_kit::List<Context> _list;
Lx::Task _timer_task;
Genode::Signal_handler<Lx_kit::Timer> _dispatcher;
Genode::Tslab<Context, 32 * sizeof(Context)> _timer_alloc;
/**
* Lookup local timer
*/
Context *_find_context(void const *timer)
{
for (Context *c = _list.first(); c; c = c->next())
if (c->timer == timer)
return c;
return 0;
}
/**
* Program the first timer in the list
*/
void _program_first_timer()
{
Context *ctx = _list.first();
if (!ctx)
return;
/* calculate relative microseconds for trigger */
Genode::uint64_t us = ctx->timeout > _jiffies ?
(Genode::uint64_t)jiffies_to_msecs(ctx->timeout - _jiffies) * 1000 : 0;
_timer_conn.trigger_once(us);
}
/**
* Schedule timer
*
* Add the context to the scheduling list depending on its timeout
* and reprogram the first timer.
*/
void _schedule_timer(Context *ctx, unsigned long expires)
{
_list.remove(ctx);
ctx->timeout = expires;
ctx->pending = true;
/*
* Also write the timeout value to the expires field in
* struct timer_list because some code the checks
* it directly.
*/
ctx->expires(expires);
Context *c;
for (c = _list.first(); c; c = c->next())
if (ctx->timeout <= c->timeout)
break;
_list.insert_before(ctx, c);
_program_first_timer();
}
/**
* Handle trigger_once signal
*/
void _handle()
{
_timer_task.unblock();
Lx::scheduler().schedule();
}
public:
/**
* Constructor
*/
Timer(Genode::Env &env, Genode::Entrypoint &ep,
Genode::Allocator &alloc, unsigned long &jiffies)
:
_jiffies(jiffies),
_timer_conn(env),
_timer_conn_modern(env),
_timer_task(Timer::run_timer, reinterpret_cast<void*>(this),
"timer", Lx::Task::PRIORITY_2, Lx::scheduler()),
_dispatcher(ep, *this, &Lx_kit::Timer::_handle),
_timer_alloc(&alloc)
{
_timer_conn.sigh(_dispatcher);
update_jiffies();
}
Context* first() { return _list.first(); }
unsigned long jiffies() const { return _jiffies; }
static void run_timer(void *p)
{
Timer &t = *reinterpret_cast<Timer*>(p);
while (1) {
Lx::scheduler().current()->block_and_schedule();
while (Lx_kit::Timer::Context *ctx = t.first()) {
if (ctx->timeout > t.jiffies()) {
break;
}
ctx->pending = false;
ctx->function();
if (!ctx->pending) {
t.del(ctx->timer);
}
}
t.schedule_next();
}
}
/*************************
** Lx::Timer interface **
*************************/
void add(void *timer, Type type)
{
Context *t = nullptr;
if (type == HR)
t = new (&_timer_alloc) Context(static_cast<hrtimer *>(timer));
else
t = new (&_timer_alloc) Context(static_cast<timer_list *>(timer));
_list.append(t);
}
int del(void *timer)
{
Context *ctx = _find_context(timer);
/**
* If the timer expired it was already cleaned up after its
* execution.
*/
if (!ctx)
return 0;
int rv = ctx->pending ? 1 : 0;
_list.remove(ctx);
destroy(&_timer_alloc, ctx);
return rv;
}
int schedule(void *timer, unsigned long expires)
{
Context *ctx = _find_context(timer);
if (!ctx) {
Genode::error("schedule unknown timer ", timer);
return -1; /* XXX better use 0 as rv? */
}
/*
* If timer was already active return 1, otherwise 0. The return
* value is needed by mod_timer().
*/
int rv = ctx->pending ? 1 : 0;
_schedule_timer(ctx, expires);
return rv;
}
void schedule_next() { _program_first_timer(); }
/**
* Check if the timer is currently pending
*/
bool pending(void const *timer)
{
Context *ctx = _find_context(timer);
if (!ctx) {
return false;
}
return ctx->pending;
}
bool find(void const *timer) const
{
for (Context const *c = _list.first(); c; c = c->next())
if (c->timer == timer)
return true;
return false;
}
void update_jiffies()
{
/*
* Do not use lx_emul usecs_to_jiffies(unsigned int) because
* of implicit truncation!
*/
_jiffies = (Genode::uint64_t)_timer_conn_modern.curr_time().trunc_to_plain_ms().value / JIFFIES_TICK_MS;
}
void usleep(Genode::uint64_t us) {
_timer_conn.usleep(us); }
};
/******************************
** Lx::Timer implementation **
******************************/
Lx::Timer &Lx::timer(Genode::Env *env, Genode::Entrypoint *ep,
Genode::Allocator *md_alloc,
unsigned long *jiffies)
{
static Lx_kit::Timer inst(*env, *ep, *md_alloc, *jiffies);
return inst;
}
void Lx::timer_update_jiffies()
{
timer().update_jiffies();
}

View File

@ -1,226 +0,0 @@
/*
* \brief Work queue implementation
* \author Josef Soentgen
* \author Stefan Kalkowski
* \date 2015-10-26
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/tslab.h>
#include <legacy/lx_kit/internal/list.h>
#include <legacy/lx_kit/scheduler.h>
/* Linux emulation environment includes */
#include <lx_emul.h>
#include <legacy/lx_kit/work.h>
namespace Lx_kit { class Work; }
class Lx_kit::Work : public Lx::Work
{
public:
/**
* Context encapsulates a normal work item
*/
struct Context : public Lx_kit::List<Context>::Element
{
Lx::Task *waiting_task { nullptr };
void *work;
enum Type { NORMAL, DELAYED, TASKLET } type;
void exec() {
switch (type) {
case NORMAL:
{
work_struct *w = static_cast<work_struct *>(work);
w->func(w);
}
break;
case DELAYED:
{
delayed_work *w = static_cast<delayed_work *>(work);
w->work.func(&(w)->work);
}
break;
case TASKLET:
{
tasklet_struct *tasklet = static_cast<tasklet_struct *>(work);
tasklet->func(tasklet->data);
}
break;
}
}
Context(delayed_work *w) : work(w), type(DELAYED) { }
Context(work_struct *w) : work(w), type(NORMAL) { }
Context(tasklet_struct *w) : work(w), type(TASKLET) { }
};
private:
Lx::Task _task;
Lx_kit::List<Context> _list;
Genode::Tslab<Context, 64 * sizeof(Context)> _work_alloc;
/**
* Schedule work item
*/
template <typename WORK>
void _schedule(WORK *work)
{
Context *c = new (&_work_alloc) Context(work);
_list.append(c);
}
public:
Lx::Task *_waiting_task = nullptr;
Work(Genode::Allocator &alloc, char const *name = "work_queue")
: _task(Work::run_work, reinterpret_cast<void*>(this), name,
Lx::Task::PRIORITY_2, Lx::scheduler()),
_work_alloc(&alloc) { }
/**
* Execute all available work items
*/
void exec()
{
while (Context *c = _list.first()) {
_list.remove(c);
c->exec();
if (c->waiting_task) {
c->waiting_task->unblock();
c->waiting_task = nullptr;
}
destroy(&_work_alloc, c);
}
}
static void run_work(void *wq)
{
Work *work_queue = reinterpret_cast<Work*>(wq);
while (1) {
work_queue->exec();
if (work_queue->_waiting_task) {
work_queue->_waiting_task->unblock();
work_queue->_waiting_task = nullptr;
}
Lx::scheduler().current()->block_and_schedule();
}
}
/************************
** Lx::Work interface **
************************/
void unblock()
{
_task.unblock();
}
void flush(Lx::Task &task)
{
_task.unblock();
_waiting_task = &task;
}
void wakeup_for(void const * const work, Lx::Task &task)
{
Context *ctx = nullptr;
for (Context *c = _list.first(); c; c = c->next()) {
if (c->work == work) {
ctx = c;
break;
}
}
if (!ctx) {
Genode::error("BUG: no work queued for wakeup_for call");
Genode::sleep_forever();
}
ctx->waiting_task = &task;
_task.unblock();
}
void schedule(struct work_struct *work) {
_schedule(work); }
void schedule_tasklet(struct tasklet_struct *tasklet) {
_schedule(tasklet); }
bool cancel_work(struct work_struct *work, bool sync = false)
{
for (Context *c = _list.first(); c; c = c->next()) {
if (c->work == work) {
if (sync)
c->exec();
_list.remove(c);
destroy(&_work_alloc, c);
return true;
}
}
return false;
}
bool work_queued(void const * const work)
{
for (Context *c = _list.first(); c; c = c->next()) {
if (c->work == work) {
return true;
}
}
return false;
}
char const *task_name() override { return _task.name(); }
};
/*****************************
** Lx::Work implementation **
*****************************/
Lx::Work & Lx::Work::work_queue(Genode::Allocator *alloc)
{
static Lx_kit::Work inst(*alloc);
return inst;
}
Lx::Work * Lx::Work::alloc_work_queue(Genode::Allocator *alloc, char const *name)
{
Lx::Work *work = new (alloc) Lx_kit::Work(*alloc, name);
return work;
}
void Lx::Work::free_work_queue(Lx::Work *w)
{
Genode::error(__func__, ": IMPLEMENT ME");
}