From 0106045bad27746e21491d7821b4a2131c604229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Thu, 17 Mar 2016 15:19:03 +0100 Subject: [PATCH] lx_kit: add modular lx_emul backend The modular lx_kit seperates the required back end functionality of the Linux emulation environment from the front end. Thereby each driver can reuse specific parts or supply more suitable implementations by itself. It is used to reduce the amount of redundant code in each driver. The lx_kit is split into several layers whose structure is as follows: The first layer in _repos/dde_linux/src/include/lx_emul_ contains those header files that provide the structural definitions and function declarations of the Linux API, e.g. _errno.h_ provides all error code values. The second layer in _repos/dde_linux/src/include/lx_emul/impl_ contains the implementation of selected functions, e.g. _slab.h_ provides the implementation of 'kmalloc()'. The lx_kit back end API is the third layer and provides the _Lx::Malloc_ interface (_repos/dde_linux/src/include/lx_kit/malloc.h_) which is used to implement 'kmalloc()'. There are several generic implementations of the lx_kit interfaces that can be used by a driver. A driver typically includes a 'lx_emul/impl/xyz.h' header once directly in its lx_emul compilation unit. The lx_kit interface files are only included in those compilation units that use or implement the interface. If a driver wants to use a generic implementation it must add the source file to its source file list. The generic implementations are located in _repos/dde_linux/src/lx_kit/_. The modular lx_kit still depends on the private _lx_emul.h_ header file that is tailored to each driver. Since the lx_kit already contains much of the declarations and definitions that were originally placed in these private header files, those files can now ommit a large amount of code. Fixes #1974. --- repos/dde_linux/README | 32 ++ repos/dde_linux/include/lx/extern_c_begin.h | 26 - repos/dde_linux/include/lx/extern_c_end.h | 20 - repos/dde_linux/include/lx/list.h | 102 ---- repos/dde_linux/include/lx/lx.h | 83 ---- repos/dde_linux/lib/mk/lx.mk | 5 - repos/dde_linux/src/include/lx_emul/bug.h | 10 +- .../dde_linux/src/include/lx_emul/compiler.h | 9 +- .../src/include/lx_emul/completion.h | 31 ++ repos/dde_linux/src/include/lx_emul/errno.h | 2 + .../src/include/lx_emul/extern_c_begin.h | 11 +- .../src/include/lx_emul/extern_c_end.h | 3 + repos/dde_linux/src/include/lx_emul/gfp.h | 4 + .../src/include/lx_emul/impl/completion.h | 33 +- .../src/include/lx_emul/impl/delay.h | 4 +- .../dde_linux/src/include/lx_emul/impl/gfp.h | 16 +- .../include/lx_emul/impl/internal/malloc.h | 208 -------- .../impl/internal/slab_backend_alloc.h | 175 ------- repos/dde_linux/src/include/lx_emul/impl/io.h | 7 +- .../src/include/lx_emul/impl/mutex.h | 16 +- .../dde_linux/src/include/lx_emul/impl/pci.h | 139 +----- .../src/include/lx_emul/impl/pci_resource.h | 142 ++++++ .../src/include/lx_emul/impl/sched.h | 5 +- .../dde_linux/src/include/lx_emul/impl/slab.h | 38 +- .../src/include/lx_emul/impl/timer.h | 31 +- .../dde_linux/src/include/lx_emul/impl/wait.h | 6 +- .../dde_linux/src/include/lx_emul/impl/work.h | 48 +- repos/dde_linux/src/include/lx_emul/kernel.h | 7 + repos/dde_linux/src/include/lx_emul/kobject.h | 13 +- repos/dde_linux/src/include/lx_emul/module.h | 2 + repos/dde_linux/src/include/lx_emul/mutex.h | 1 + repos/dde_linux/src/include/lx_emul/pci.h | 3 +- repos/dde_linux/src/include/lx_emul/pm.h | 13 +- .../src/include/lx_emul/scatterlist.h | 5 + .../dde_linux/src/include/lx_emul/spinlock.h | 2 +- repos/dde_linux/src/include/lx_emul/time.h | 15 +- repos/dde_linux/src/include/lx_emul/timer.h | 21 + repos/dde_linux/src/include/lx_emul/types.h | 2 + repos/dde_linux/src/include/lx_emul/work.h | 13 +- .../addr_to_page_mapping.h | 16 +- .../src/include/lx_kit/backend_alloc.h | 33 ++ .../{lx_emul/impl => lx_kit}/internal/debug.h | 8 +- .../impl => lx_kit}/internal/io_port.h | 10 +- .../{lx_emul/impl => lx_kit}/internal/list.h | 14 +- .../impl => lx_kit}/internal/pci_dev.h | 34 +- .../impl => lx_kit}/internal/slab_alloc.h | 12 +- .../lx_kit/internal/slab_backend_alloc.h | 64 +++ .../{lx_emul/impl => lx_kit}/internal/task.h | 41 +- repos/dde_linux/src/include/lx_kit/irq.h | 40 ++ repos/dde_linux/src/include/lx_kit/malloc.h | 63 +++ .../src/include/lx_kit/mapped_io_mem_range.h | 33 ++ .../internal => lx_kit}/pci_dev_registry.h | 16 +- .../dde_linux/src/include/lx_kit/scheduler.h | 75 +++ repos/dde_linux/src/include/lx_kit/timer.h | 84 ++++ repos/dde_linux/src/include/lx_kit/types.h | 25 + repos/dde_linux/src/include/lx_kit/work.h | 67 +++ .../spec/arm/lx_kit/internal/arch_execute.h | 44 ++ .../src/include/spec/arm_v6/lx_emul/barrier.h | 31 ++ .../src/include/spec/arm_v7/lx_emul/barrier.h | 31 ++ .../include/{ => spec}/x86/lx_emul/barrier.h | 0 .../impl => lx_kit}/internal/arch_execute.h | 17 + .../impl => lx_kit}/internal/arch_execute.h | 17 + repos/dde_linux/src/lib/lx/lx.cc | 17 - repos/dde_linux/src/lib/lxip/lxcc_emul.cc | 1 - repos/dde_linux/src/lib/usb/lx_emul.cc | 1 - repos/dde_linux/src/lib/wifi/lxcc_emul.cc | 1 - .../impl/internal/irq.h => lx_kit/irq.cc} | 75 +-- repos/dde_linux/src/lx_kit/malloc.cc | 383 +++++++++++++++ .../mapped_io_mem_range.cc} | 55 ++- .../pci_backend_alloc.h => lx_kit/pci.cc} | 46 +- repos/dde_linux/src/lx_kit/printf.cc | 445 ++++++++++++++++++ .../scheduler.h => lx_kit/scheduler.cc} | 98 ++-- repos/dde_linux/src/lx_kit/spec/arm/setjmp.S | 91 ++++ .../dde_linux/src/lx_kit/spec/x86_32/setjmp.S | 79 ++++ .../dde_linux/src/lx_kit/spec/x86_64/setjmp.S | 93 ++++ .../impl/internal/timer.h => lx_kit/timer.cc} | 221 +++++---- .../impl/internal/work.h => lx_kit/work.cc} | 110 +++-- 77 files changed, 2608 insertions(+), 1186 deletions(-) delete mode 100644 repos/dde_linux/include/lx/extern_c_begin.h delete mode 100644 repos/dde_linux/include/lx/extern_c_end.h delete mode 100644 repos/dde_linux/include/lx/list.h delete mode 100644 repos/dde_linux/include/lx/lx.h delete mode 100644 repos/dde_linux/lib/mk/lx.mk create mode 100644 repos/dde_linux/src/include/lx_emul/completion.h delete mode 100644 repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h delete mode 100644 repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h create mode 100644 repos/dde_linux/src/include/lx_emul/impl/pci_resource.h rename repos/dde_linux/src/include/{lx_emul/impl/internal => lx_kit}/addr_to_page_mapping.h (77%) create mode 100644 repos/dde_linux/src/include/lx_kit/backend_alloc.h rename repos/dde_linux/src/include/{lx_emul/impl => lx_kit}/internal/debug.h (68%) rename repos/dde_linux/src/include/{lx_emul/impl => lx_kit}/internal/io_port.h (89%) rename repos/dde_linux/src/include/{lx_emul/impl => lx_kit}/internal/list.h (82%) rename repos/dde_linux/src/include/{lx_emul/impl => lx_kit}/internal/pci_dev.h (90%) rename repos/dde_linux/src/include/{lx_emul/impl => lx_kit}/internal/slab_alloc.h (83%) create mode 100644 repos/dde_linux/src/include/lx_kit/internal/slab_backend_alloc.h rename repos/dde_linux/src/include/{lx_emul/impl => lx_kit}/internal/task.h (88%) create mode 100644 repos/dde_linux/src/include/lx_kit/irq.h create mode 100644 repos/dde_linux/src/include/lx_kit/malloc.h create mode 100644 repos/dde_linux/src/include/lx_kit/mapped_io_mem_range.h rename repos/dde_linux/src/include/{lx_emul/impl/internal => lx_kit}/pci_dev_registry.h (86%) create mode 100644 repos/dde_linux/src/include/lx_kit/scheduler.h create mode 100644 repos/dde_linux/src/include/lx_kit/timer.h create mode 100644 repos/dde_linux/src/include/lx_kit/types.h create mode 100644 repos/dde_linux/src/include/lx_kit/work.h create mode 100644 repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h create mode 100644 repos/dde_linux/src/include/spec/arm_v6/lx_emul/barrier.h create mode 100644 repos/dde_linux/src/include/spec/arm_v7/lx_emul/barrier.h rename repos/dde_linux/src/include/{ => spec}/x86/lx_emul/barrier.h (100%) rename repos/dde_linux/src/include/spec/x86_32/{lx_emul/impl => lx_kit}/internal/arch_execute.h (69%) rename repos/dde_linux/src/include/spec/x86_64/{lx_emul/impl => lx_kit}/internal/arch_execute.h (70%) delete mode 100644 repos/dde_linux/src/lib/lx/lx.cc rename repos/dde_linux/src/{include/lx_emul/impl/internal/irq.h => lx_kit/irq.cc} (71%) create mode 100644 repos/dde_linux/src/lx_kit/malloc.cc rename repos/dde_linux/src/{include/lx_emul/impl/internal/mapped_io_mem_range.h => lx_kit/mapped_io_mem_range.cc} (71%) rename repos/dde_linux/src/{include/lx_emul/impl/internal/pci_backend_alloc.h => lx_kit/pci.cc} (71%) create mode 100644 repos/dde_linux/src/lx_kit/printf.cc rename repos/dde_linux/src/{include/lx_emul/impl/internal/scheduler.h => lx_kit/scheduler.cc} (73%) create mode 100644 repos/dde_linux/src/lx_kit/spec/arm/setjmp.S create mode 100644 repos/dde_linux/src/lx_kit/spec/x86_32/setjmp.S create mode 100644 repos/dde_linux/src/lx_kit/spec/x86_64/setjmp.S rename repos/dde_linux/src/{include/lx_emul/impl/internal/timer.h => lx_kit/timer.cc} (58%) rename repos/dde_linux/src/{include/lx_emul/impl/internal/work.h => lx_kit/work.cc} (56%) diff --git a/repos/dde_linux/README b/repos/dde_linux/README index 2e8a8d6f9a..e78aa61978 100644 --- a/repos/dde_linux/README +++ b/repos/dde_linux/README @@ -251,3 +251,35 @@ address is not fixed and may change every time the same device is plugged in. The configuration of the USB driver can be changed at runtime to satisfy dynamic configurations or rather policies when using the 'Usb' session interface. + + +lx_kit +###### + +The modular lx_kit seperates the required back end functionality of the Linux +emulation environment from the front end. Thereby each driver can reuse +specific parts or supply more suitable implementations by itself. It is used to +reduce the amount of redundant code in each driver. + +The lx_kit is split into several layers whose structure is as follows: + +The first layer in _repos/dde_linux/src/include/lx_emul_ contains those header +files that provide the structural definitions and function declarations of the +Linux API, e.g. _errno.h_ provides all error code values. The second layer in +_repos/dde_linux/src/include/lx_emul/impl_ contains the implementation of +selected functions, e.g. _slab.h_ provides the implementation of 'kmalloc()'. +The lx_kit back end API is the third layer and provides the _Lx::Malloc_ +interface (_repos/dde_linux/src/include/lx_kit/malloc.h_) which is used to +implement 'kmalloc()'. There are several generic implementations of the lx_kit +interfaces that can be used by a driver. + +A driver typically includes a 'lx_emul/impl/xyz.h' header once directly in its +lx_emul compilation unit. The lx_kit interface files are only included in those +compilation units that use or implement the interface. If a driver wants to use +a generic implementation it must add the source file to its source file list. +The generic implementations are located in _repos/dde_linux/src/lx_kit/_. + +The modular lx_kit still depends on the private _lx_emul.h_ header file that is +tailored to each driver. Since the lx_kit already contains much of the +declarations and definitions that were originally placed in these private +header files, those files can now ommit a large amount of code. diff --git a/repos/dde_linux/include/lx/extern_c_begin.h b/repos/dde_linux/include/lx/extern_c_begin.h deleted file mode 100644 index 8fadabf14f..0000000000 --- a/repos/dde_linux/include/lx/extern_c_begin.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * \brief Include before including Linux headers in C++ - * \author Christian Helmuth - * \date 2014-08-21 - */ - -/* - * Copyright (C) 2014 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#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_ diff --git a/repos/dde_linux/include/lx/extern_c_end.h b/repos/dde_linux/include/lx/extern_c_end.h deleted file mode 100644 index ac6b23f8df..0000000000 --- a/repos/dde_linux/include/lx/extern_c_end.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * \brief Include after including Linux headers in C++ - * \author Christian Helmuth - * \date 2014-08-21 - */ - -/* - * Copyright (C) 2014 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#undef new -#undef class -#undef private - -#pragma GCC diagnostic pop - -} /* extern "C" */ diff --git a/repos/dde_linux/include/lx/list.h b/repos/dde_linux/include/lx/list.h deleted file mode 100644 index c12fdaf1ad..0000000000 --- a/repos/dde_linux/include/lx/list.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * \brief Slightly improved list - * \author Christian Helmuth - * \date 2014-09-25 - */ - -/* - * Copyright (C) 2014 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LIST_H_ -#define _LIST_H_ - -#include - - -namespace Lx { - template class List; - template class List_element; -} - -template -class Lx::List : private Genode::List -{ - private: - - typedef Genode::List 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 -class Lx::List_element : public Lx::List >::Element -{ - private: - - T *_object; - - public: - - List_element(T *object) : _object(object) { } - - T *object() const { return _object; } -}; - -#endif /* _LIST_H_ */ diff --git a/repos/dde_linux/include/lx/lx.h b/repos/dde_linux/include/lx/lx.h deleted file mode 100644 index 74072fd0c5..0000000000 --- a/repos/dde_linux/include/lx/lx.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _INCLUDE__LX__LX_H_ -#define _INCLUDE__LX__LX_H_ - -#include -#include - -typedef genode_int8_t int8_t; -typedef genode_int16_t int16_t; -typedef genode_int32_t int32_t; -typedef genode_uint32_t uint32_t; -typedef genode_int64_t int64_t; -typedef genode_uint8_t uint8_t; -typedef genode_uint16_t uint16_t; -typedef genode_uint64_t uint64_t; -typedef __SIZE_TYPE__ size_t; - -void lx_printf(char const *, ...) __attribute__((format(printf, 1, 2))); -void lx_vprintf(char const *, va_list); - -#define lx_log(doit, msg...) \ - do { \ - if (doit) { \ - lx_printf("%s(): ", __func__); \ - lx_printf(msg); \ - lx_printf("\n"); \ - } \ - } while(0) - - -/********************** - ** linux/compiler.h ** - **********************/ - -#define __printf(a, b) __attribute__((format(printf, a, b))) - - -/************************** - ** linux/compiler-gcc.h ** - **************************/ - -#define __noreturn __attribute__((noreturn)) - -/*************** - ** asm/bug.h ** - ***************/ - -#define WARN_ON(condition) ({ \ - int ret = !!(condition); \ - if (ret) lx_printf("[%s] WARN_ON(" #condition ") ", __func__); \ - ret; }) - -#define WARN(condition, fmt, arg...) ({ \ - int ret = !!(condition); \ - if (ret) lx_printf("[%s] *WARN* " fmt , __func__ , ##arg); \ - ret; }) - -#define BUG() do { \ - lx_printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ - while (1); \ -} while (0) - -#define WARN_ON_ONCE WARN_ON -#define WARN_ONCE WARN - -#define BUG_ON(condition) do { if (condition) BUG(); } while(0) - - -/******************** - ** linux/kernel.h ** - ********************/ - -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("panic()"); - while (1) ; -} - -#endif /* _INCLUDE__LX__LX_H_ */ diff --git a/repos/dde_linux/lib/mk/lx.mk b/repos/dde_linux/lib/mk/lx.mk deleted file mode 100644 index c87e369da4..0000000000 --- a/repos/dde_linux/lib/mk/lx.mk +++ /dev/null @@ -1,5 +0,0 @@ -SRC_CC = lx.cc - -LIB_DIR = $(REP_DIR)/src/lib/lx - -vpath %.cc $(LIB_DIR) diff --git a/repos/dde_linux/src/include/lx_emul/bug.h b/repos/dde_linux/src/include/lx_emul/bug.h index 48fa6e0788..8bf720a661 100644 --- a/repos/dde_linux/src/include/lx_emul/bug.h +++ b/repos/dde_linux/src/include/lx_emul/bug.h @@ -21,12 +21,12 @@ #define WARN_ON(condition) ({ \ int ret = !!(condition); \ - if (ret) lx_printf("[%s] WARN_ON(" #condition ") ", __func__); \ + if (ret) lx_printf("[%s] WARN_ON(" #condition ") \n", __func__); \ ret; }) #define WARN(condition, fmt, arg...) ({ \ int ret = !!(condition); \ - if (ret) lx_printf("[%s] *WARN* " fmt , __func__ , ##arg); \ + if (ret) lx_printf("[%s] *WARN* " fmt " \n", __func__ , ##arg); \ ret; }) #define BUG() do { \ @@ -38,3 +38,9 @@ #define WARN_ONCE WARN #define BUG_ON(condition) do { if (condition) BUG(); } while(0) + +#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") diff --git a/repos/dde_linux/src/include/lx_emul/compiler.h b/repos/dde_linux/src/include/lx_emul/compiler.h index 5a9dbc3a48..ea02abf683 100644 --- a/repos/dde_linux/src/include/lx_emul/compiler.h +++ b/repos/dde_linux/src/include/lx_emul/compiler.h @@ -45,7 +45,7 @@ #define __attribute_const__ #undef __always_inline -#define __always_inline +#define __always_inline inline #undef __unused #define noinline __attribute__((noinline)) @@ -57,6 +57,13 @@ #define __noreturn __attribute__((noreturn)) +#define WRITE_ONCE(x, val) \ +({ \ + barrier(); \ + __builtin_memcpy((void *)&(x), (const void *)&(val), sizeof(x)); \ + barrier(); \ +}) + /************************** ** linux/compiler-gcc.h ** diff --git a/repos/dde_linux/src/include/lx_emul/completion.h b/repos/dde_linux/src/include/lx_emul/completion.h new file mode 100644 index 0000000000..4c525a21cb --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/completion.h @@ -0,0 +1,31 @@ +/* + * \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 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + + +/************************ + ** linux/completion.h ** + ************************/ + +struct completion; + +void complete(struct completion *); +void init_completion(struct completion *c); + +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); diff --git a/repos/dde_linux/src/include/lx_emul/errno.h b/repos/dde_linux/src/include/lx_emul/errno.h index 341242ab7c..6388cabcde 100644 --- a/repos/dde_linux/src/include/lx_emul/errno.h +++ b/repos/dde_linux/src/include/lx_emul/errno.h @@ -45,6 +45,7 @@ enum { ENODEV = 19, EINVAL = 22, ENFILE = 23, + ENOTTY = 25, EFBIG = 27, ENOSPC = 28, ESPIPE = 29, @@ -99,6 +100,7 @@ enum { ENOTUNIQ = 207, ERFKILL = 208, ETIME = 209, + EPROBE_DEFER = 210, MAX_ERRNO = 4095, }; diff --git a/repos/dde_linux/src/include/lx_emul/extern_c_begin.h b/repos/dde_linux/src/include/lx_emul/extern_c_begin.h index a880be1952..2bc440a337 100644 --- a/repos/dde_linux/src/include/lx_emul/extern_c_begin.h +++ b/repos/dde_linux/src/include/lx_emul/extern_c_begin.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -23,8 +23,11 @@ extern "C" { #pragma GCC diagnostic ignored "-Wsign-compare" /* deal with C++ keywords used for identifiers etc. */ -#define private private_ -#define class class_ -#define new new_ +#define private private_ +#define class class_ +#define new new_ +#define delete delete_ +#define namespace namespace_ +#define virtual virtual_ #endif /* __cplusplus */ diff --git a/repos/dde_linux/src/include/lx_emul/extern_c_end.h b/repos/dde_linux/src/include/lx_emul/extern_c_end.h index f9aa11ad11..08c9ac66a5 100644 --- a/repos/dde_linux/src/include/lx_emul/extern_c_end.h +++ b/repos/dde_linux/src/include/lx_emul/extern_c_end.h @@ -13,9 +13,12 @@ #ifdef __cplusplus +#undef delete #undef new #undef class #undef private +#undef namespace +#undef virtual #pragma GCC diagnostic pop diff --git a/repos/dde_linux/src/include/lx_emul/gfp.h b/repos/dde_linux/src/include/lx_emul/gfp.h index 6f385ef8e7..3915b267e1 100644 --- a/repos/dde_linux/src/include/lx_emul/gfp.h +++ b/repos/dde_linux/src/include/lx_emul/gfp.h @@ -45,13 +45,17 @@ enum { __GFP_NO_KSWAPD = 0x00400000u, __GFP_OTHER_NODE = 0x00800000u, __GFP_WRITE = 0x01000000u, + __GFP_DIRECT_RECLAIM = 0x400000u, + __GFP_KSWAPD_RECLAIM = 0x2000000u, GFP_LX_DMA = 0x80000000u, + __GFP_RECLAIM = __GFP_DIRECT_RECLAIM | __GFP_KSWAPD_RECLAIM, GFP_ATOMIC = __GFP_HIGH, GFP_DMA = __GFP_DMA, GFP_DMA32 = __GFP_DMA32, GFP_KERNEL = __GFP_WAIT | __GFP_IO | __GFP_FS, + GFP_TEMPORARY = __GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_RECLAIMABLE, GFP_USER = __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL, GFP_HIGHUSER = __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | __GFP_HIGHMEM, diff --git a/repos/dde_linux/src/include/lx_emul/impl/completion.h b/repos/dde_linux/src/include/lx_emul/impl/completion.h index 5fdac72f66..9e148274f4 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/completion.h +++ b/repos/dde_linux/src/include/lx_emul/impl/completion.h @@ -5,12 +5,15 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ +/* Linux kint includes */ +#include + typedef Lx::Task::List_element Wait_le; typedef Lx::Task::List Wait_list; @@ -21,6 +24,16 @@ void init_waitqueue_head(wait_queue_head_t *wq) } +void remove_wait_queue(wait_queue_head_t *wq, wait_queue_t *wait) +{ + Wait_list *list = static_cast(wq->list); + if (!list) + return; + + destroy(Genode::env()->heap(), list); +} + + int waitqueue_active(wait_queue_head_t *wq) { Wait_list *list = static_cast(wq->list); @@ -59,8 +72,9 @@ void __wait_event(wait_queue_head_t wq) { Wait_list *list = static_cast(wq.list); if (!list) { - PERR("__wait_event(): empty list in wq: %p", &wq); - Genode::sleep_forever(); + PWRN("__wait_event():dd empty list in wq: %p", &wq); + init_waitqueue_head(&wq); + list = static_cast(wq.list); } Lx::Task *task = Lx::scheduler().current(); @@ -80,20 +94,22 @@ void init_completion(struct completion *work) void complete(struct completion *work) { work->done = 1; + + Lx::Task *task = static_cast(work->task); + if (task) { task->unblock(); } } unsigned long wait_for_completion_timeout(struct completion *work, unsigned long timeout) { - __wait_completion(work); - return 1; + return __wait_completion(work, timeout); } int wait_for_completion_interruptible(struct completion *work) { - __wait_completion(work); + __wait_completion(work, 0); return 0; } @@ -101,12 +117,11 @@ int wait_for_completion_interruptible(struct completion *work) long wait_for_completion_interruptible_timeout(struct completion *work, unsigned long timeout) { - __wait_completion(work); - return 1; + return __wait_completion(work, timeout); } void wait_for_completion(struct completion *work) { - __wait_completion(work); + __wait_completion(work, 0); } diff --git a/repos/dde_linux/src/include/lx_emul/impl/delay.h b/repos/dde_linux/src/include/lx_emul/impl/delay.h index 1f9fe5e2e2..02d520bdc2 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/delay.h +++ b/repos/dde_linux/src/include/lx_emul/impl/delay.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -14,7 +14,7 @@ /* Genode includes */ #include -#include +#include /* * XXX We may consider to use the Lx::Timer instead of opening a dedicated diff --git a/repos/dde_linux/src/include/lx_emul/impl/gfp.h b/repos/dde_linux/src/include/lx_emul/impl/gfp.h index b4067f3713..58af5246b7 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/gfp.h +++ b/repos/dde_linux/src/include/lx_emul/impl/gfp.h @@ -5,19 +5,21 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include -#include +/* Linux kit includes */ +#include +#include +#include struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) { - struct page *page = (struct page *)kzalloc(sizeof(struct page) * 1<addr + i*PAGE_SIZE); - page[i].paddr = page->paddr + i*PAGE_SIZE; - atomic_set(&page[i]._count, 1); - } - return page; } diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h b/repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h deleted file mode 100644 index 975f9f2744..0000000000 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * \brief Linux kernel memory allocator - * \author Sebastian Sumpf - * \author Josef Soentgen - * \author Norman Feske - * \date 2014-10-10 - */ - -/* - * Copyright (C) 2014 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LX_EMUL__IMPL__INTERNAL__MALLOC_H_ -#define _LX_EMUL__IMPL__INTERNAL__MALLOC_H_ - -#include -#include - -namespace Lx { class Malloc; } - - -class Lx::Malloc -{ - private: - - enum { - SLAB_START_LOG2 = 3, /* 8 B */ - SLAB_STOP_LOG2 = 16, /* 64 KiB */ - 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; - Slab_alloc *_allocator[NUM_SLABS]; - Genode::Cache_attribute _cached; /* 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_attribute cached) - : - _back_allocator(alloc), _cached(cached), _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] = new (Genode::env()->heap()) - Slab_alloc(1U << i, alloc); - } - - /** - * Alloc in slabs - */ - void *alloc(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) { - PERR("Slab too large %u reqested %zu cached %d", 1U << msb, size, _cached); - return 0; - } - - addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc(); - if (!addr) { - PERR("Failed to get slab for %u", 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)); - } - - 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); - } - - /** - * Belongs given address to this allocator - */ - bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); } - - /** - * Cached memory allocator - */ - static Malloc & mem() - { - static Malloc inst(Slab_backend_alloc::mem(), Genode::CACHED); - return inst; - } - - /** - * DMA memory allocator - */ - static Malloc & dma() - { - static Malloc inst(Slab_backend_alloc::dma(), Genode::UNCACHED); - return inst; - } -}; - -#endif /* _LX_EMUL__IMPL__INTERNAL__MALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h b/repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h deleted file mode 100644 index b4a5485788..0000000000 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h +++ /dev/null @@ -1,175 +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 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LX_EMUL__IMPL__INTERNAL__SLAB_BACKEND_ALLOC_H_ -#define _LX_EMUL__IMPL__INTERNAL__SLAB_BACKEND_ALLOC_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -namespace Lx { - - Genode::Ram_dataspace_capability - backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached); - - void backend_free(Genode::Ram_dataspace_capability cap); - class Slab_backend_alloc; -} - -class Lx::Slab_backend_alloc : public Genode::Allocator, - public Genode::Rm_connection, - public Genode::Region_map_client -{ - private: - - typedef Genode::addr_t addr_t; - - enum { - VM_SIZE = 24 * 1024 * 1024, /* size of VM region to reserve */ - BLOCK_SIZE = 1024 * 1024, /* 1 MiB */ - ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */ - }; - - addr_t _base; /* virt. base address */ - Genode::Cache_attribute _cached; /* 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) { - PERR("Slab-backend exhausted!"); - return false; - } - - try { - _ds_cap[_index] = Lx::backend_alloc(BLOCK_SIZE, _cached); - /* attach at index * BLOCK_SIZE */ - Region_map_client::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0); - - /* lookup phys. address */ - _ds_phys[_index] = Genode::Dataspace_client(_ds_cap[_index]).phys_addr(); - } catch (...) { return false; } - - /* return base + offset in VM area */ - addr_t block_base = _base + (_index * BLOCK_SIZE); - ++_index; - - _range.add_range(block_base, BLOCK_SIZE); - return true; - } - - public: - - Slab_backend_alloc(Genode::Cache_attribute cached) - : - Region_map_client(Rm_connection::create(VM_SIZE)), - _cached(cached), _index(0), _range(Genode::env()->heap()) - { - /* reserver attach us, anywere */ - _base = Genode::env()->rm_session()->attach(dataspace()); - } - - /** - * Allocate - */ - bool alloc(size_t size, void **out_addr) override - { - bool done = _range.alloc(size, out_addr); - - if (done) - return done; - - done = _alloc_block(); - if (!done) { - PERR("Backend allocator exhausted\n"); - return false; - } - - return _range.alloc(size, out_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; } - - /** - * Return phys address for given virtual addr. - */ - addr_t phys_addr(addr_t addr) - { - if (addr < _base || addr >= (_base + VM_SIZE)) - return ~0UL; - - int index = (addr - _base) / BLOCK_SIZE; - - /* physical base of dataspace */ - addr_t phys = _ds_phys[index]; - - if (!phys) - return ~0UL; - - /* add offset */ - phys += (addr - _base - (index * BLOCK_SIZE)); - return phys; - } - - /** - * Translate given physical address to virtual address - * - * \return virtual address, or 0 if no translation exists - */ - 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] + BLOCK_SIZE) - return _base + i*BLOCK_SIZE + phys - _ds_phys[i]; - } - - PWRN("virt_addr(0x%lx) - no translation", phys); - return 0; - } - - addr_t start() const { return _base; } - addr_t end() const { return _base + VM_SIZE - 1; } - - /** - * Cached memory backend allocator - */ - static Slab_backend_alloc & mem() - { - static Slab_backend_alloc inst(Genode::CACHED); - return inst; - } - - /** - * DMA memory backend allocator - */ - static Slab_backend_alloc & dma() - { - static Slab_backend_alloc inst(Genode::UNCACHED); - return inst; - } -}; - -#endif /* _LX_EMUL__IMPL__INTERNAL__SLAB_BACKEND_ALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/io.h b/repos/dde_linux/src/include/lx_emul/impl/io.h index f8cc7cbc2f..644bb23a24 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/io.h +++ b/repos/dde_linux/src/include/lx_emul/impl/io.h @@ -5,14 +5,15 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include -#include +/* Linux kit includes */ +#include +#include void *ioremap(phys_addr_t phys_addr, unsigned long size) diff --git a/repos/dde_linux/src/include/lx_emul/impl/mutex.h b/repos/dde_linux/src/include/lx_emul/impl/mutex.h index bb188853a7..8dc971e162 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/mutex.h +++ b/repos/dde_linux/src/include/lx_emul/impl/mutex.h @@ -5,13 +5,14 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Linux kit includes */ +#include enum { MUTEX_UNLOCKED = 1, MUTEX_LOCKED = 0, MUTEX_WAITERS = -1 }; @@ -24,6 +25,7 @@ void mutex_init(struct mutex *m) m->holder = nullptr; m->waiters = new (Genode::env()->heap()) Lx::Task::List; m->id = ++id; + m->counter = 0; } @@ -36,6 +38,7 @@ void mutex_destroy(struct mutex *m) m->holder = nullptr; m->waiters = nullptr; m->id = 0; + m->counter = 0; } @@ -52,8 +55,8 @@ void mutex_lock(struct mutex *m) Lx::Task *t = reinterpret_cast(m->holder); if (t == Lx::scheduler().current()) { - PERR("Bug: mutex does not support recursive locking"); - Genode::sleep_forever(); + m->counter++; + return; } /* notice that a task waits for the mutex to be released */ @@ -77,6 +80,11 @@ void mutex_unlock(struct mutex *m) Genode::sleep_forever(); } + if (m->counter) { + m->counter--; + return; + } + Lx::Task::List *waiters = static_cast(m->waiters); if (m->state == MUTEX_WAITERS) diff --git a/repos/dde_linux/src/include/lx_emul/impl/pci.h b/repos/dde_linux/src/include/lx_emul/impl/pci.h index f3563a11b4..caa184ab33 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/pci.h +++ b/repos/dde_linux/src/include/lx_emul/impl/pci.h @@ -5,22 +5,17 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Linux kit includes */ +#include +#include -#include -#include - - -extern void pci_dev_put(struct pci_dev *pci_dev) -{ - Genode::destroy(Genode::env()->heap(), pci_dev); -} +#include extern "C" int pci_register_driver(struct pci_driver *driver) @@ -44,9 +39,10 @@ extern "C" int pci_register_driver(struct pci_driver *driver) /* look if we find the device ID in the driver's 'id_table' */ pci_device_id const *matching_id = nullptr; - for (pci_device_id const *id = id_table; id->class_ != 0; id++) + for (pci_device_id const *id = id_table; id->device; id++) { if (id->device == device_id) matching_id = id; + } /* skip device that is not handled by driver */ if (!matching_id) @@ -78,124 +74,3 @@ extern "C" int pci_register_driver(struct pci_driver *driver) return pci_dev ? 0 : -ENODEV; } - - -extern "C" size_t pci_resource_start(struct pci_dev *dev, unsigned bar) -{ - if (bar >= DEVICE_COUNT_RESOURCE) - return 0; - - return dev->resource[bar].start; -} - -extern "C" size_t pci_resource_end(struct pci_dev *dev, unsigned bar) -{ - if (bar >= DEVICE_COUNT_RESOURCE) - return 0; - - return dev->resource[bar].end; -} - -extern "C" size_t pci_resource_len(struct pci_dev *dev, unsigned bar) -{ - size_t start = pci_resource_start(dev, bar); - - if (!start) - return 0; - - return (dev->resource[bar].end - start) + 1; -} - - -extern "C" void *pci_ioremap_bar(struct pci_dev *dev, int bar) -{ - using namespace Genode; - - if (bar >= DEVICE_COUNT_RESOURCE || bar < 0) - return 0; - - return Lx::ioremap(pci_resource_start(dev, bar), - pci_resource_len(dev, bar), - Genode::UNCACHED); -} - - -extern "C" unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar) -{ - if (bar >= DEVICE_COUNT_RESOURCE) - return 0; - - return dev->resource[bar].flags; -} - - -extern "C" int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int, int where, u8 *val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; - dev->config_read(where, val); - return 0; -} - - -extern "C" int pci_bus_read_config_word(struct pci_bus *bus, unsigned int, int where, u16 *val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; - dev->config_read(where, val); - return 0; -} - - -extern "C" int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int, int where, u32 *val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; - dev->config_read(where, val); - return 0; -} - - -extern "C" int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int, int where, u8 val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; - dev->config_write(where, val); - return 0; -} - - -extern "C" int pci_bus_write_config_word(struct pci_bus *bus, unsigned int, int where, u16 val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; - dev->config_write(where, val); - return 0; -} - - -extern "C" int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int, int where, u32 val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; - dev->config_write(where, val); - return 0; -} - - -extern "C" const char *pci_name(const struct pci_dev *pdev) -{ - /* simply return driver name */ - return "dummy"; -} - - -extern "C" int pcie_capability_read_word(struct pci_dev *pdev, int pos, u16 *val) -{ - Lx::Pci_dev *dev = (Lx::Pci_dev *)pdev->bus; - switch (pos) { - case PCI_EXP_LNKCTL: - dev->config_read(pdev->pcie_cap + PCI_EXP_LNKCTL, val); - return 0; - break; - default: - break; - } - - return 1; -} -// diff --git a/repos/dde_linux/src/include/lx_emul/impl/pci_resource.h b/repos/dde_linux/src/include/lx_emul/impl/pci_resource.h new file mode 100644 index 0000000000..2e74f4bd81 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/pci_resource.h @@ -0,0 +1,142 @@ +/* + * \brief Implementation of linux/pci.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Linux kit includes */ +#include +#include + + +extern void pci_dev_put(struct pci_dev *pci_dev) +{ + Genode::destroy(Genode::env()->heap(), pci_dev); +} + + +extern "C" size_t pci_resource_start(struct pci_dev *dev, unsigned bar) +{ + if (bar >= DEVICE_COUNT_RESOURCE) + return 0; + + return dev->resource[bar].start; +} + +extern "C" size_t pci_resource_end(struct pci_dev *dev, unsigned bar) +{ + if (bar >= DEVICE_COUNT_RESOURCE) + return 0; + + return dev->resource[bar].end; +} + +extern "C" size_t pci_resource_len(struct pci_dev *dev, unsigned bar) +{ + size_t start = pci_resource_start(dev, bar); + + if (!start) + return 0; + + return (dev->resource[bar].end - start) + 1; +} + + +extern "C" void *pci_ioremap_bar(struct pci_dev *dev, int bar) +{ + using namespace Genode; + + if (bar >= DEVICE_COUNT_RESOURCE || bar < 0) + return 0; + + return Lx::ioremap(pci_resource_start(dev, bar), + pci_resource_len(dev, bar), + Genode::UNCACHED); +} + + +extern "C" unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar) +{ + if (bar >= DEVICE_COUNT_RESOURCE) + return 0; + + return dev->resource[bar].flags; +} + + +extern "C" int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int, int where, u8 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_read(where, val); + return 0; +} + + +extern "C" int pci_bus_read_config_word(struct pci_bus *bus, unsigned int, int where, u16 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_read(where, val); + return 0; +} + + +extern "C" int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int, int where, u32 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_read(where, val); + return 0; +} + + +extern "C" int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int, int where, u8 val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_write(where, val); + return 0; +} + + +extern "C" int pci_bus_write_config_word(struct pci_bus *bus, unsigned int, int where, u16 val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_write(where, val); + return 0; +} + + +extern "C" int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int, int where, u32 val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_write(where, val); + return 0; +} + + +extern "C" const char *pci_name(const struct pci_dev *pdev) +{ + /* simply return driver name */ + return "dummy"; +} + + +extern "C" int pcie_capability_read_word(struct pci_dev *pdev, int pos, u16 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)pdev->bus; + switch (pos) { + case PCI_EXP_LNKCTL: + dev->config_read(pdev->pcie_cap + PCI_EXP_LNKCTL, val); + return 0; + break; + default: + break; + } + + return 1; +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/sched.h b/repos/dde_linux/src/include/lx_emul/impl/sched.h index 7a80d43d40..5b53fa4ff8 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/sched.h +++ b/repos/dde_linux/src/include/lx_emul/impl/sched.h @@ -5,13 +5,14 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Linux kit includes */ +#include static void unblock_task(unsigned long task) diff --git a/repos/dde_linux/src/include/lx_emul/impl/slab.h b/repos/dde_linux/src/include/lx_emul/impl/slab.h index 8d37e7fb04..8d16aef9e6 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/slab.h +++ b/repos/dde_linux/src/include/lx_emul/impl/slab.h @@ -5,13 +5,14 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Linux kit includes */ +#include void *kmalloc(size_t size, gfp_t flags) @@ -21,8 +22,15 @@ void *kmalloc(size_t size, gfp_t flags) if (flags & __GFP_DMA32) PWRN("GFP_DMA32 memory (below 4 GiB) requested (%p)", __builtin_return_address(0)); - void *addr = flags & GFP_LX_DMA ? Lx::Malloc::dma().alloc(size, 12) - : Lx::Malloc::mem().alloc(size); + void *addr = nullptr; + + if (flags & GFP_LX_DMA) { + addr = Lx::Malloc::dma().alloc(size, 12); + } else { + addr = (size > (1 << Lx::Malloc::MAX_SIZE_LOG2)) + ? Lx::Malloc::mem().alloc_large(size) + : Lx::Malloc::mem().alloc(size); + } if ((Genode::addr_t)addr & 0x3) PERR("unaligned kmalloc %lx", (Genode::addr_t)addr); @@ -137,35 +145,39 @@ void *kmemdup(const void *src, size_t size, gfp_t flags) struct kmem_cache : Lx::Slab_alloc { - kmem_cache(size_t object_size, bool dma) + 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()) + : 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 *)) { - if (ctor) { - PERR("%s: ctor not supported", __func__); - return nullptr; - } - /* * Copied from wifi_drv. * * XXX SLAB_LX_DMA is never used anywhere else, remove it? */ enum { SLAB_LX_DMA = 0x80000000ul, }; - return new (Genode::env()->heap()) kmem_cache(size, flags & SLAB_LX_DMA); + return new (Genode::env()->heap()) kmem_cache(size, flags & SLAB_LX_DMA, ctor); } void * kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags) { - return (void *)cache->alloc(); + void *addr = (void *)cache->alloc(); + if (addr && cache->ctor) { cache->ctor(addr); } + return addr; } diff --git a/repos/dde_linux/src/include/lx_emul/impl/timer.h b/repos/dde_linux/src/include/lx_emul/impl/timer.h index 13a922464a..6ad73bcae1 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/timer.h +++ b/repos/dde_linux/src/include/lx_emul/impl/timer.h @@ -5,13 +5,14 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Linux kit includes */ +#include void init_timer(struct timer_list *timer) { } @@ -20,7 +21,7 @@ void init_timer(struct timer_list *timer) { } int mod_timer(struct timer_list *timer, unsigned long expires) { if (!Lx::timer().find(timer)) - Lx::timer().add(timer); + Lx::timer().add(timer, Lx::Timer::LIST); return Lx::timer().schedule(timer, expires); } @@ -50,3 +51,27 @@ int del_timer(struct timer_list *timer) 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.tv64 / (NSEC_PER_MSEC * HZ); + + if (!Lx::timer().find(timer)) + Lx::timer().add(timer, Lx::Timer::HR); + + return Lx::timer().schedule(timer, expires); +} + + +int hrtimer_cancel(struct hrtimer *timer) +{ + int rv = Lx::timer().del(timer); + Lx::timer().schedule_next(); + + return rv; +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/wait.h b/repos/dde_linux/src/include/lx_emul/impl/wait.h index df0f74053d..c022790360 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/wait.h +++ b/repos/dde_linux/src/include/lx_emul/impl/wait.h @@ -5,12 +5,16 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ +/* Linux kit includes */ +#include + + void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *w, int state) { if (!q) { diff --git a/repos/dde_linux/src/include/lx_emul/impl/work.h b/repos/dde_linux/src/include/lx_emul/impl/work.h index 1069addc7a..6308d84e6d 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/work.h +++ b/repos/dde_linux/src/include/lx_emul/impl/work.h @@ -5,37 +5,69 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#include +/* Linux kit includes */ +#include +#include int schedule_work(struct work_struct *work) { - Lx::Work::work_queue().schedule(work); - Lx::Work::work_queue().unblock(); + 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; + + /* 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; +} + + static void _schedule_delayed_work(unsigned long w) { - schedule_work((struct work_struct *)w); + delayed_work *work = (delayed_work *)w; + workqueue_struct *wq = work->wq; + + /* check for separate work queue task */ + if (wq && wq->task) { + Lx::Work *lx_work = (Lx::Work *)wq->task; + lx_work->schedule_delayed(work, 0); + lx_work->unblock(); + } else { + Lx::Work::work_queue().schedule_delayed(work, 0); + Lx::Work::work_queue().unblock(); + } } 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) { - schedule_work(&dwork->work); + _schedule_delayed_work((unsigned long)dwork); } else { - setup_timer(&dwork->timer, _schedule_delayed_work, (unsigned long)&dwork->work); + setup_timer(&dwork->timer, _schedule_delayed_work, (unsigned long)dwork); mod_timer(&dwork->timer, delay); } return true; @@ -44,7 +76,7 @@ bool queue_delayed_work(struct workqueue_struct *wq, int schedule_delayed_work(struct delayed_work *dwork, unsigned long delay) { - return queue_delayed_work(system_wq, dwork, delay); + return queue_delayed_work(dwork->wq ? dwork->wq : system_wq, dwork, delay); } diff --git a/repos/dde_linux/src/include/lx_emul/kernel.h b/repos/dde_linux/src/include/lx_emul/kernel.h index 7cc116d916..4c75d04666 100644 --- a/repos/dde_linux/src/include/lx_emul/kernel.h +++ b/repos/dde_linux/src/include/lx_emul/kernel.h @@ -20,6 +20,7 @@ *********************/ #define IS_ENABLED(x) x +#define IS_BUILTIN(x) x /******************** @@ -39,6 +40,12 @@ #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; diff --git a/repos/dde_linux/src/include/lx_emul/kobject.h b/repos/dde_linux/src/include/lx_emul/kobject.h index e01981868b..5f57e88147 100644 --- a/repos/dde_linux/src/include/lx_emul/kobject.h +++ b/repos/dde_linux/src/include/lx_emul/kobject.h @@ -24,13 +24,24 @@ 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 kobject *parent; }; +struct kobject +{ + struct kset *kset; + struct kobj_type *ktype; + struct kobject *parent; + const char *name; +}; + struct kobj_uevent_env { char buf[32]; diff --git a/repos/dde_linux/src/include/lx_emul/module.h b/repos/dde_linux/src/include/lx_emul/module.h index f719929ec1..e21db30c31 100644 --- a/repos/dde_linux/src/include/lx_emul/module.h +++ b/repos/dde_linux/src/include/lx_emul/module.h @@ -65,6 +65,8 @@ int try_module_get(struct module *); #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) diff --git a/repos/dde_linux/src/include/lx_emul/mutex.h b/repos/dde_linux/src/include/lx_emul/mutex.h index caf5686b30..5635d2d98a 100644 --- a/repos/dde_linux/src/include/lx_emul/mutex.h +++ b/repos/dde_linux/src/include/lx_emul/mutex.h @@ -24,6 +24,7 @@ struct mutex int state; void *holder; void *waiters; + unsigned counter; unsigned id; /* for debugging */ }; diff --git a/repos/dde_linux/src/include/lx_emul/pci.h b/repos/dde_linux/src/include/lx_emul/pci.h index dac438737c..dc88a3be48 100644 --- a/repos/dde_linux/src/include/lx_emul/pci.h +++ b/repos/dde_linux/src/include/lx_emul/pci.h @@ -51,8 +51,9 @@ struct pci_driver { char *name; const struct pci_device_id *id_table; int (*probe) (struct pci_dev *dev, - const struct pci_device_id *id); + const struct pci_device_id *id); void (*remove) (struct pci_dev *dev); + void (*shutdown) (struct pci_dev *dev); struct device_driver driver; }; diff --git a/repos/dde_linux/src/include/lx_emul/pm.h b/repos/dde_linux/src/include/lx_emul/pm.h index 314a96cb62..e519d878ca 100644 --- a/repos/dde_linux/src/include/lx_emul/pm.h +++ b/repos/dde_linux/src/include/lx_emul/pm.h @@ -23,7 +23,11 @@ struct device; typedef struct pm_message { int event; } pm_message_t; -struct dev_pm_info { pm_message_t power_state; }; +struct dev_pm_info +{ + pm_message_t power_state; + bool is_prepared; +}; struct dev_pm_ops { int (*suspend)(struct device *dev); @@ -34,10 +38,17 @@ struct dev_pm_ops { 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 diff --git a/repos/dde_linux/src/include/lx_emul/scatterlist.h b/repos/dde_linux/src/include/lx_emul/scatterlist.h index f0a3df8caf..c7e166dadf 100644 --- a/repos/dde_linux/src/include/lx_emul/scatterlist.h +++ b/repos/dde_linux/src/include/lx_emul/scatterlist.h @@ -36,6 +36,7 @@ struct sg_table { struct scatterlist *sgl; /* the list */ unsigned int nents; /* number of mapped entries */ + unsigned int orig_nents; }; struct sg_page_iter @@ -56,6 +57,10 @@ struct sg_mapping_iter 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, diff --git a/repos/dde_linux/src/include/lx_emul/spinlock.h b/repos/dde_linux/src/include/lx_emul/spinlock.h index ee63414b1e..f15fc19eaa 100644 --- a/repos/dde_linux/src/include/lx_emul/spinlock.h +++ b/repos/dde_linux/src/include/lx_emul/spinlock.h @@ -41,4 +41,4 @@ int spin_trylock(spinlock_t *lock); ** linux/spinlock_types.h ** ****************************/ -#define __SPIN_LOCK_UNLOCKED(x) 0 +#define __SPIN_LOCK_UNLOCKED(x) {0} diff --git a/repos/dde_linux/src/include/lx_emul/time.h b/repos/dde_linux/src/include/lx_emul/time.h index 80b1bcd4f1..623ca9b9d8 100644 --- a/repos/dde_linux/src/include/lx_emul/time.h +++ b/repos/dde_linux/src/include/lx_emul/time.h @@ -24,7 +24,12 @@ struct timespec { long tv_nsec; }; -struct timeval { }; +struct timeval +{ + __kernel_time_t tv_sec; + __kernel_suseconds_t tv_usec; +}; + struct timespec current_kernel_time(void); void do_gettimeofday(struct timeval *tv); @@ -74,7 +79,13 @@ static inline ktime_t ktime_add(const ktime_t a, const ktime_t b) s64 ktime_us_delta(const ktime_t later, const ktime_t earlier); -struct timeval ktime_to_timeval(const ktime_t); +static inline struct timeval ktime_to_timeval(const ktime_t kt) +{ + struct timeval tv; + tv.tv_sec = kt.tv64 / NSEC_PER_SEC; + tv.tv_usec = (kt.tv64 - (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); diff --git a/repos/dde_linux/src/include/lx_emul/timer.h b/repos/dde_linux/src/include/lx_emul/timer.h index 90990447e3..2ce8b8b3d7 100644 --- a/repos/dde_linux/src/include/lx_emul/timer.h +++ b/repos/dde_linux/src/include/lx_emul/timer.h @@ -48,3 +48,24 @@ static inline void add_timer(struct timer_list *timer) { mod_timer(timer, timer- static inline int del_timer_sync(struct timer_list * timer) { return del_timer(timer); } + + +/********************* + ** linux/hrtimer.h ** + *********************/ + +enum hrtimer_mode { HRTIMER_MODE_ABS = 0 }; +enum hrtimer_restart { HRTIMER_NORESTART = 0 }; + +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 *); diff --git a/repos/dde_linux/src/include/lx_emul/types.h b/repos/dde_linux/src/include/lx_emul/types.h index d60d0310ff..b7f15d8fd7 100644 --- a/repos/dde_linux/src/include/lx_emul/types.h +++ b/repos/dde_linux/src/include/lx_emul/types.h @@ -90,7 +90,9 @@ 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; diff --git a/repos/dde_linux/src/include/lx_emul/work.h b/repos/dde_linux/src/include/lx_emul/work.h index e1cd41917f..559ebd0606 100644 --- a/repos/dde_linux/src/include/lx_emul/work.h +++ b/repos/dde_linux/src/include/lx_emul/work.h @@ -31,11 +31,15 @@ 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); @@ -73,7 +77,6 @@ bool flush_work_sync(struct work_struct *work); /* dummy for queue_delayed_work call in storage/usb.c */ #define system_freezable_wq 0 -struct workqueue_struct { unsigned unused; }; struct workqueue_struct *create_singlethread_workqueue(const char *name); struct workqueue_struct *alloc_ordered_workqueue(const char *fmt, unsigned int flags, ...) __printf(1, 3); @@ -135,8 +138,14 @@ enum { ** linux/wait.h ** ******************/ +typedef struct wait_queue wait_queue_t; +typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key); typedef struct wait_queue_head { void *list; } wait_queue_head_t; -typedef struct wait_queue { unsigned unused; } wait_queue_t; +struct wait_queue +{ + wait_queue_func_t func; + void *private; +}; #define DEFINE_WAIT(name) \ wait_queue_t name; diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/addr_to_page_mapping.h b/repos/dde_linux/src/include/lx_kit/addr_to_page_mapping.h similarity index 77% rename from repos/dde_linux/src/include/lx_emul/impl/internal/addr_to_page_mapping.h rename to repos/dde_linux/src/include/lx_kit/addr_to_page_mapping.h index 4d507eba83..af7268c35b 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/addr_to_page_mapping.h +++ b/repos/dde_linux/src/include/lx_kit/addr_to_page_mapping.h @@ -7,26 +7,26 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__ADDR_TO_PAGE_MAPPING_H_ -#define _LX_EMUL__IMPL__INTERNAL__ADDR_TO_PAGE_MAPPING_H_ +#ifndef _LX_KIT__ADDR_TO_PAGE_MAPPING_H_ +#define _LX_KIT__ADDR_TO_PAGE_MAPPING_H_ /* Linux emulation environment includes */ -#include -#include +#include +#include namespace Lx { class Addr_to_page_mapping; } -class Lx::Addr_to_page_mapping : public Lx::List::Element +class Lx::Addr_to_page_mapping : public Lx_kit::List::Element { private: - unsigned long _addr { 0 }; + unsigned long _addr { 0 }; struct page *_page { 0 }; static Genode::List *_list() @@ -75,4 +75,4 @@ class Lx::Addr_to_page_mapping : public Lx::List::Element }; -#endif /* _LX_EMUL__IMPL__INTERNAL__ADDR_TO_PAGE_MAPPING_H_ */ +#endif /* _LX_KIT__ADDR_TO_PAGE_MAPPING_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/backend_alloc.h b/repos/dde_linux/src/include/lx_kit/backend_alloc.h new file mode 100644 index 0000000000..9d0ae55fda --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/backend_alloc.h @@ -0,0 +1,33 @@ + +/* + * \brief Back-end allocator + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 + + +namespace Lx { + + using namespace Genode; + + Ram_dataspace_capability backend_alloc(addr_t size, + Cache_attribute cached); + void backend_free(Ram_dataspace_capability cap); +} + +#endif /* _LX_KIT__BACKEND_ALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/debug.h b/repos/dde_linux/src/include/lx_kit/internal/debug.h similarity index 68% rename from repos/dde_linux/src/include/lx_emul/impl/internal/debug.h rename to repos/dde_linux/src/include/lx_kit/internal/debug.h index 5248d6beaf..a034a857e5 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/debug.h +++ b/repos/dde_linux/src/include/lx_kit/internal/debug.h @@ -7,17 +7,17 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__DEBUG_H_ -#define _LX_EMUL__IMPL__INTERNAL__DEBUG_H_ +#ifndef _LX_KIT__INTERNAL__DEBUG_H_ +#define _LX_KIT__INTERNAL__DEBUG_H_ #ifndef PDBGV #define PDBGV(...) do { if (verbose) PDBG(__VA_ARGS__); } while (0) #endif -#endif /* _LX_EMUL__IMPL__INTERNAL__DEBUG_H_ */ +#endif /* _LX_KIT__INTERNAL__DEBUG_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/io_port.h b/repos/dde_linux/src/include/lx_kit/internal/io_port.h similarity index 89% rename from repos/dde_linux/src/include/lx_emul/impl/internal/io_port.h rename to repos/dde_linux/src/include/lx_kit/internal/io_port.h index 2975dcd97c..81efc24715 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/io_port.h +++ b/repos/dde_linux/src/include/lx_kit/internal/io_port.h @@ -6,14 +6,14 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__IO_PORT_H_ -#define _LX_EMUL__IMPL__INTERNAL__IO_PORT_H_ +#ifndef _LX_KIT__INTERNAL__IO_PORT_H_ +#define _LX_KIT__INTERNAL__IO_PORT_H_ /* Genode includes */ #include @@ -68,7 +68,7 @@ class Lx::Io_port bool in(unsigned port, POD *val) { if (!_valid(port)) - return false;; + return false; switch (sizeof(POD)) { case 1: *val = _port->inb(port); break; @@ -80,4 +80,4 @@ class Lx::Io_port } }; -#endif /* _LX_EMUL__IMPL__INTERNAL__IO_PORT_H_ */ +#endif /* _LX_KIT__INTERNAL__IO_PORT_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/list.h b/repos/dde_linux/src/include/lx_kit/internal/list.h similarity index 82% rename from repos/dde_linux/src/include/lx_emul/impl/internal/list.h rename to repos/dde_linux/src/include/lx_kit/internal/list.h index e01913ece1..499576fde3 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/list.h +++ b/repos/dde_linux/src/include/lx_kit/internal/list.h @@ -5,25 +5,25 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__LIST_H_ -#define _LX_EMUL__IMPL__INTERNAL__LIST_H_ +#ifndef _LX_KIT__INTERNAL__LIST_H_ +#define _LX_KIT__INTERNAL__LIST_H_ #include -namespace Lx { +namespace Lx_kit { template class List; template class List_element; } template -class Lx::List : private Genode::List +class Lx_kit::List : private Genode::List { private: @@ -86,7 +86,7 @@ class Lx::List : private Genode::List template -class Lx::List_element : public Lx::List >::Element +class Lx_kit::List_element : public Lx_kit::List >::Element { private: @@ -99,4 +99,4 @@ class Lx::List_element : public Lx::List >::Element T *object() const { return _object; } }; -#endif /* _LX_EMUL__IMPL__INTERNAL__LIST_H_ */ +#endif /* _LX_KIT__INTERNAL__LIST_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev.h b/repos/dde_linux/src/include/lx_kit/internal/pci_dev.h similarity index 90% rename from repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev.h rename to repos/dde_linux/src/include/lx_kit/internal/pci_dev.h index 8a48166cdf..8549e55b6a 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev.h +++ b/repos/dde_linux/src/include/lx_kit/internal/pci_dev.h @@ -13,8 +13,8 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__PCI_DEV_H_ -#define _LX_EMUL__IMPL__INTERNAL__PCI_DEV_H_ +#ifndef _LX_KIT__INTERNAL__PCI_DEV_H_ +#define _LX_KIT__INTERNAL__PCI_DEV_H_ /* Genode includes */ #include @@ -25,9 +25,9 @@ #include /* Linux emulation environment includes */ -#include -#include -#include +#include +#include +#include namespace Lx { @@ -45,7 +45,7 @@ namespace Lx { } -class Lx::Pci_dev : public pci_dev, public Lx::List::Element +class Lx::Pci_dev : public pci_dev, public Lx_kit::List::Element { private: @@ -76,6 +76,12 @@ class Lx::Pci_dev : public pci_dev, public Lx::List::Element } } + static unsigned _virq_num() + { + static unsigned instance = 128; + return ++instance; + } + public: /** @@ -99,8 +105,18 @@ class Lx::Pci_dev : public pci_dev, public Lx::List::Element this->dev.dma_mask = &this->dev._dma_mask_buf; this->dev.coherent_dma_mask = ~0; - /* read interrupt line */ - this->irq = _client.config_read(IRQ, Device::ACCESS_8BIT); + enum { USB_SUB_CLASS = 0xc0300 }; + + /* + * For USB we generate virtual IRQ numbers so we can identify the device + * later on + */ + if ((class_ & ~0xffU) == USB_SUB_CLASS) + this->irq = _virq_num(); + else + /* read interrupt line */ + this->irq = _client.config_read(IRQ, Device::ACCESS_8BIT); + /* hide ourselfs in bus structure */ this->bus = (struct pci_bus *)this; @@ -261,4 +277,4 @@ void Lx::for_each_pci_device(FUNC const &func) } } -#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_DEV_H_ */ +#endif /* _LX_KIT__INTERNAL__PCI_DEV_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/slab_alloc.h b/repos/dde_linux/src/include/lx_kit/internal/slab_alloc.h similarity index 83% rename from repos/dde_linux/src/include/lx_emul/impl/internal/slab_alloc.h rename to repos/dde_linux/src/include/lx_kit/internal/slab_alloc.h index 3b17fe6c57..8fa8bf6050 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/slab_alloc.h +++ b/repos/dde_linux/src/include/lx_kit/internal/slab_alloc.h @@ -13,15 +13,16 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__SLAB_ALLOC_H_ -#define _LX_EMUL__IMPL__INTERNAL__SLAB_ALLOC_H_ +#ifndef _LX_KIT__INTERAL__SLAB_ALLOC_H_ +#define _LX_KIT__INTERAL__SLAB_ALLOC_H_ /* Genode includes */ #include #include /* Linux emulation environment includes */ -#include +#include +#include namespace Lx { class Slab_alloc; } @@ -50,9 +51,6 @@ class Lx::Slab_alloc : public Genode::Slab _object_size(object_size) { } - /** - * Convenience slabe-entry allocation - */ Genode::addr_t alloc() { Genode::addr_t result; @@ -65,4 +63,4 @@ class Lx::Slab_alloc : public Genode::Slab } }; -#endif /* _LX_EMUL__IMPL__INTERNAL__SLAB_ALLOC_H_ */ +#endif /* _LX_KIT__INTERAL__SLAB_ALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/internal/slab_backend_alloc.h b/repos/dde_linux/src/include/lx_kit/internal/slab_backend_alloc.h new file mode 100644 index 0000000000..bb4dcaf13c --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/internal/slab_backend_alloc.h @@ -0,0 +1,64 @@ + +/* + * \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 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 + +/* Linux emulation environment includes */ +#include + + +namespace Lx { + + using Lx_kit::addr_t; + + class Slab_backend_alloc; +} + + +class Lx::Slab_backend_alloc : public Genode::Allocator +{ + public: + + /** + * Allocate + */ + virtual bool alloc(size_t size, void **out_addr) = 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_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/task.h b/repos/dde_linux/src/include/lx_kit/internal/task.h similarity index 88% rename from repos/dde_linux/src/include/lx_emul/impl/internal/task.h rename to repos/dde_linux/src/include/lx_kit/internal/task.h index 4a2df7608f..d4811b044e 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/task.h +++ b/repos/dde_linux/src/include/lx_kit/internal/task.h @@ -13,29 +13,33 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__TASK_H_ -#define _LX_EMUL__IMPL__INTERNAL__TASK_H_ - -/* libc includes */ -#include +#ifndef _LX_KIT__INTERNAL__TASK_H_ +#define _LX_KIT__INTERNAL__TASK_H_ /* Genode includes */ +#include +#include #include /* Linux emulation environment includes */ -#include -#include +#include +#include + +#if !defined(USE_INTERNAL_SETJMP) +/* libc includes */ +#include +#endif /* USE_INTERNAL_SETJMP */ + namespace Lx { - class Scheduler; class Task; } /** * Allows pseudo-parallel execution of functions */ -class Lx::Task : public Lx::List::Element +class Lx::Task : public Lx_kit::List::Element { public: @@ -61,16 +65,16 @@ class Lx::Task : public Lx::List::Element /** * List element type */ - typedef Lx::List_element List_element; + typedef Lx_kit::List_element List_element; /** * List type */ - typedef Lx::List List; + typedef Lx_kit::List List; private: - bool verbose = true; + bool verbose = false; State _state = STATE_INIT; @@ -106,16 +110,14 @@ class Lx::Task : public Lx::List::Element List_element _wait_le { this }; bool _wait_le_enqueued { false }; - inline void _deinit(); - public: - inline Task(void (*func)(void*), void *arg, char const *name, - Priority priority, Scheduler &scheduler); + Task(void (*func)(void*), void *arg, char const *name, + Priority priority, Scheduler &scheduler); - virtual ~Task() { _deinit(); } + virtual ~Task(); - State state() const { return _state; } + State state() const { return _state; } Priority priority() const { return _priority; } void wait_enqueue(List *list) @@ -254,4 +256,5 @@ class Lx::Task : public Lx::List::Element char const *name() { return _name; } }; -#endif /* _LX_EMUL__IMPL__INTERNAL__TASK_H_ */ + +#endif /* _LX_KIT__INTERNAL__TASK_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/irq.h b/repos/dde_linux/src/include/lx_kit/irq.h new file mode 100644 index 0000000000..98b232f53a --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/irq.h @@ -0,0 +1,40 @@ +/* + * \brief Signal context for IRQ's + * \author Josef Soentgen + * \author Christian Helmuth + * \author Stefan Kalkowski + * \date 2014-10-14 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 +#include + + +namespace Lx { class Irq; } + +class Lx::Irq +{ + public: + + static Irq &irq(Server::Entrypoint *ep = nullptr, + Genode::Allocator *alloc = nullptr); + + /** + * Request an IRQ + */ + virtual void request_irq(Platform::Device &dev, irq_handler_t handler, + void *dev_id, irq_handler_t thread_fn = 0) = 0; +}; + +#endif /* _LX_KIT__IRQ_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/malloc.h b/repos/dde_linux/src/include/lx_kit/malloc.h new file mode 100644 index 0000000000..ca4547d812 --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/malloc.h @@ -0,0 +1,63 @@ +/* + * \brief Linux kernel memory allocator + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 +#include +#include + + +namespace Lx { + + class Malloc; +} + + +class Lx::Malloc +{ + public: + + enum { MAX_SIZE_LOG2 = 16 /* 64 KiB */ }; + + /** + * Alloc in slabs + */ + virtual void *alloc(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; + + static Malloc &mem(); + static Malloc &dma(); +}; + +#endif /* _LX_KIT__MALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/mapped_io_mem_range.h b/repos/dde_linux/src/include/lx_kit/mapped_io_mem_range.h new file mode 100644 index 0000000000..e5fc9eff3f --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/mapped_io_mem_range.h @@ -0,0 +1,33 @@ +/* + * \brief Representation of a locally-mapped MMIO range + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 + +/* Linux emulation environment includes */ +#include + +namespace Lx { + + using namespace Genode; + + void *ioremap(addr_t, unsigned long, Cache_attribute); + void iounmap(volatile void*); + Dataspace_capability ioremap_lookup(addr_t, size_t); +} + + +#endif /* _LX_KIT__MAPPED_IO_MEM_RANGE_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h b/repos/dde_linux/src/include/lx_kit/pci_dev_registry.h similarity index 86% rename from repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h rename to repos/dde_linux/src/include/lx_kit/pci_dev_registry.h index 43375a98f6..3cc0f5da3a 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h +++ b/repos/dde_linux/src/include/lx_kit/pci_dev_registry.h @@ -11,11 +11,11 @@ * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ -#define _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ +#ifndef _LX_KIT__PCI_DEV_REGISTRY_H_ +#define _LX_KIT__PCI_DEV_REGISTRY_H_ /* Linux emulation environment includes */ -#include +#include namespace Lx { @@ -34,7 +34,7 @@ class Lx::Pci_dev_registry { private: - List _devs; + Lx_kit::List _devs; public: @@ -44,7 +44,9 @@ class Lx::Pci_dev_registry _devs.insert(pci_dev); } - Genode::Io_mem_dataspace_capability io_mem(resource_size_t phys, + Pci_dev* first() { return _devs.first(); } + + Genode::Io_mem_dataspace_capability io_mem(Genode::addr_t phys, Genode::Cache_attribute cache_attribute, Genode::size_t size, Genode::addr_t &offset) @@ -72,7 +74,7 @@ class Lx::Pci_dev_registry return Genode::Io_mem_session_client(io_mem_cap).dataspace(); } - PERR("Device using i/o memory of address %zx is unknown", phys); + PERR("Device using i/o memory of address %lx is unknown", phys); return Genode::Io_mem_dataspace_capability(); } @@ -102,4 +104,4 @@ class Lx::Pci_dev_registry } }; -#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ */ +#endif /* _LX_KIT__PCI_DEV_REGISTRY_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/scheduler.h b/repos/dde_linux/src/include/lx_kit/scheduler.h new file mode 100644 index 0000000000..79aa2cdabb --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/scheduler.h @@ -0,0 +1,75 @@ +/* + * \brief Scheduler for executing Lx::Task objects + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _LX_KIT__SCHEDULER_H_ +#define _LX_KIT__SCHEDULER_H_ + +namespace Lx { + + class Task; + class Scheduler; + + /** + * Return singleton instance of the scheduler + * + * Implementation must be provided by the driver. + */ + Scheduler &scheduler(); +} + + +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 + + +#endif /* _LX_KIT__SCHEDULER_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/timer.h b/repos/dde_linux/src/include/lx_kit/timer.h new file mode 100644 index 0000000000..959db89710 --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/timer.h @@ -0,0 +1,84 @@ +/* + * \brief Timer + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 + +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(Server::Entrypoint *ep = 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; +}; + + +#endif /* _LX_KIT__TIMER_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/types.h b/repos/dde_linux/src/include/lx_kit/types.h new file mode 100644 index 0000000000..a9a847dc81 --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/types.h @@ -0,0 +1,25 @@ +/* + * \brief Linux kit types + * \author Josef Soentgen + * \date 2016-03-18 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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 + +namespace Lx_kit { + typedef Genode::size_t size_t; + typedef Genode::addr_t addr_t; +} + +#endif /* _LX_KIT__TYPES_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/work.h b/repos/dde_linux/src/include/lx_kit/work.h new file mode 100644 index 0000000000..3a35051c1a --- /dev/null +++ b/repos/dde_linux/src/include/lx_kit/work.h @@ -0,0 +1,67 @@ +/* + * \brief Work queue implementation + * \author Josef Soentgen + * \author Stefan Kalkowski + * \date 2015-10-26 + */ + +/* + * Copyright (C) 2015-2106 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _LX_KIT__WORK_H_ +#define _LX_KIT__WORK_H_ + +#include + +namespace Lx { + class Work; +} + + +class Lx::Work +{ + public: + + + virtual ~Work() { } + + /** + * Unblock corresponding task + */ + virtual void unblock() = 0; + + /** + * Schedule work + */ + virtual void schedule(struct ::work_struct *) = 0; + + /** + * Schedule delayed work + */ + virtual void schedule_delayed(struct ::delayed_work *, unsigned long delay) = 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; + + /** + * 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_ */ diff --git a/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h b/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h new file mode 100644 index 0000000000..e93ba77f55 --- /dev/null +++ b/repos/dde_linux/src/include/spec/arm/lx_kit/internal/arch_execute.h @@ -0,0 +1,44 @@ +/** + * \brief Platform specific code + * \author Sebastian Sumpf + * \date 2012-06-10 + */ + +/* + * Copyright (C) 2012-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _ARCH_EXECUTE_H_ +#define _ARCH_EXECUTE_H_ + +#if defined(USE_INTERNAL_SETJMP) +#ifdef __cplusplus +extern "C" { +#endif + +#define _JBLEN 64 +typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1]; + +void _longjmp(jmp_buf, int); +int _setjmp(jmp_buf); + +#ifdef __cplusplus +} +#endif +#endif /* USE_INTERNAL_SETJMP */ + + +static inline +void arch_execute(void *sp, void *func, void *arg) +{ + asm volatile ("mov r0, %2;" /* set arg */ + "mov sp, %0;" /* set stack */ + "mov pc, %1;" /* call func */ + "" + : : "r"(sp), "r"(func), "r"(arg) : "r0"); +} + +#endif /* _ARCH_EXECUTE_H_ */ diff --git a/repos/dde_linux/src/include/spec/arm_v6/lx_emul/barrier.h b/repos/dde_linux/src/include/spec/arm_v6/lx_emul/barrier.h new file mode 100644 index 0000000000..239275b80c --- /dev/null +++ b/repos/dde_linux/src/include/spec/arm_v6/lx_emul/barrier.h @@ -0,0 +1,31 @@ +/* + * \brief ARMv6-specific part of the Linux API emulation + * \author Christian Prochaska + * \date 2014-05-28 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/******************* + ** asm/barrier.h ** + *******************/ + +#define mb() asm volatile ("": : :"memory") +#define rmb() mb() +#define wmb() asm volatile ("": : :"memory") + +/* + * This is the "safe" implementation as needed for a configuration + * with SMP enabled. + */ + +#define smp_mb() asm volatile ("": : :"memory") +#define smp_rmb() smp_mb() +#define smp_wmb() asm volatile ("": : :"memory") + +static inline void barrier() { asm volatile ("": : :"memory"); } diff --git a/repos/dde_linux/src/include/spec/arm_v7/lx_emul/barrier.h b/repos/dde_linux/src/include/spec/arm_v7/lx_emul/barrier.h new file mode 100644 index 0000000000..7bb1d25e68 --- /dev/null +++ b/repos/dde_linux/src/include/spec/arm_v7/lx_emul/barrier.h @@ -0,0 +1,31 @@ +/* + * \brief ARMv7-specific part of the Linux API emulation + * \author Christian Prochaska + * \date 2014-05-28 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which 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") + +/* + * 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"); } diff --git a/repos/dde_linux/src/include/x86/lx_emul/barrier.h b/repos/dde_linux/src/include/spec/x86/lx_emul/barrier.h similarity index 100% rename from repos/dde_linux/src/include/x86/lx_emul/barrier.h rename to repos/dde_linux/src/include/spec/x86/lx_emul/barrier.h diff --git a/repos/dde_linux/src/include/spec/x86_32/lx_emul/impl/internal/arch_execute.h b/repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h similarity index 69% rename from repos/dde_linux/src/include/spec/x86_32/lx_emul/impl/internal/arch_execute.h rename to repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h index 134c9f484b..541742842f 100644 --- a/repos/dde_linux/src/include/spec/x86_32/lx_emul/impl/internal/arch_execute.h +++ b/repos/dde_linux/src/include/spec/x86_32/lx_kit/internal/arch_execute.h @@ -14,6 +14,23 @@ #ifndef _ARCH_EXECUTE_H_ #define _ARCH_EXECUTE_H_ +#if defined(USE_INTERNAL_SETJMP) +#ifdef __cplusplus +extern "C" { +#endif + +#define _JBLEN 11 +typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1]; + +void _longjmp(jmp_buf, int); +int _setjmp(jmp_buf); + +#ifdef __cplusplus +} +#endif +#endif /* USE_INTERNAL_SETJMP */ + + static inline void arch_execute(void *sp, void *func, void *arg) { diff --git a/repos/dde_linux/src/include/spec/x86_64/lx_emul/impl/internal/arch_execute.h b/repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h similarity index 70% rename from repos/dde_linux/src/include/spec/x86_64/lx_emul/impl/internal/arch_execute.h rename to repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h index eb96ce8f6c..ea4a6a6879 100644 --- a/repos/dde_linux/src/include/spec/x86_64/lx_emul/impl/internal/arch_execute.h +++ b/repos/dde_linux/src/include/spec/x86_64/lx_kit/internal/arch_execute.h @@ -15,6 +15,23 @@ #ifndef _ARCH_EXECUTE_H_ #define _ARCH_EXECUTE_H_ +#if defined(USE_INTERNAL_SETJMP) +#ifdef __cplusplus +extern "C" { +#endif + +#define _JBLEN 12 + typedef struct _jmp_buf { long _jb[_JBLEN]; } jmp_buf[1]; + + void _longjmp(jmp_buf, int); + int _setjmp(jmp_buf); + +#ifdef __cplusplus +} +#endif +#endif /* USE_INTERNAL_SETJMP */ + + static inline void arch_execute(void *sp, void *func, void *arg) { diff --git a/repos/dde_linux/src/lib/lx/lx.cc b/repos/dde_linux/src/lib/lx/lx.cc deleted file mode 100644 index da661e80e2..0000000000 --- a/repos/dde_linux/src/lib/lx/lx.cc +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include - -#include - -void lx_printf(char const *fmt, ...) -{ - va_list va; - va_start(va, fmt); - Genode::vprintf(fmt, va); - va_end(va); -} - - -void lx_vprintf(char const *fmt, va_list va) { - Genode::vprintf(fmt, va); } diff --git a/repos/dde_linux/src/lib/lxip/lxcc_emul.cc b/repos/dde_linux/src/lib/lxip/lxcc_emul.cc index 31d29843f9..f2d2952ea4 100644 --- a/repos/dde_linux/src/lib/lxip/lxcc_emul.cc +++ b/repos/dde_linux/src/lib/lxip/lxcc_emul.cc @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/repos/dde_linux/src/lib/usb/lx_emul.cc b/repos/dde_linux/src/lib/usb/lx_emul.cc index 5d5490d7ef..a761ac11fc 100644 --- a/repos/dde_linux/src/lib/usb/lx_emul.cc +++ b/repos/dde_linux/src/lib/usb/lx_emul.cc @@ -15,7 +15,6 @@ /* Genode includes */ #include #include -#include #include #include #include diff --git a/repos/dde_linux/src/lib/wifi/lxcc_emul.cc b/repos/dde_linux/src/lib/wifi/lxcc_emul.cc index 2b5506bd33..6a2c11dec9 100644 --- a/repos/dde_linux/src/lib/wifi/lxcc_emul.cc +++ b/repos/dde_linux/src/lib/wifi/lxcc_emul.cc @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/irq.h b/repos/dde_linux/src/lx_kit/irq.cc similarity index 71% rename from repos/dde_linux/src/include/lx_emul/impl/internal/irq.h rename to repos/dde_linux/src/lx_kit/irq.cc index 2075e2530a..0f3bcff14b 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/irq.h +++ b/repos/dde_linux/src/lx_kit/irq.cc @@ -7,27 +7,29 @@ */ /* - * Copyright (C) 2014-2015 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__IRQ_H_ -#define _LX_EMUL__IMPL__INTERNAL__IRQ_H_ - /* Genode includes */ +#include #include #include -#include -/* Linux emulation environment includes */ -#include +/* Linux emulation environment */ +#include -namespace Lx { class Irq; } +/* Linux kit includes */ +#include +#include -class Lx::Irq +namespace Lx_kit { class Irq; } + + +class Lx_kit::Irq : public Lx::Irq { private: @@ -50,7 +52,7 @@ class Lx::Irq /** * This contains the Linux-driver handlers */ - class Handler : public Lx::List::Element + class Handler : public Lx_kit::List::Element { private: @@ -83,15 +85,15 @@ class Lx::Irq /** * Context encapsulates the handling of an IRQ */ - class Context : public Lx::List::Element + class Context : public Lx_kit::List::Element { private: - Name_composer _name; - Platform::Device &_dev; - Genode::Irq_session_client _irq_sess; - Lx::List _handler; /* List of registered handlers */ - Lx::Task _task; + Name_composer _name; + Platform::Device &_dev; + Genode::Irq_session_client _irq_sess; + Lx_kit::List _handler; + Lx::Task _task; Genode::Signal_rpc_member _dispatcher; @@ -141,11 +143,9 @@ class Lx::Irq */ void handle_irq() { - bool handled = false; - /* report IRQ to all clients */ for (Handler *h = _handler.first(); h; h = h->next()) { - if ((handled = h->handle())) break; + h->handle(); } _irq_sess.ack_irq(); @@ -165,10 +165,10 @@ class Lx::Irq using Context_slab = Genode::Tslab; using Handler_slab = Genode::Tslab; - Server::Entrypoint &_ep; - Lx::List _list; - Context_slab _context_alloc; - Handler_slab _handler_alloc; + Server::Entrypoint &_ep; + Lx_kit::List _list; + Context_slab _context_alloc; + Handler_slab _handler_alloc; /** * Find context for given device @@ -180,20 +180,25 @@ class Lx::Irq return nullptr; } - Irq(Server::Entrypoint &ep) + Irq(Server::Entrypoint &ep, Genode::Allocator &alloc) : _ep(ep), - _context_alloc(Genode::env()->heap()), - _handler_alloc(Genode::env()->heap()) { } + _context_alloc(&alloc), + _handler_alloc(&alloc) { } public: - static Irq &irq(Server::Entrypoint *ep = nullptr); + static Irq &irq(Server::Entrypoint &ep, Genode::Allocator &alloc) + { + static Irq inst(ep, alloc); + return inst; + } + + /*********************** + ** Lx::Irq interface ** + ***********************/ - /** - * Request an IRQ - */ void request_irq(Platform::Device &dev, irq_handler_t handler, - void *dev_id, irq_handler_t thread_fn = 0) + void *dev_id, irq_handler_t thread_fn = 0) override { Context *ctx = _find_context(dev); @@ -210,4 +215,10 @@ class Lx::Irq } }; -#endif /* _LX_EMUL__IMPL__INTERNAL__IRQ_H_ */ + +/**************************** + ** Lx::Irq implementation ** + ****************************/ + +Lx::Irq &Lx::Irq::irq(Server::Entrypoint *ep, Genode::Allocator *alloc) { + return Lx_kit::Irq::irq(*ep, *alloc); } diff --git a/repos/dde_linux/src/lx_kit/malloc.cc b/repos/dde_linux/src/lx_kit/malloc.cc new file mode 100644 index 0000000000..a4aeefd665 --- /dev/null +++ b/repos/dde_linux/src/lx_kit/malloc.cc @@ -0,0 +1,383 @@ +/* + * \brief Linux kit memory allocator + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include + +/* Linux kit includes */ +#include +#include +#include + + +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_attribute _cached; /* 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) { + PERR("Slab-backend exhausted!"); + return false; + } + + try { + _ds_cap[_index] = Lx::backend_alloc(P_BLOCK_SIZE, _cached); + /* 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] = Genode::Dataspace_client(_ds_cap[_index]).phys_addr(); + } 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::Cache_attribute cached) + : + Region_map_client(Rm_connection::create(VM_SIZE)), + _cached(cached), _index(0), _range(Genode::env()->heap()) + { + /* reserver attach us, anywere */ + _base = Genode::env()->rm_session()->attach(dataspace()); + } + + static Slab_backend_alloc &mem() + { + static Lx_kit::Slab_backend_alloc inst(Genode::CACHED); + return inst; + } + + static Slab_backend_alloc &dma() + { + static Lx_kit::Slab_backend_alloc inst(Genode::UNCACHED); + return inst; + } + + /************************************** + ** Lx::Slab_backend_alloc interface ** + **************************************/ + + bool alloc(size_t size, void **out_addr) override + { + bool done = _range.alloc(size, out_addr); + + if (done) + return done; + + done = _alloc_block(); + if (!done) { + PERR("Backend allocator exhausted\n"); + return false; + } + + return _range.alloc(size, out_addr); + } + + 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]; + } + + PWRN("virt_addr(0x%lx) - no translation", phys); + 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; + Slab_alloc *_allocator[NUM_SLABS]; + Genode::Cache_attribute _cached; /* 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_attribute cached) + : + _back_allocator(alloc), _cached(cached), _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] = new (Genode::env()->heap()) + Slab_alloc(1U << i, alloc); + } + + static Malloc & mem() + { + static Malloc inst(Slab_backend_alloc::mem(), Genode::CACHED); + return inst; + } + + static Malloc & dma() + { + static Malloc inst(Slab_backend_alloc::dma(), Genode::UNCACHED); + return inst; + } + + /************************** + ** Lx::Malloc interface ** + **************************/ + + void *alloc(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) { + PERR("Slab too large %u reqested %zu cached %d", 1U << msb, size, _cached); + return 0; + } + + addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc(); + if (!addr) { + PERR("Failed to get slab for %u", 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) + { + void *addr; + if (!_back_allocator.alloc(size, &addr)) { + PERR("Large back end allocation failed (%zu bytes)", size); + return nullptr; + } + + return addr; + } + + 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 ** + *******************************/ + +/** + * Cached memory backend allocator + */ +Lx::Slab_backend_alloc &Lx::Slab_backend_alloc::mem() { + return Lx_kit::Slab_backend_alloc::mem(); } + + +/** + * DMA memory backend allocator + */ +Lx::Slab_backend_alloc &Lx::Slab_backend_alloc::dma() { + return Lx_kit::Slab_backend_alloc::dma(); } + + +/** + * Cached memory allocator + */ +Lx::Malloc &Lx::Malloc::mem() { + return Lx_kit::Malloc::mem(); } + +/** + * DMA memory allocator + */ +Lx::Malloc &Lx::Malloc::dma() { + return Lx_kit::Malloc::dma(); } diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/mapped_io_mem_range.h b/repos/dde_linux/src/lx_kit/mapped_io_mem_range.cc similarity index 71% rename from repos/dde_linux/src/include/lx_emul/impl/internal/mapped_io_mem_range.h rename to repos/dde_linux/src/lx_kit/mapped_io_mem_range.cc index 0b2dcbd330..4800832195 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/mapped_io_mem_range.h +++ b/repos/dde_linux/src/lx_kit/mapped_io_mem_range.cc @@ -5,44 +5,42 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__MAPPED_IO_MEM_RANGE_H_ -#define _LX_EMUL__IMPL__INTERNAL__MAPPED_IO_MEM_RANGE_H_ - /* Genode includes */ #include #include +#include #include +/* Linux emulation environment */ +#include + /* Linux emulation environment includes */ -#include +#include +#include +#include +#include -namespace Lx { +namespace Lx_kit { class Mapped_io_mem_range; } - class Mapped_io_mem_range; - - void *ioremap(resource_size_t, unsigned long, Genode::Cache_attribute); - void iounmap(volatile void*); - Genode::Dataspace_capability ioremap_lookup(Genode::addr_t, Genode::size_t); -} /** * Representation of a locally-mapped MMIO range * * This class is supposed to be a private utility to support 'ioremap'. */ -class Lx::Mapped_io_mem_range : public Lx::List::Element +class Lx_kit::Mapped_io_mem_range : public Lx_kit::List::Element, + public Genode::Rm_connection { private: Genode::size_t const _size; Genode::addr_t const _phys; - Genode::Rm_connection _rm; Genode::Region_map_client _region_map; Genode::Attached_dataspace _ds; Genode::addr_t const _virt; @@ -54,7 +52,7 @@ class Lx::Mapped_io_mem_range : public Lx::List::Element Genode::addr_t offset) : _size(size), _phys(phys), - _region_map(_rm.create(size)), + _region_map(Rm_connection::create(size)), _ds(_region_map.dataspace()), _virt((Genode::addr_t)_ds.local_addr() | (phys &0xfffUL)) { _region_map.attach_at(ds_cap, 0, size, offset); } @@ -81,16 +79,20 @@ class Lx::Mapped_io_mem_range : public Lx::List::Element }; -static Lx::List ranges; +static Lx_kit::List ranges; -void *Lx::ioremap(resource_size_t phys_addr, unsigned long size, +/******************************************** + ** Lx_kit::Mapped_io_mem_range implementation ** + ********************************************/ + +void *Lx::ioremap(addr_t phys_addr, unsigned long size, Genode::Cache_attribute cache_attribute) { using namespace Genode; /* search for the requested region within the already mapped ranges */ - for (Lx::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) { + for (Lx_kit::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) { if (r->phys_range(phys_addr, size)) { void * const virt = (void *)(r->virt() + phys_addr - r->phys()); @@ -100,19 +102,19 @@ void *Lx::ioremap(resource_size_t phys_addr, unsigned long size, } } - addr_t offset; + addr_t offset = 0; Io_mem_dataspace_capability ds_cap = Lx::pci_dev_registry()->io_mem(phys_addr, cache_attribute, size, offset); if (!ds_cap.valid()) { - PERR("Failed to request I/O memory: [%zx,%lx)", phys_addr, + PERR("Failed to request I/O memory: [%lx,%lx)", phys_addr, phys_addr + size); return nullptr; } - Lx::Mapped_io_mem_range *io_mem = - new (env()->heap()) Lx::Mapped_io_mem_range(phys_addr, size, + Lx_kit::Mapped_io_mem_range *io_mem = + new (env()->heap()) Lx_kit::Mapped_io_mem_range(phys_addr, size, ds_cap, offset); ranges.insert(io_mem); @@ -120,8 +122,7 @@ void *Lx::ioremap(resource_size_t phys_addr, unsigned long size, PLOG("ioremap: mapped phys 0x%lx (size %lx) to virt 0x%lx", (long)phys_addr, (long)size, (long)io_mem->virt()); - addr_t const sub_page_offset = phys_addr & 0xfff; - return (void *)(io_mem->virt() + sub_page_offset); + return (void *)io_mem->virt(); } void Lx::iounmap(volatile void * virt) @@ -129,7 +130,7 @@ void Lx::iounmap(volatile void * virt) using namespace Genode; /* search for the requested region within the already mapped ranges */ - for (Lx::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) { + for (Lx_kit::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) { if (r->virt() == (addr_t)virt) { ranges.remove(r); @@ -143,11 +144,9 @@ Genode::Dataspace_capability Lx::ioremap_lookup(Genode::addr_t virt_addr, Genode::size_t size) { /* search for the requested region within the already mapped ranges */ - for (Lx::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) + for (Lx_kit::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) if (r->virt_range(virt_addr, size)) return r->cap(); return Genode::Dataspace_capability(); } - -#endif /* _LX_EMUL__IMPL__INTERNAL__MAPPED_IO_MEM_RANGE_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_backend_alloc.h b/repos/dde_linux/src/lx_kit/pci.cc similarity index 71% rename from repos/dde_linux/src/include/lx_emul/impl/internal/pci_backend_alloc.h rename to repos/dde_linux/src/lx_kit/pci.cc index 1a3c27737b..35eff74ebc 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_backend_alloc.h +++ b/repos/dde_linux/src/lx_kit/pci.cc @@ -7,33 +7,35 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__PCI_BACKEND_ALLOC_H_ -#define _LX_EMUL__IMPL__INTERNAL__PCI_BACKEND_ALLOC_H_ - /* Genode includes */ #include #include -/* Linux emulation environment includes */ -#include +/* XXX only because of struct pci_dev */ +#include -namespace Lx { +/* Linux emulation environment includes */ +#include +#include + + +namespace Lx_kit { struct Memory_object_base; struct Ram_object; struct Dma_object; - extern Genode::Object_pool memory_pool; + Genode::Object_pool memory_pool; }; -struct Lx::Memory_object_base : Genode::Object_pool::Entry +struct Lx_kit::Memory_object_base : Genode::Object_pool::Entry { Memory_object_base(Genode::Ram_dataspace_capability cap) : Genode::Object_pool::Entry(cap) {} @@ -49,7 +51,7 @@ struct Lx::Memory_object_base : Genode::Object_pool::Entry }; -struct Lx::Ram_object : Memory_object_base +struct Lx_kit::Ram_object : Memory_object_base { Ram_object(Genode::Ram_dataspace_capability cap) : Memory_object_base(cap) {} @@ -58,7 +60,7 @@ struct Lx::Ram_object : Memory_object_base }; -struct Lx::Dma_object : Memory_object_base +struct Lx_kit::Dma_object : Memory_object_base { Dma_object(Genode::Ram_dataspace_capability cap) : Memory_object_base(cap) {} @@ -67,10 +69,15 @@ struct Lx::Dma_object : Memory_object_base }; +/********************************* + ** Lx::Backend_alloc interface ** + *********************************/ + Genode::Ram_dataspace_capability Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) { using namespace Genode; + using namespace Lx_kit; Memory_object_base *o; Genode::Ram_dataspace_capability cap; @@ -100,6 +107,7 @@ Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) void Lx::backend_free(Genode::Ram_dataspace_capability cap) { using namespace Genode; + using namespace Lx_kit; Memory_object_base *object; memory_pool.apply(cap, [&] (Memory_object_base *o) { @@ -114,5 +122,19 @@ void Lx::backend_free(Genode::Ram_dataspace_capability cap) } -#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_BACKEND_ALLOC_H_ */ +/******************** + ** Pci singletons ** + ********************/ +Platform::Connection *Lx::pci() +{ + static Platform::Connection _pci; + return &_pci; +} + + +Lx::Pci_dev_registry *Lx::pci_dev_registry() +{ + static Lx::Pci_dev_registry _pci_dev_registry; + return &_pci_dev_registry; +} diff --git a/repos/dde_linux/src/lx_kit/printf.cc b/repos/dde_linux/src/lx_kit/printf.cc new file mode 100644 index 0000000000..ac63651bf4 --- /dev/null +++ b/repos/dde_linux/src/lx_kit/printf.cc @@ -0,0 +1,445 @@ +/* + * \brief Linux kit memory allocator + * \author Sebastian Sumpf + * \date 2016-04-20 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include + + +namespace Lx { class Console; } + +extern "C" int stdout_write(const char *s); + +static const bool verbose_console = false; + +/** + * Format string command representation + */ +class 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] == '#'); + 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; + stdout_write(_buf); + _idx = 0; + } + + /** + * Output signed value with the specified base + */ + template + 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 + 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(numeric_arg, cmd.base); + else + _out_signed(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(numeric_arg, cmd.base, cmd.padding); + break; + } + + /* fall through */ + + case Format_command::PTR: + + _out_unsigned(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(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(ip[i], cmd.base, cmd.padding); + } + } + break; + + case Format_command::INVALID: + + _out_string(""); + /* 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, ...) +{ + if (verbose_console) + PDBG("[%p] %s", __builtin_return_address(0), 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); } diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/scheduler.h b/repos/dde_linux/src/lx_kit/scheduler.cc similarity index 73% rename from repos/dde_linux/src/include/lx_emul/impl/internal/scheduler.h rename to repos/dde_linux/src/lx_kit/scheduler.cc index 6f2a9c4fc8..155d29b9f0 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/scheduler.h +++ b/repos/dde_linux/src/lx_kit/scheduler.cc @@ -7,59 +7,44 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__SCHEDULER_H_ -#define _LX_EMUL__IMPL__INTERNAL__SCHEDULER_H_ - /* Genode includes */ #include #include #include +#include #include #include /* Linux emulation environment includes */ -#include -#include +#include +#include -namespace Lx { +#include + +namespace Lx_kit { class Scheduler; - - /** - * Return singleton instance of the scheduler - * - * Implementation must be provided by the driver. - */ - Scheduler &scheduler(); - - /** - * Called each time when a scheduling decision is taken - * - * Must be provided by the compilation unit that includes 'scheduler.h', - * e.g., by also including 'timer.h'. - */ - static inline void timer_update_jiffies(); } -class Lx::Scheduler +class Lx_kit::Scheduler : public Lx::Scheduler { private: bool verbose = false; - Lx::List _present_list; - Genode::Lock _present_list_mutex; + Lx_kit::List _present_list; + Genode::Lock _present_list_mutex; - Task *_current = nullptr; /* currently scheduled task */ + Lx::Task *_current = nullptr; /* currently scheduled task */ - bool _run_task(Task *); + bool _run_task(Lx::Task *); /* * Support for logging @@ -116,10 +101,11 @@ class Lx::Scheduler new (Genode::env()->heap()) Logger(*this, 10); } - /** - * Return currently scheduled task - */ - Task *current() + /***************************** + ** Lx::Scheduler interface ** + *****************************/ + + Lx::Task *current() override { if (!_current) { PERR("BUG: _current is zero!"); @@ -129,10 +115,10 @@ class Lx::Scheduler return _current; } - /** - * Add new task to the present list - */ - void add(Task *task) + bool active() const override { + return _current != nullptr; } + + void add(Lx::Task *task) override { Lx::Task *p = _present_list.first(); for ( ; p; p = p->next()) { @@ -145,12 +131,12 @@ class Lx::Scheduler _present_list.append(task); } - /** - * Schedule all present tasks - * - * Returns if no task is runnable. - */ - void schedule() + void remove(Lx::Task *task) override + { + _present_list.remove(task); + } + + void schedule() override { bool at_least_one = false; @@ -168,7 +154,7 @@ class Lx::Scheduler Lx::timer_update_jiffies(); bool was_run = false; - for (Task *t = _present_list.first(); t; t = t->next()) { + for (Lx::Task *t = _present_list.first(); t; t = t->next()) { /* update current before running task */ _current = t; @@ -190,12 +176,7 @@ class Lx::Scheduler _current = nullptr; } - /** - * Log current state of tasks in present list (debug) - * - * Log lines are prefixed with 'prefix'. - */ - void log_state(char const *prefix) + void log_state(char const *prefix) override { unsigned i; Lx::Task *t; @@ -208,6 +189,10 @@ class Lx::Scheduler }; +/***************************** + ** Lx::Task implementation ** + *****************************/ + Lx::Task::Task(void (*func)(void*), void *arg, char const *name, Priority priority, Scheduler &scheduler) : @@ -216,15 +201,26 @@ Lx::Task::Task(void (*func)(void*), void *arg, char const *name, { scheduler.add(this); - PDBGV("name: '%s' func: %p arg: %p prio: %u t: %p", name, func, arg, priority, this); + if (verbose) + PDBG("name: '%s' func: %p arg: %p prio: %u t: %p", name, func, arg, priority, this); } -void Lx::Task::_deinit() +Lx::Task::~Task() { + _scheduler.remove(this); + if (_stack) Genode::Thread::myself()->free_secondary_stack(_stack); } -#endif /* _LX_EMUL__IMPL__INTERNAL__SCHEDULER_H_ */ +/********************************** + ** Lx::Scheduler implementation ** + **********************************/ + +Lx::Scheduler &Lx::scheduler() +{ + static Lx_kit::Scheduler inst; + return inst; +} diff --git a/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S b/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S new file mode 100644 index 0000000000..4e84fb23f3 --- /dev/null +++ b/repos/dde_linux/src/lx_kit/spec/arm/setjmp.S @@ -0,0 +1,91 @@ +/* $NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */ + +/* + * Copyright (c) 1997 Mark Brinicombe + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#include +__FBSDID("$FreeBSD$"); + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the stack. + * The previous signal state is NOT restored. + * + * Note: r0 is the return value + * r1-r3 are scratch registers in functions + */ + +ENTRY(_setjmp) + ldr r1, .L_setjmp_magic + str r1, [r0], #4 + + /* SOFTFP */ + add r0, r0, #52 + /* Store integer registers */ + stmia r0, {r4-r14} + + mov r0, #0x00000000 + RET + +.L_setjmp_magic: + .word _JB_MAGIC__SETJMP + +WEAK_ALIAS(___longjmp, _longjmp) +ENTRY(_longjmp) + ldr r2, .L_setjmp_magic + ldr r3, [r0], #4 + teq r2, r3 + bne botch + + /* SOFTFP */ + add r0, r0, #52 + /* Restore integer registers */ + ldmia r0, {r4-r14} + + /* Validate sp and r14 */ + teq sp, #0 + teqne r14, #0 + beq botch + + /* Set return value */ + mov r0, r1 + teq r0, #0x00000000 + moveq r0, #0x00000001 + RET + + /* validation failed, die die die. */ +botch: + b . diff --git a/repos/dde_linux/src/lx_kit/spec/x86_32/setjmp.S b/repos/dde_linux/src/lx_kit/spec/x86_32/setjmp.S new file mode 100644 index 0000000000..7aefb8a3ca --- /dev/null +++ b/repos/dde_linux/src/lx_kit/spec/x86_32/setjmp.S @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) + .asciz "@(#)_setjmp.s 5.1 (Berkeley) 4/23/90" +#endif /* LIBC_SCCS and not lint */ +//#include + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the environment 'a'. + * The previous signal state is NOT restored. + */ + +.text; .p2align 2,0x90 +.globl _setjmp; .type _setjmp,@function; _setjmp: + movl 4(%esp),%eax + movl 0(%esp),%edx + movl %edx, 0(%eax) /* rta */ + movl %ebx, 4(%eax) + movl %esp, 8(%eax) + movl %ebp,12(%eax) + movl %esi,16(%eax) + movl %edi,20(%eax) + fnstcw 24(%eax) + xorl %eax,%eax + ret +.size _setjmp, . - _setjmp + +.text; .p2align 2,0x90 +.globl _longjmp; .type _longjmp,@function; _longjmp: + movl 4(%esp),%edx + movl 8(%esp),%eax + movl 0(%edx),%ecx + movl 4(%edx),%ebx + movl 8(%edx),%esp + movl 12(%edx),%ebp + movl 16(%edx),%esi + movl 20(%edx),%edi + fldcw 24(%edx) + testl %eax,%eax + jnz 1f + incl %eax +1: movl %ecx,0(%esp) + ret +.size _longjmp, . - _longjmp diff --git a/repos/dde_linux/src/lx_kit/spec/x86_64/setjmp.S b/repos/dde_linux/src/lx_kit/spec/x86_64/setjmp.S new file mode 100644 index 0000000000..69ef6cf7e2 --- /dev/null +++ b/repos/dde_linux/src/lx_kit/spec/x86_64/setjmp.S @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) + .asciz "@(#)_setjmp.s 5.1 (Berkeley) 4/23/90" +#endif /* LIBC_SCCS and not lint */ +//#include + +/* + * C library -- _setjmp, _longjmp + * + * _longjmp(a,v) + * will generate a "return(v)" from the last call to + * _setjmp(a) + * by restoring registers from the environment 'a'. + * The previous signal state is NOT restored. + */ + +.text; .p2align 4,0x90 +.globl _setjmp; .type _setjmp,@function; _setjmp: + movq %rdi,%rax + movq 0(%rsp),%rdx /* retval */ + movq %rdx, 0(%rax) /* 0; retval */ + movq %rbx, 8(%rax) /* 1; rbx */ + movq %rsp,16(%rax) /* 2; rsp */ + movq %rbp,24(%rax) /* 3; rbp */ + movq %r12,32(%rax) /* 4; r12 */ + movq %r13,40(%rax) /* 5; r13 */ + movq %r14,48(%rax) /* 6; r14 */ + movq %r15,56(%rax) /* 7; r15 */ + fnstcw 64(%rax) /* 8; fpu cw */ + stmxcsr 68(%rax) /* and mxcsr */ + xorq %rax,%rax + ret +.size _setjmp, . - _setjmp + +.text; .p2align 4,0x90 +.globl _longjmp; .type _longjmp,@function; _longjmp: + movq %rdi,%rdx + /* Restore the mxcsr, but leave exception flags intact. */ + stmxcsr -4(%rsp) + movl 68(%rdx),%eax + andl $0xffffffc0,%eax + movl -4(%rsp),%edi + andl $0x3f,%edi + xorl %eax,%edi + movl %edi,-4(%rsp) + ldmxcsr -4(%rsp) + movq %rsi,%rax /* retval */ + movq 0(%rdx),%rcx + movq 8(%rdx),%rbx + movq 16(%rdx),%rsp + movq 24(%rdx),%rbp + movq 32(%rdx),%r12 + movq 40(%rdx),%r13 + movq 48(%rdx),%r14 + movq 56(%rdx),%r15 + fldcw 64(%rdx) + testq %rax,%rax + jnz 1f + incq %rax +1: movq %rcx,0(%rsp) + ret +.size _longjmp, . - _longjmp diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/timer.h b/repos/dde_linux/src/lx_kit/timer.cc similarity index 58% rename from repos/dde_linux/src/include/lx_emul/impl/internal/timer.h rename to repos/dde_linux/src/lx_kit/timer.cc index 41f8228236..24acede156 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/timer.h +++ b/repos/dde_linux/src/lx_kit/timer.cc @@ -7,85 +7,90 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__TIMER_H_ -#define _LX_EMUL__IMPL__INTERNAL__TIMER_H_ - /* Genode includes */ #include #include #include +/* Linux kit includes */ +#include +#include + /* Linux emulation environment includes */ -#include -#include +#include -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(Server::Entrypoint *ep = nullptr, - unsigned long *jiffies_ptr = nullptr); - - /** - * Blue-print implementation of 'timer' function - */ - static inline Timer &_timer_impl(Server::Entrypoint *ep, - unsigned long *jiffies_ptr); - - static inline void timer_update_jiffies(); - - static inline void run_timer(void *); -} +#include -class Lx::Timer +namespace Lx_kit { class Timer; } + +class Lx_kit::Timer : public Lx::Timer { public: /** * Context encapsulates a regular linux timer_list */ - struct Context : public Lx::List::Element + struct Context : public Lx_kit::List::Element { enum { INVALID_TIMEOUT = ~0UL }; - struct timer_list *timer; + Type type; + void *timer; bool pending { false }; unsigned long timeout { INVALID_TIMEOUT }; /* absolute in jiffies */ bool programmed { false }; - Context(struct timer_list *timer) : timer(timer) { } + 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)->expires = e; + } + + void function() + { + switch (type) { + case LIST: + { + timer_list *t = static_cast(timer); + if (t->function) + t->function(t->data); + } + break; + + case HR: + { + hrtimer *t = static_cast(timer); + if (t->function) + t->function(t); + } + break; + } + } }; private: - unsigned long &_jiffies; ::Timer::Connection _timer_conn; - Lx::List _list; + Lx_kit::List _list; Lx::Task _timer_task; - Genode::Signal_rpc_member _dispatcher; + Genode::Signal_rpc_member _dispatcher; Genode::Tslab _timer_alloc; /** * Lookup local timer */ - Context *_find_context(struct timer_list const *timer) + Context *_find_context(void const *timer) { for (Context *c = _list.first(); c; c = c->next()) if (c->timer == timer) @@ -141,7 +146,7 @@ class Lx::Timer * struct timer_list because the wireless stack checks * it directly. */ - ctx->timer->expires = expires; + ctx->expires(expires); Context *c; for (c = _list.first(); c; c = c->next()) @@ -170,27 +175,55 @@ class Lx::Timer Timer(Server::Entrypoint &ep, unsigned long &jiffies) : _jiffies(jiffies), - _timer_task(run_timer, nullptr, "timer", Lx::Task::PRIORITY_2, - Lx::scheduler()), - _dispatcher(ep, *this, &Lx::Timer::_handle), + _timer_task(Timer::run_timer, reinterpret_cast(this), + "timer", Lx::Task::PRIORITY_2, Lx::scheduler()), + _dispatcher(ep, *this, &Lx_kit::Timer::_handle), _timer_alloc(Genode::env()->heap()) { _timer_conn.sigh(_dispatcher); } - /** - * Add new linux timer - */ - void add(struct timer_list *timer) + Context* first() { return _list.first(); } + + unsigned long jiffies() const { return _jiffies; } + + static void run_timer(void *p) { - Context *t = new (&_timer_alloc) Context(timer); + Timer &t = *reinterpret_cast(p); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + + Lx_kit::Timer::Context *ctx = t.first(); + if (!ctx || ctx->timeout > t.jiffies()) + continue;; + + 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(timer)); + else + t = new (&_timer_alloc) Context(static_cast(timer)); + _list.append(t); } - /** - * Delete linux timer - */ - int del(struct timer_list *timer) + int del(void *timer) { Context *ctx = _find_context(timer); @@ -209,10 +242,7 @@ class Lx::Timer return rv; } - /** - * Initial scheduling of linux timer - */ - int schedule(struct timer_list *timer, unsigned long expires) + int schedule(void *timer, unsigned long expires) { Context *ctx = _find_context(timer); if (!ctx) { @@ -231,15 +261,12 @@ class Lx::Timer return rv; } - /** - * Schedule next linux timer - */ void schedule_next() { _program_first_timer(); } /** * Check if the timer is currently pending */ - bool pending(struct timer_list const *timer) + bool pending(void const *timer) { Context *ctx = _find_context(timer); if (!ctx) { @@ -249,66 +276,32 @@ class Lx::Timer return ctx->pending; } - Context *find(struct timer_list const *timer) { - return _find_context(timer); } - - /** - * Update jiffie counter - */ - void update_jiffies() + bool find(void const *timer) const { - _jiffies = msecs_to_jiffies(_timer_conn.elapsed_ms()); + for (Context const *c = _list.first(); c; c = c->next()) + if (c->timer == timer) + return true; + + return false; } - /** - * Get first timer context - */ - Context* first() { return _list.first(); } - - unsigned long jiffies() const { return _jiffies; } + void update_jiffies() { + _jiffies = msecs_to_jiffies(_timer_conn.elapsed_ms()); } }; +/****************************** + ** Lx::Timer implementation ** + ******************************/ + +Lx::Timer &Lx::timer(Server::Entrypoint *ep, unsigned long *jiffies) +{ + static Lx_kit::Timer inst(*ep, *jiffies); + return inst; +} + + void Lx::timer_update_jiffies() { timer().update_jiffies(); } - - -void Lx::run_timer(void *) -{ - Timer &t = timer(); - - while (1) { - Lx::scheduler().current()->block_and_schedule(); - - while (Lx::Timer::Context *ctx = t.first()) { - if (ctx->timeout > t.jiffies()) - break; - - ctx->timer->function(ctx->timer->data); - t.del(ctx->timer); - } - - t.schedule_next(); - } -} - - -Lx::Timer &Lx::_timer_impl(Server::Entrypoint *ep, unsigned long *jiffies_ptr) -{ - static bool initialized = false; - - if (!initialized && !ep) { - PERR("attempt to use Lx::Timer before its construction"); - class Lx_timer_not_constructed { }; - throw Lx_timer_not_constructed(); - } - - static Lx::Timer inst(*ep, *jiffies_ptr); - initialized = true; - return inst; -} - - -#endif /* _LX_EMUL__IMPL__INTERNAL__TIMER_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/work.h b/repos/dde_linux/src/lx_kit/work.cc similarity index 56% rename from repos/dde_linux/src/include/lx_emul/impl/internal/work.h rename to repos/dde_linux/src/lx_kit/work.cc index b6b2b429e6..e765fed8d4 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/internal/work.h +++ b/repos/dde_linux/src/lx_kit/work.cc @@ -6,32 +6,35 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _LX_EMUL__IMPL__INTERNAL__WORK_H_ -#define _LX_EMUL__IMPL__INTERNAL__WORK_H_ +/* Genode includes */ +#include + +#include +#include /* Linux emulation environment includes */ -#include -#include +#include -namespace Lx { - class Work; -} +#include -class Lx::Work +namespace Lx_kit { class Work; } + + +class Lx_kit::Work : public Lx::Work { public: /** * Context encapsulates a normal work item */ - struct Context : public Lx::List::Element + struct Context : public Lx_kit::List::Element { void *work; enum Type { NORMAL, DELAYED, TASKLET } type; @@ -66,50 +69,65 @@ class Lx::Work private: - Lx::Task _task; - Lx::List _list; + Lx::Task _task; + Lx_kit::List _list; Genode::Tslab _work_alloc; - Work() - : _task(Work::run_work, reinterpret_cast(this), "work_queue", - Lx::Task::PRIORITY_2, Lx::scheduler()), - _work_alloc(Genode::env()->heap()) { } - - public: - - static Work & work_queue(); - - /** - * Unblock corresponding task - */ - void unblock() { _task.unblock(); } - /** * Schedule work item */ template - void schedule(WORK *work) + void _schedule(WORK *work) { Context *c = new (&_work_alloc) Context(work); _list.append(c); } + public: + + Work(Genode::Allocator &alloc, char const *name = "work_queue") + : _task(Work::run_work, reinterpret_cast(this), name, + Lx::Task::PRIORITY_2, Lx::scheduler()), + _work_alloc(&alloc) { } + /** * Execute all available work items */ void exec() { while (Context *c = _list.first()) { - c->exec(); _list.remove(c); + c->exec(); destroy(&_work_alloc, c); } } - /** - * Cancel work item - */ + static void run_work(void *wq) + { + Work *work_queue = reinterpret_cast(wq); + while (1) { + work_queue->exec(); + Lx::scheduler().current()->block_and_schedule(); + } + } + + /************************ + ** Lx::Work interface ** + ************************/ + + void unblock() { _task.unblock(); } + + void schedule(struct work_struct *work) { + _schedule(work); } + + void schedule_delayed(struct delayed_work *work, + unsigned long /*delay*/) { + _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()) { @@ -126,21 +144,29 @@ class Lx::Work return false; } - static void run_work(void * wq) - { - Work * work_queue = reinterpret_cast(wq); - while (1) { - work_queue->exec(); - Lx::scheduler().current()->block_and_schedule(); - } - } + char const *task_name() override { return _task.name(); } }; -Lx::Work & Lx::Work::work_queue() +/***************************** + ** Lx::Work implementation ** + *****************************/ + +Lx::Work & Lx::Work::work_queue(Genode::Allocator *alloc) { - static Lx::Work work; + 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; } -#endif /* _LX_EMUL__IMPL__INTERNAL__WORK_H_ */ + +void Lx::Work::free_work_queue(Lx::Work *w) +{ + PERR("%s: IMPLEMENT ME", __func__); +}