mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
dde_linux: remove legacy lx_kit and lx_emul
All good things must come to an end. issue #5104
This commit is contained in:
parent
8aa3967201
commit
97f8179f90
@ -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)
|
@ -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))))
|
@ -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))
|
@ -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
|
@ -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)
|
@ -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);
|
@ -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; }
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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)
|
@ -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);
|
||||
}
|
@ -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")
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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) { }
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 *);
|
@ -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)
|
@ -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)
|
@ -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 *);
|
@ -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>
|
@ -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; })
|
@ -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)
|
@ -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)
|
@ -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
|
@ -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
|
@ -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)
|
@ -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);
|
@ -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 }
|
@ -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}
|
@ -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);
|
@ -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);
|
@ -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 *);
|
@ -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;
|
@ -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; \
|
||||
})
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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"); }
|
@ -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"); }
|
@ -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"); }
|
@ -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"); }
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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); }
|
@ -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; }
|
@ -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); }
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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");
|
||||
}
|
Loading…
Reference in New Issue
Block a user