diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000000..ef46a9e63a
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,78 @@
+{
+ "configurations": [
+ {
+ "name": "EalánOS",
+ "includePath": [
+ "${workspaceFolder}/depot/genodelabs/api/libc/**",
+ "${workspaceFolder}/depot/genodelabs/api/stdcxx/**",
+ "${workspaceFolder}/repos/**",
+ "${workspaceFolder}/repos/mml/**",
+ "${workspaceFolder}/repos/libports/include/**",
+ "${workspaceFolder}/contrib/mxtasking-07a3844690ae8eb15832d93e29567a5a8e6e45af/include/**",
+ "${workspaceFolder}/contrib/libpfm4-b0ec09148c2be9f4a96203a3d2de4ebed6ce2da0/include/**",
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/libc/**",
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/spec/x86_64/libc",
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/libc/sys/**",
+ "${workspaceFolder}/contrib/stdcxx-d2865c41fafbbf66051d38e7b742c4d5bc2f05a3/include/stdcxx/",
+ "${workspaceFolder}/contrib/stdcxx-d2865c41fafbbf66051d38e7b742c4d5bc2f05a3/include/stdcxx/std",
+ "${workspaceFolder}/contrib/stdcxx-d2865c41fafbbf66051d38e7b742c4d5bc2f05a3/include/stdcxx/c_std",
+ "${workspaceFolder}/repos/libports/include/spec/x86_64/stdcxx",
+ "${workspaceFolder}/repos/base-nova/src/core/include/**",
+ "${workspaceFolder}/repos/base-nova/src/include/**",
+ "${workspaceFolder}/repos/base-nova/include/**",
+ "${workspaceFolder}/repos/base/src/core/include/**",
+ "${workspaceFolder}/repos/base/src/include/**",
+ "${workspaceFolder}/repos/base/include/**",
+ "/usr/local/genode/tool/21.05/lib/gcc/x86_64-pc-elf/10.3.0/include",
+ "/home/mml/loopbench/**"
+ ],
+ "defines": [
+ "__GENODE__",
+ "__FreeBSD__=12",
+ "_GLIBCXX_HAVE_MBSTATE_T",
+ "_GLIBCXX_ATOMIC_BUILTINS_4",
+ "_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC"
+ ],
+ "compilerPath": "/usr/local/genode/tool/21.05/bin/genode-x86-gcc",
+ "cStandard": "gnu17",
+ "cppStandard": "gnu++17",
+ "intelliSenseMode": "linux-gcc-x64",
+ "compilerArgs": [
+ "-nostdinc",
+ "-m64"
+ ],
+ "configurationProvider": "ms-vscode.makefile-tools",
+ "forcedInclude": [
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/libc/stdint.h"
+ ],
+ "mergeConfigurations": true,
+ "browse": {
+ "limitSymbolsToIncludedHeaders": true,
+ "path": [
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/libc/**",
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/spec/x86_64/libc",
+ "${workspaceFolder}/contrib/libc-c7cd230b11ca71979f32950803bc78b45adfa0ce/include/libc/sys/**",
+ "${workspaceFolder}/contrib/stdcxx-d2865c41fafbbf66051d38e7b742c4d5bc2f05a3/include/stdcxx/",
+ "${workspaceFolder}/contrib/stdcxx-d2865c41fafbbf66051d38e7b742c4d5bc2f05a3/include/stdcxx/std",
+ "${workspaceFolder}/contrib/stdcxx-d2865c41fafbbf66051d38e7b742c4d5bc2f05a3/include/stdcxx/c_std",
+ "${workspaceFolder}/repos/libports/include/spec/x86_64/stdcxx"
+ ]
+ }
+ },
+ {
+ "name": "Genode",
+ "includePath": [
+ "${workspaceFolder}/**",
+ "${workspaceFolder}/repos/base/**"
+ ],
+ "defines": [],
+ "compilerPath": "/usr/local/genode/tool/21.05/bin/genode-x86-gcc",
+ "cStandard": "c17",
+ "cppStandard": "c++20",
+ "intelliSenseMode": "${default}",
+ "configurationProvider": "ms-vscode.makefile-tools",
+ "mergeConfigurations": true
+ }
+ ],
+ "version": 4
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..a4f0c0c941
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,167 @@
+{
+ "files.associations": {
+ "*.rasi": "css",
+ "*.bbmodel": "json",
+ "*.sublime-snippet": "xml",
+ "*.hbs": "html",
+ "*.ejs": "html",
+ "*.emu": "html",
+ "lesskey": "lesskey",
+ "*.Xresources": "xdefaults",
+ "i3/config": "i3",
+ "i3/*.conf": "i3",
+ "polybar/config": "ini",
+ "polybar/*.conf": "ini",
+ "*.S": "gas",
+ "*.html.en": "html",
+ "*.html.de": "html",
+ "stop_token": "cpp",
+ "*.tcc": "cpp",
+ "initializer_list": "cpp",
+ "streambuf": "cpp",
+ "tuple": "cpp",
+ "memory": "cpp",
+ "*.def": "cpp",
+ "array": "cpp",
+ "deque": "cpp",
+ "forward_list": "cpp",
+ "list": "cpp",
+ "string": "cpp",
+ "vector": "cpp",
+ "any": "cpp",
+ "executor": "cpp",
+ "internet": "cpp",
+ "io_context": "cpp",
+ "memory_resource": "cpp",
+ "socket": "cpp",
+ "string_view": "cpp",
+ "timer": "cpp",
+ "functional": "cpp",
+ "rope": "cpp",
+ "slist": "cpp",
+ "coroutine": "cpp",
+ "future": "cpp",
+ "scoped_allocator": "cpp",
+ "valarray": "cpp",
+ "regex": "cpp",
+ "cstdint": "cpp",
+ "bitset": "cpp",
+ "random": "cpp",
+ "optional": "cpp",
+ "dynamic_bitset": "cpp",
+ "mutex": "cpp",
+ "shared_mutex": "cpp",
+ "algorithm": "cpp",
+ "atomic": "cpp",
+ "bit": "cpp",
+ "cassert": "cpp",
+ "cctype": "cpp",
+ "cerrno": "cpp",
+ "chrono": "cpp",
+ "ciso646": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "compare": "cpp",
+ "concepts": "cpp",
+ "cstddef": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "ctime": "cpp",
+ "cwchar": "cpp",
+ "cwctype": "cpp",
+ "map": "cpp",
+ "unordered_map": "cpp",
+ "exception": "cpp",
+ "fstream": "cpp",
+ "ios": "cpp",
+ "iosfwd": "cpp",
+ "iostream": "cpp",
+ "istream": "cpp",
+ "iterator": "cpp",
+ "limits": "cpp",
+ "new": "cpp",
+ "numeric": "cpp",
+ "ostream": "cpp",
+ "queue": "cpp",
+ "ranges": "cpp",
+ "ratio": "cpp",
+ "sstream": "cpp",
+ "stdexcept": "cpp",
+ "system_error": "cpp",
+ "thread": "cpp",
+ "type_traits": "cpp",
+ "typeinfo": "cpp",
+ "utility": "cpp",
+ "variant": "cpp",
+ "charconv": "cpp",
+ "cfenv": "cpp",
+ "cinttypes": "cpp",
+ "csetjmp": "cpp",
+ "csignal": "cpp",
+ "cstdarg": "cpp",
+ "cuchar": "cpp",
+ "set": "cpp",
+ "unordered_set": "cpp",
+ "codecvt": "cpp",
+ "condition_variable": "cpp",
+ "iomanip": "cpp",
+ "*.run": "xml",
+ "span": "cpp",
+ "config.h": "c",
+ "bench.h": "c",
+ "hash_map": "cpp",
+ "hash_set": "cpp",
+ "strstream": "cpp",
+ "decimal": "cpp",
+ "buffer": "cpp",
+ "netfwd": "cpp",
+ "propagate_const": "cpp",
+ "source_location": "cpp",
+ "complex": "cpp",
+ "numbers": "cpp",
+ "typeindex": "cpp",
+ "bool_set": "cpp"
+ },
+ "vscode-as-git-mergetool.settingsAssistantOnStartup": false,
+ "makefile.makeDirectory": "build/x86_64",
+ "C_Cpp.errorSquiggles": "enabledIfIncludesResolve",
+ "C_Cpp.default.cppStandard": "gnu++17",
+ "C_Cpp.default.cStandard": "gnu17",
+ "C_Cpp.workspaceSymbols": "Just My Code",
+ "C_Cpp.inlayHints.parameterNames.enabled": true,
+ "C_Cpp.inlayHints.autoDeclarationTypes.showOnLeft": true,
+ "C_Cpp.intelliSenseMemoryLimit": 16384,
+ "makefile.makefilePath": "",
+ "makefile.dryrunSwitches": [
+ "--keep-going",
+ "--print-directory",
+ "KERNEL=nova",
+ "BOARD=pc",
+ "run/vscode",
+ "VERBOSE="
+ ],
+ "C_Cpp.default.intelliSenseMode": "linux-gcc-x64",
+ "C_Cpp.default.mergeConfigurations": true,
+ "C_Cpp.autocompleteAddParentheses": true,
+ "C_Cpp.intelliSenseCacheSize": 20480,
+ "makefile.buildBeforeLaunch": false,
+ "makefile.extensionOutputFolder": ".vscode",
+ "makefile.configurationCachePath": ".vscode/configurationCache.log",
+ "explorer.excludeGitIgnore": true,
+ "makefile.buildLog": ".vscode/build.log",
+ "definition-autocompletion.update_index_on_change": true,
+ "definition-autocompletion.update_index_interval": 5,
+ "C_Cpp.intelliSenseEngineFallback": "enabled",
+ "makefile.extensionLog": ".vscode/extension.log",
+ "makefile.ignoreDirectoryCommands": false,
+ "html.format.wrapLineLength": 80,
+ "editor.wordWrap": "bounded",
+ "editor.wordWrapColumn": 90,
+ "editor.fontSize": 13,
+ "terminal.integrated.shellIntegration.suggestEnabled": true,
+ "git.mergeEditor": true,
+ "merge-conflict.autoNavigateNextConflict.enabled": true,
+ "git.ignoreLimitWarning": true,
+ "customizeUI.statusBarPosition": "under-panel"
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..1a5ddae5a8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+# EalánOS — An Operating System for Heterogeneous Many-core Systems
+
+EalánOS is a research operating system, based on the [Genode OS Framework](https://genode.org/), that explores new architectural designs and resource management strategies for many-core systems with heterogeneous computing and memory resources. It is a reference implementation of the [MxKernel](https://mxkernel.org/) architecture.
+
+## MxKernel Architecture
+The MxKernel is a new operating system architecture inspired by many-core operating systems, such as [FOS](https://dl.acm.org/doi/abs/10.1145/1531793.1531805) and [Tesselation](https://www.usenix.org/event/hotpar09/tech/full_papers/liu/liu_html/), as well as hypervisors, exokernels and unikernels.
+Novel approaches of the MxKernel include the use of tasks, short-lived closed units of work, instead of threads as control-flow abstraction, and the concept of elastic cells as process abstraction. The architecture has first been described in the paper [MxKernel: Rethinking Operating System Architecture for Many-core Hardware](https://ess.cs.uos.de/research/projects/MxKernel/sfma-mxkernel.pdf) presented at the [9th Workshop on Systems for Multi-core and Heterogeneous Architectures](https://sites.google.com/site/sfma2019eurosys/).
+
+## Task-based programming
+EalánOS promotes task-parallel programming by including the [MxTasking](https://github.com/jmuehlig/mxtasking.git) task-parallel runtime library. MxTasking improves on the common task-parallel programming paradigm by allowing tasks to be annotated with hints about the tasks behavior, such as memory accesses. These annotations are used by the runtime environment to implement advanced features, like automatic prefetching of data and automatic synchronization of concurrent memory accesses.
+
+## Documentation
+Because EalánOS is based on Genode, the primary documentation, for now, can be found in the book [Genode Foundations](https://genode.org/documentation/genode-foundations-22-05.pdf).
+
+## Features added to Genode
+EalánOS extends the Genode OS framework by functionality needed and helpful for many-core systems with non-uniform memory access (NUMA), such as
+- A topology service that allows to query NUMA information from within a Genode component.
+- A port of [MxTasking](https://github.com/jmuehlig/mxtasking.git), a task-based framework designed to aid in developing parallel applications.
+- (WiP) A extension of Genode's RAM service that enables applications to allocate memory from a specific NUMA region, similar to libnuma's `numa_alloc_on_node`, and thus improve NUMA-locality of internal data objects.
+- (WiP) An interface for using Hardware Performance Monitoring Counters inside Genode components. Currently, performance counters are only implemented for AMD's Zen1 microarchitecture.
+
+### Acknowledgement
+The work on EalánOS and the MxKernel architecture is supported by the German Research Foundation (DFG) as part of the priority program 2037 "[Scalable Data Management on Future Hardware](https://dfg-spp2037.de/)" under Grant numbers SP968/9-1 and SP968/9-2.
+The MxTasking framework is developed as part of the same DFG project at the [DBIS group at TU Dortmund Universitiy](http://dbis.cs.tu-dortmund.de/cms/de/home/index.html) and funded under Grant numbers TE1117/2-1.
\ No newline at end of file
diff --git a/repos/base-hw/lib/mk/bootstrap-hw.inc b/repos/base-hw/lib/mk/bootstrap-hw.inc
index 16e2ecf94f..6788c8e1b6 100644
--- a/repos/base-hw/lib/mk/bootstrap-hw.inc
+++ b/repos/base-hw/lib/mk/bootstrap-hw.inc
@@ -10,6 +10,7 @@ SRC_CC += lib/base/allocator_avl.cc
SRC_CC += lib/base/avl_tree.cc
SRC_CC += lib/base/elf_binary.cc
SRC_CC += lib/base/heap.cc
+SRC_CC += lib/base/regional_heap.cc
SRC_CC += lib/base/registry.cc
SRC_CC += lib/base/log.cc
SRC_CC += lib/base/output.cc
diff --git a/repos/base-nova/include/nova/cap_map.h b/repos/base-nova/include/nova/cap_map.h
index 4ee78bf29e..e5b1d3d221 100644
--- a/repos/base-nova/include/nova/cap_map.h
+++ b/repos/base-nova/include/nova/cap_map.h
@@ -23,6 +23,8 @@
#include
+#include
+
#include
#include
@@ -36,9 +38,10 @@ namespace Genode {
addr_t _base = 0;
addr_t _last = 0;
- enum {
+ enum
+ {
HEADER = sizeof(_base) + sizeof(_mutex) + sizeof(_last),
- CAP_RANGE_SIZE = 4096,
+ CAP_RANGE_SIZE = 131072,
WORDS = (CAP_RANGE_SIZE - HEADER - sizeof(Avl_node)) / sizeof(addr_t),
};
@@ -51,8 +54,8 @@ namespace Genode {
Cap_range(addr_t base) : _base(base)
{
- static_assert(sizeof(*this) == CAP_RANGE_SIZE,
- "Cap_range misconfigured");
+ //static_assert(sizeof(*this) == CAP_RANGE_SIZE,
+ //"Cap_range misconfigured");
for (unsigned i = 0; i < elements(); i++)
_cap_array[i] = 0;
diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h
index db8fce16c7..85f5c6b8ac 100644
--- a/repos/base-nova/include/nova/syscall-generic.h
+++ b/repos/base-nova/include/nova/syscall-generic.h
@@ -3,8 +3,9 @@
* \author Norman Feske
* \author Sebastian Sumpf
* \author Alexander Boettcher
+ * \author Michael Müller
* \author Benjamin Lamowski
- * \date 2009-12-27
+ * \date 2022-12-13
*/
/*
@@ -36,6 +37,7 @@
#define _INCLUDE__NOVA__SYSCALL_GENERIC_H_
#include
+#include
namespace Nova {
@@ -65,6 +67,16 @@ namespace Nova {
NOVA_ASSIGN_PCI = 0xd,
NOVA_ASSIGN_GSI = 0xe,
NOVA_PD_CTRL = 0xf,
+ NOVA_YIELD = 0x10,
+ NOVA_MXINIT = 0x11,
+ NOVA_ALLOC_CORES= 0x12,
+ NOVA_CORE_ALLOC = 0x13,
+ NOVA_CREATE_CELL= 0x14,
+ NOVA_CELL_CTRL = 0x15,
+ NOVA_CONS_CTRL = 0x16,
+ NOVA_CPUID = 0x17,
+ NOVA_RESERVE_CPU= 0x18,
+ NOVA_CREATE_HAB = 0x19,
};
/**
@@ -135,11 +147,19 @@ namespace Nova {
bool has_feature_svm() const { return feature_flags & (1 << 2); }
struct Cpu_desc {
+ enum Vendor
+ {
+ UNKNOWN,
+ INTEL,
+ AMD
+ };
+
uint8_t flags;
uint8_t thread;
uint8_t core;
uint8_t package;
uint8_t acpi_id;
+ uint8_t vendor;
uint8_t family;
uint8_t model;
uint8_t stepping:4;
@@ -179,6 +199,36 @@ namespace Nova {
return desc ? desc->flags & 0x1 : false;
}
+ unsigned numa_nodes() const {
+ unsigned node_num = 1;
+ unsigned long nodes = 0x0;
+ unsigned long last_node = 0;
+
+ for (unsigned cpu = 0; cpu < cpu_max(); cpu++) {
+ Cpu_desc const *c = cpu_desc_of_cpu(cpu);
+ if (c->numa_id != last_node && !(nodes & (1<numa_id))) {
+ node_num++;
+ nodes |= (1 << c->numa_id);
+ }
+ }
+ return node_num;
+ }
+
+ unsigned numa_nodes() const {
+ unsigned node_num = 1;
+ unsigned long nodes = 0x0;
+ unsigned long last_node = 0;
+
+ for (unsigned cpu = 0; cpu < cpu_max(); cpu++) {
+ Cpu_desc const *c = cpu_desc_of_cpu(cpu);
+ if (c->numa_id != last_node && !(nodes & (1<numa_id))) {
+ node_num++;
+ nodes |= (1 << c->numa_id);
+ }
+ }
+ return node_num;
+ }
+
/**
* Resort CPU ids such, that
* - the boot CPU id is ever logical CPU id 0
@@ -196,12 +246,7 @@ namespace Nova {
unsigned const num_cpus = cpus();
bool too_many_cpus = false;
unsigned cpu_i = 0;
-
- /* fallback lambda in case re-ordering fails */
- auto remap_failure = [&] {
- for (uint16_t i = 0; i < max_cpus; i++) { map_cpus[i] = i; }
- return false;
- };
+ unsigned const num_nodes = numa_nodes();
/* assign boot cpu ever the virtual cpu id 0 */
Cpu_desc const * const boot = cpu_desc_of_cpu(boot_cpu);
@@ -211,45 +256,25 @@ namespace Nova {
map_cpus[cpu_i++] = (uint8_t)boot_cpu;
if (cpu_i >= num_cpus)
return true;
- if (cpu_i >= max_cpus)
- return remap_failure();
- /* assign cores + SMT threads first and skip E-cores */
- bool done = for_all_cpus([&](auto const &cpu, auto const kernel_cpu_id) {
- if (kernel_cpu_id == boot_cpu)
- return false;
+ for (uint8_t node = 0; node < num_nodes; node++) {
+ for (unsigned i = 0; i < num_cpus; i++) {
+ if (i == boot_cpu || !is_cpu_enabled(i))
+ continue;
- /* handle normal or P-core */
- if (cpu.e_core())
- return false;
+ Cpu_desc const *c = cpu_desc_of_cpu(i);
+ if (!(c->numa_id == node))
+ continue;
- map_cpus[cpu_i++] = (uint8_t)kernel_cpu_id;
+ cpu_numa_map[i] = c->numa_id;
+ map_cpus[cpu_i++] = (uint8_t)i;
- too_many_cpus = !!(cpu_i >= max_cpus);
+ if (cpu_i >= num_cpus)
+ return true;
+ }
+ }
- return (cpu_i >= num_cpus || too_many_cpus);
- });
-
- if (done)
- return too_many_cpus ? remap_failure() : true;
-
- /* assign remaining E-cores */
- done = for_all_cpus([&](auto &cpu, auto &kernel_cpu_id) {
- if (kernel_cpu_id == boot_cpu)
- return false;
-
- /* handle solely E-core */
- if (!cpu.e_core())
- return false;
-
- map_cpus[cpu_i++] = (uint16_t)kernel_cpu_id;
-
- too_many_cpus = !!(cpu_i >= max_cpus);
-
- return (cpu_i >= num_cpus || too_many_cpus);
- });
-
- return too_many_cpus ? remap_failure() : done;
+ return false;
}
/**
@@ -323,6 +348,28 @@ namespace Nova {
SC_EC_TIME = 3,
};
+ /**
+ * Hpc operations
+ *
+ */
+ enum Hpc_op
+ {
+ HPC_SETUP = 6U,
+ HPC_START = 7U,
+ HPC_STOP = 8U,
+ HPC_RESET = 9U,
+ HPC_READ = 10U,
+ };
+
+ /**
+ * Cell operations
+ */
+ enum Cell_op
+ {
+ SHRINK = 0,
+ GROW = 1,
+ };
+
/**
* Pd operations
*/
@@ -612,7 +659,7 @@ namespace Nova {
public:
- enum { DEFAULT_QUANTUM = 10000, DEFAULT_PRIORITY = 64 };
+ enum { DEFAULT_QUANTUM = 1500, DEFAULT_PRIORITY = 64 };
Qpd(mword_t quantum = DEFAULT_QUANTUM,
mword_t priority = DEFAULT_PRIORITY)
@@ -891,5 +938,13 @@ namespace Nova {
SM_SEL_EC = 0x1d, /* convention on Genode */
};
+ /**
+ * Console operations
+ */
+ enum Cons_op
+ {
+ LOCK = 0,
+ UNLOCK = 1,
+ };
}
#endif /* _INCLUDE__NOVA__SYSCALL_GENERIC_H_ */
diff --git a/repos/base-nova/include/spec/64bit/nova/syscalls.h b/repos/base-nova/include/spec/64bit/nova/syscalls.h
index f116d73585..82e28b7594 100644
--- a/repos/base-nova/include/spec/64bit/nova/syscalls.h
+++ b/repos/base-nova/include/spec/64bit/nova/syscalls.h
@@ -37,6 +37,7 @@
#include
#include
+#include
#define ALWAYS_INLINE __attribute__((always_inline))
@@ -45,7 +46,7 @@ namespace Nova {
ALWAYS_INLINE
inline mword_t rdi(Syscall s, uint8_t flags, mword_t sel)
{
- return sel << 8 | (flags & 0xf) << 4 | s;
+ return sel << 9 | (flags & 0xf) << 5 | s;
}
@@ -155,7 +156,7 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t call(mword_t pt)
{
- return syscall_1(NOVA_CALL, 0, pt, 0);
+ return syscall_1(NOVA_CALL, 0, 0, pt);
}
@@ -254,6 +255,36 @@ namespace Nova {
return util_time(NOVA_EC_CTRL, ec, Ec_op::EC_TIME, time);
}
+ ALWAYS_INLINE
+ inline uint8_t hpc_ctrl(Hpc_op op, mword_t sel, mword_t type, mword_t &p1, mword_t &p2, mword_t &p3)
+ {
+ uint8_t res = syscall_6(NOVA_EC_CTRL, op, sel, type, p1, p2, p3);
+ return res;
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t hpc_read(mword_t sel, mword_t type, mword_t &value)
+ {
+ return syscall_5(NOVA_EC_CTRL, HPC_READ, sel, type, value);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t hpc_start(mword_t sel, mword_t type)
+ {
+ return syscall_1(NOVA_EC_CTRL, HPC_START, sel, type);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t hpc_stop(mword_t sel, mword_t type)
+ {
+ return syscall_1(NOVA_EC_CTRL, HPC_STOP, sel, type);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t hpc_reset(mword_t sel, mword_t type, mword_t val)
+ {
+ return syscall_2(NOVA_EC_CTRL, HPC_RESET, sel, type, val);
+ }
ALWAYS_INLINE
inline uint8_t create_sc(mword_t sc, mword_t pd, mword_t ec, Qpd qpd)
@@ -416,5 +447,76 @@ namespace Nova {
msi_data = cpu;
return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
}
+
+ ALWAYS_INLINE
+ inline uint8_t yield(bool release_core = true, bool block = true)
+ {
+ Nova::uint8_t flags = block ? release_core : 3;
+ return syscall_0(NOVA_YIELD, flags, 0);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t mxinit(mword_t rip, mword_t id, mword_t channel)
+ {
+ return syscall_2(NOVA_MXINIT, 0, id, rip, channel);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t alloc_cores(mword_t count, mword_t &allocated, mword_t &remainder)
+ {
+ Nova::mword_t rest = 0;
+ Nova::mword_t null = 0;
+ Nova::uint8_t res = syscall_6(NOVA_ALLOC_CORES, 0, 0, count, allocated, rest, null);
+ remainder = rest;
+ return res;
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t wake_core(mword_t core)
+ {
+ return syscall_1(NOVA_RESERVE_CPU, 0, 0, core);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t core_allocation(mword_t &allocation, bool mask = false)
+ {
+ return syscall_5(NOVA_CORE_ALLOC, static_cast(mask), 0, allocation, allocation);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t cpu_id(mword_t &cpuid)
+ {
+ return syscall_5(NOVA_CPUID, 0, 0, cpuid, cpuid);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t create_cell(mword_t pd, mword_t prio, mword_t mask, mword_t start, mword_t count)
+ {
+ return syscall_5(NOVA_CREATE_CELL, static_cast(prio), pd, mask, start, count);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t update_cell(mword_t pd, mword_t mask, mword_t index)
+ {
+ return syscall_2(NOVA_CELL_CTRL, Cell_op::GROW, pd, mask, index);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t create_habitat(mword_t start_cpu, mword_t size)
+ {
+ return syscall_2(NOVA_CREATE_HAB, 0, 0, start_cpu, size);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t acquire_console()
+ {
+ return syscall_0(NOVA_CONS_CTRL, Nova::Cons_op::LOCK);
+ }
+
+ ALWAYS_INLINE
+ inline uint8_t release_console()
+ {
+ return syscall_0(NOVA_CONS_CTRL, Nova::Cons_op::UNLOCK);
+ }
}
#endif /* _INCLUDE__SPEC__64BIT__NOVA__SYSCALLS_H_ */
diff --git a/repos/base-nova/lib/mk/base-nova-common.mk b/repos/base-nova/lib/mk/base-nova-common.mk
index e990dc33f7..f395bc6486 100644
--- a/repos/base-nova/lib/mk/base-nova-common.mk
+++ b/repos/base-nova/lib/mk/base-nova-common.mk
@@ -14,6 +14,7 @@ SRC_CC += stack_area_addr.cc
SRC_CC += cap_map.cc
SRC_CC += capability.cc
SRC_CC += signal_transmitter.cc
+SRC_CC += perf.cc
#
# Prevent the compiler from deleting null pointer checks related to 'this == 0'
diff --git a/repos/base-nova/lib/mk/core-nova.inc b/repos/base-nova/lib/mk/core-nova.inc
index 206f936546..31dbcdd6fc 100644
--- a/repos/base-nova/lib/mk/core-nova.inc
+++ b/repos/base-nova/lib/mk/core-nova.inc
@@ -43,7 +43,8 @@ SRC_CC += stack_area.cc \
signal_receiver.cc \
vm_session_component.cc \
vm_session_common.cc \
- heartbeat.cc
+ heartbeat.cc \
+ topo_session_component.cc
INC_DIR += $(REP_DIR)/src/core/include \
$(REP_DIR)/src/include \
@@ -77,4 +78,5 @@ vpath platform_rom_modules.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
vpath heartbeat.cc $(GEN_CORE_DIR)
vpath vm_session_common.cc $(GEN_CORE_DIR)
+vpath topo_session_component.cc $(GEN_CORE_DIR)
vpath %.cc $(REP_DIR)/src/core
diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash
index 2101237a0c..ecb39db6d6 100644
--- a/repos/base-nova/ports/nova.hash
+++ b/repos/base-nova/ports/nova.hash
@@ -1 +1 @@
-d58086480d6a21a06bbd956e2d2e605d0f39b6b2
+968b205c5c1b6a93846626cf7307b19eb6bac891
diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port
index cc0e8e0ac2..ac04cb3edb 100644
--- a/repos/base-nova/ports/nova.port
+++ b/repos/base-nova/ports/nova.port
@@ -2,9 +2,9 @@ LICENSE := GPLv2
VERSION := git
DOWNLOADS := nova.git
-# r10 branch
-URL(nova) := https://github.com/alex-ab/NOVA.git
-REV(nova) := fc9ad04ecec3911302451fcbf6cd87063be66ad0
+# feature/numa branch
+URL(nova) := https://github.com/mmueller41/NOVA.git
+REV(nova) := tukija
DIR(nova) := src/kernel/nova
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))
diff --git a/repos/base-nova/recipes/api/base-nova/hash b/repos/base-nova/recipes/api/base-nova/hash
index 9c9994f2f2..211cd99a21 100644
--- a/repos/base-nova/recipes/api/base-nova/hash
+++ b/repos/base-nova/recipes/api/base-nova/hash
@@ -1 +1 @@
-2024-10-07 d1a751a3b41d145c3a97b3431ae1f006050fee10
+2024-09-13 1567ef314f1b68c8871e29ffc0ba19e9dbaaee8a
diff --git a/repos/base-nova/recipes/src/base-nova/hash b/repos/base-nova/recipes/src/base-nova/hash
index 02d5a1981a..241611d6e5 100644
--- a/repos/base-nova/recipes/src/base-nova/hash
+++ b/repos/base-nova/recipes/src/base-nova/hash
@@ -1 +1 @@
-2024-12-10 bb446406fbb1173c3f243fe323d5cad8423ff958
+2024-11-26 12d153ce5fc0661b11808621eaffeed3a18aa460
diff --git a/repos/base-nova/src/core/core_log_out.cc b/repos/base-nova/src/core/core_log_out.cc
index 5eba5717cd..be31c052c3 100644
--- a/repos/base-nova/src/core/core_log_out.cc
+++ b/repos/base-nova/src/core/core_log_out.cc
@@ -18,13 +18,13 @@
#include
#include
-void Core::Core_log::out(char const c)
+void Genode::Core_log::out(char const c)
{
enum { CLOCK = 0, BAUDRATE = 115200 };
- static X86_uart uart(0x3f8/*Bios_data_area::singleton()->serial_port()*/,
+ static X86_uart uart(0x2f8/*Bios_data_area::singleton()->serial_port()*/,
CLOCK, BAUDRATE);
if (c == '\n')
uart.put_char('\r');
uart.put_char(c);
-}
+}
\ No newline at end of file
diff --git a/repos/base-nova/src/core/include/platform.h b/repos/base-nova/src/core/include/platform.h
index 2b40e106d9..d5a26f2963 100644
--- a/repos/base-nova/src/core/include/platform.h
+++ b/repos/base-nova/src/core/include/platform.h
@@ -19,6 +19,8 @@
#include
#include
#include
+#include
+#include
namespace Core { class Platform; }
@@ -51,7 +53,10 @@ class Core::Platform : public Platform_generic
/* map of virtual cpu ids in Genode to kernel cpu ids */
uint16_t map_cpu_ids[MAX_SUPPORTED_CPUS];
- uint8_t cpu_numa_map[MAX_SUPPORTED_CPUS];
+ uint8_t cpu_numa_map[MAX_SUPPORTED_CPUS];
+ /* map of kernel NUMA region to Genode memory ranges */
+ Genode::Range_allocator::Range numa_mem_ranges[MAX_SUPPORTED_CPUS]; // TODO: Add new macro for max of numa regions
+
addr_t _map_pages(addr_t phys_page, addr_t pages,
bool guard_page = false);
@@ -121,10 +126,27 @@ class Core::Platform : public Platform_generic
unsigned pager_index(Affinity::Location location) const;
unsigned kernel_cpu_id(Affinity::Location location) const;
+ /**
+ * @brief ID of NUMA region the CPU belongs to
+ *
+ * @param kernel_cpu_id id of CPU
+ * @return unsigned ID of corresponding NUMA region
+ */
unsigned domain_of_cpu(unsigned kernel_cpu_id) const {
return cpu_numa_map[kernel_cpu_id];
}
+ /**
+ * @brief Return memory range of a given NUMA region
+ *
+ * @param numa_id ID of NUMA region
+ * @return Genode::Range_allocator::Range physical address range for this NUMA region
+ */
+
+ Genode::Range_allocator::Range &mem_range(unsigned numa_id) {
+ return numa_mem_ranges[numa_id];
+ }
+
Affinity::Location sanitize(Affinity::Location location) {
return Affinity::Location(location.xpos() % _cpus.width(),
location.ypos() % _cpus.height(),
@@ -136,15 +158,17 @@ class Core::Platform : public Platform_generic
*/
unsigned core_pd_sel() const { return _core_pd_sel; }
- void for_each_location(auto const &fn)
- {
- for (unsigned x = 0; x < _cpus.width(); x++) {
- for (unsigned y = 0; y < _cpus.height(); y++) {
- Affinity::Location location(x, y, 1, 1);
- fn(location);
+ template
+ void for_each_location(FUNC const &fn)
+ {
+ for (unsigned x = 0; x < _cpus.width(); x++) {
+ for (unsigned y = 0; y < _cpus.height(); y++) {
+ Affinity::Location location(x, y, 1, 1);
+ fn(location);
+ }
}
}
- }
-};
+ };
+}
#endif /* _CORE__INCLUDE__PLATFORM_H_ */
diff --git a/repos/base-nova/src/core/pd_session_support.cc b/repos/base-nova/src/core/pd_session_support.cc
index 248038b390..6d0974c07b 100644
--- a/repos/base-nova/src/core/pd_session_support.cc
+++ b/repos/base-nova/src/core/pd_session_support.cc
@@ -108,6 +108,58 @@ Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range const vi
return Map_result::OK;
}
+void _calculate_mask_for_location(Nova::mword_t *core_mask, const Affinity::Location &loc)
+{
+ for (unsigned y = loc.ypos(); y < loc.ypos() + loc.height(); y++)
+ {
+ for (unsigned x = loc.xpos(); x < loc.xpos()+loc.width(); x++)
+ {
+ unsigned kernel_cpu = platform_specific().kernel_cpu_id(Affinity::Location(x, y, loc.width(), loc.height()));
+ unsigned i = kernel_cpu / (sizeof(Nova::mword_t) * 8);
+ unsigned b = kernel_cpu % (sizeof(Nova::mword_t) * 8);
+ core_mask[i] |= (1UL << b);
+
+ Genode::log("core_mask[", i, "]=", core_mask[i], " i=", i, "b=", b, "kernel_cpu=", kernel_cpu);
+ }
+ }
+}
+
+
+void Pd_session_component::create_cell(long prioritiy, const Affinity::Location &loc)
+{
+ Nova::uint8_t err = Nova::NOVA_OK;
+ unsigned num_cpus = platform_specific().MAX_SUPPORTED_CPUS;
+ unsigned num_vect = num_cpus / (sizeof(Nova::mword_t) * 8);
+ Nova::mword_t core_mask[num_vect];
+
+ Genode::memset(core_mask, 0, sizeof(core_mask));
+
+ _calculate_mask_for_location(core_mask, loc);
+
+ log("Requested to create new cell for <", this->label(), "> of priority ", prioritiy, " at ", loc);
+ for (unsigned i = 0; i < num_vect; i++) {
+ if ((err = Nova::create_cell(_pd->pd_sel(), prioritiy, core_mask[i], i, 1) != Nova::NOVA_OK))
+ {
+ error("Could not create new cell: ", err);
+ }
+ }
+}
+
+void Pd_session_component::update_cell(const Affinity::Location &loc)
+{
+ Nova::uint8_t err = Nova::NOVA_OK;
+ unsigned num_cpus = platform_specific().affinity_space().total();
+ unsigned num_vect = num_cpus / (sizeof(Nova::mword_t) * 8);
+ Nova::mword_t core_mask[num_vect];
+
+ _calculate_mask_for_location(core_mask, loc);
+
+ for (unsigned i = 0; i < num_vect; i++) {
+ if ((err = Nova::update_cell(_pd->pd_sel(), core_mask[i], i))) {
+ error("Failed to update cell <", label(), ">: ", err);
+ }
+ }
+}
using State = Genode::Pd_session::Managing_system_state;
diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc
index ca974d40dd..295f90d7df 100644
--- a/repos/base-nova/src/core/platform.cc
+++ b/repos/base-nova/src/core/platform.cc
@@ -103,7 +103,7 @@ addr_t Core::Platform::_map_pages(addr_t const phys_addr, addr_t const pages,
*****************************/
-enum { CORE_PAGER_UTCB_ADDR = 0xbff02000 };
+enum { CORE_PAGER_UTCB_ADDR = 0xfff02000 };
/**
@@ -200,7 +200,7 @@ static void page_fault_handler()
static addr_t core_pager_stack_top()
{
- enum { STACK_SIZE = 4*1024 };
+ enum { STACK_SIZE = 8*1024 };
static char stack[STACK_SIZE];
return (addr_t)&stack[STACK_SIZE - sizeof(addr_t)];
}
@@ -445,6 +445,7 @@ Core::Platform::Platform()
size_t kernel_memory = 0;
log("Found ", num_mem_desc, " memory entries in HIP");
+ memset(numa_mem_ranges, 0, sizeof(Genode::Range_allocator::Range) * MAX_SUPPORTED_CPUS);
/*
* All "available" ram must be added to our physical allocator before all
* non "available" regions that overlaps with ram get removed.
@@ -476,6 +477,11 @@ Core::Platform::Platform()
_io_mem_alloc.remove_range((addr_t)base, (size_t)size);
ram_alloc().add_range((addr_t)base, (size_t)size);
+ log("Add mem range ", reinterpret_cast(base), "-", reinterpret_cast(base + size), " for node ", mem_desc->domain);
+ if (numa_mem_ranges[mem_desc->domain].start == 0)
+ numa_mem_ranges[mem_desc->domain] = {base, base + size};
+ else if (base > numa_mem_ranges[mem_desc->domain].end)
+ numa_mem_ranges[mem_desc->domain].end = base + size;
}
addr_t hyp_log = 0;
@@ -795,13 +801,13 @@ Core::Platform::Platform()
log(Number_of_bytes(kernel_memory), " kernel memory"); log("");
/* add capability selector ranges to map */
- unsigned const first_index = 0x2000;
+ unsigned const first_index = 0x0000;
unsigned index = first_index;
for (unsigned i = 0; i < 32; i++)
{
void * phys_ptr = nullptr;
- ram_alloc().alloc_aligned(get_page_size(), get_page_size_log2()).with_result(
+ ram_alloc().alloc_aligned(128*get_page_size(), get_page_size_log2()).with_result(
[&] (void *ptr) { phys_ptr = ptr; },
[&] (Range_allocator::Alloc_error) { /* covered by nullptr test below */ });
@@ -809,7 +815,7 @@ Core::Platform::Platform()
break;
addr_t phys_addr = reinterpret_cast(phys_ptr);
- addr_t core_local_addr = _map_pages(phys_addr, 1);
+ addr_t core_local_addr = _map_pages(phys_addr, 128);
if (!core_local_addr) {
ram_alloc().free(phys_ptr);
@@ -895,6 +901,7 @@ Core::Platform::Platform()
(unsigned)(sc_idle_base + kernel_cpu_id),
"killed");
});
+ log("Added idle ECs to trace sources");
/* add exception handler EC for core and EC root thread to trace sources */
struct Core_trace_source : public Trace::Source::Info_accessor,
@@ -943,6 +950,7 @@ Core::Platform::Platform()
registry.insert(this);
}
};
+ log("Added exception handler EC");
new (core_mem_alloc())
Core_trace_source(Trace::sources(),
@@ -953,6 +961,7 @@ Core::Platform::Platform()
Core_trace_source(Trace::sources(),
Affinity::Location(0, 0, _cpus.width(), 1),
hip.sel_exc + 1, "root");
+ log("Created trace sources");
}
diff --git a/repos/base-nova/src/core/ram_dataspace_support.cc b/repos/base-nova/src/core/ram_dataspace_support.cc
index fbc0cb1c62..c3afb04ae6 100644
--- a/repos/base-nova/src/core/ram_dataspace_support.cc
+++ b/repos/base-nova/src/core/ram_dataspace_support.cc
@@ -56,29 +56,35 @@ static inline void * alloc_region(Dataspace_component &ds, const size_t size)
void Ram_dataspace_factory::_clear_ds(Dataspace_component &ds)
{
+
size_t const page_rounded_size = align_addr(ds.size(), get_page_size_log2());
- size_t memset_count = page_rounded_size / 4;
+ size_t memset_count = page_rounded_size / 32;
addr_t memset_ptr = ds.core_local_addr();
- if ((memset_count * 4 == page_rounded_size) && !(memset_ptr & 0x3))
- asm volatile ("rep stosl" : "+D" (memset_ptr), "+c" (memset_count)
+ if ((memset_count * 32 == page_rounded_size) && !(memset_ptr & 0x3))
+ {
+ asm volatile ("rep stosq" : "+D" (memset_ptr), "+c" (memset_count)
: "a" (0) : "memory");
- else
+ } else
memset(reinterpret_cast(memset_ptr), 0, page_rounded_size);
+}
+
+void Ram_dataspace_factory::_unmap_ds_from_core(Dataspace_component &ds)
+{
+ size_t const page_rounded_size = align_addr(ds.size(), get_page_size_log2());
/* we don't keep any core-local mapping */
unmap_local(*reinterpret_cast(Thread::myself()->utcb()),
- ds.core_local_addr(),
- page_rounded_size >> get_page_size_log2());
+ ds.core_local_addr(),
+ page_rounded_size >> get_page_size_log2());
- platform().region_alloc().free((void*)ds.core_local_addr(),
- page_rounded_size);
+ platform().region_alloc().free((void *)ds.core_local_addr(),
+ page_rounded_size);
ds.assign_core_local_addr(nullptr);
}
-
void Ram_dataspace_factory::_export_ram_ds(Dataspace_component &ds) {
size_t page_rounded_size = align_addr(ds.size(), get_page_size_log2());
diff --git a/repos/base-nova/src/lib/base/perf.cc b/repos/base-nova/src/lib/base/perf.cc
new file mode 100644
index 0000000000..fd51679e4d
--- /dev/null
+++ b/repos/base-nova/src/lib/base/perf.cc
@@ -0,0 +1,86 @@
+
+/*
+ * \brief Performance Counter infrastructure, NOVA-specific implemantation
+ * \author Michael Müller
+ * \date 2022-12-15
+ */
+
+#include
+
+#include
+#include
+#include
+
+unsigned long Genode::Trace::Performance_counter::private_freemask { 0xffff };
+unsigned long Genode::Trace::Performance_counter::shared_freemask { 0xffff0000 };
+
+void Genode::Trace::Performance_counter::_init_masks()
+{
+ Nova::Hip::Cpu_desc::Vendor vendor = Nova::Hip::Cpu_desc::AMD;
+ if (vendor == Nova::Hip::Cpu_desc::AMD)
+ {
+ private_freemask = 0x3f; // 6 core performance counters
+ shared_freemask = 0x1f0000; // 5 L3 complex performance counters
+ }
+ else if (vendor == Nova::Hip::Cpu_desc::INTEL)
+ {
+ private_freemask = 0x7fff;
+ shared_freemask = 0x7fff0000; // 15 CBO performance counters
+ }
+}
+
+void Genode::Trace::Performance_counter::setup(unsigned counter, uint64_t event, uint64_t mask, uint64_t flags)
+{
+ Nova::mword_t evt = event;
+ Nova::mword_t msk = mask;
+ Nova::mword_t flg = flags;
+ Nova::uint8_t rc;
+ Nova::mword_t type = (counter >>4);
+ Nova::mword_t sel = type == Performance_counter::CORE ? counter : counter & 0xf;
+
+ if ((rc = (Nova::hpc_ctrl(Nova::HPC_SETUP, sel, type, evt, msk, flg))) != Nova::NOVA_OK)
+ throw Genode::Trace::Pfc_access_error(rc);
+}
+
+void Genode::Trace::Performance_counter::start(unsigned counter)
+{
+ Nova::uint8_t rc;
+ Nova::mword_t type = (counter >> 4);
+ Nova::mword_t sel = type == Performance_counter::CORE ? counter : counter & 0xf;
+
+ if ((rc = Nova::hpc_start(sel, type)) != Nova::NOVA_OK)
+ throw Genode::Trace::Pfc_access_error(rc);
+}
+
+void Genode::Trace::Performance_counter::stop(unsigned counter)
+{
+ Nova::uint8_t rc;
+ Nova::mword_t type = (counter >>4);
+ Nova::mword_t sel = type == Performance_counter::CORE ? counter : counter & 0xf;
+
+ if ((rc = Nova::hpc_stop(sel, type)) != Nova::NOVA_OK)
+ throw Genode::Trace::Pfc_access_error(rc);
+}
+
+void Genode::Trace::Performance_counter::reset(unsigned counter, unsigned val)
+{
+ Nova::uint8_t rc;
+ Nova::mword_t type = (counter >>4);
+ Nova::mword_t sel = type == Performance_counter::CORE ? counter : counter & 0xf;
+
+ if ((rc = Nova::hpc_reset(sel, type, val)) != Nova::NOVA_OK)
+ throw Genode::Trace::Pfc_access_error(rc);
+}
+
+Genode::uint64_t Genode::Trace::Performance_counter::read(unsigned counter)
+{
+ Nova::uint8_t rc;
+ Nova::mword_t value = 0;
+ Nova::mword_t type = (counter >>4);
+ Nova::mword_t sel = type == Performance_counter::CORE ? counter : counter & 0xf;
+
+ if ((rc = Nova::hpc_read(sel, type, value)) != Nova::NOVA_OK)
+ throw Genode::Trace::Pfc_access_error(rc);
+
+ return static_cast(value);
+}
\ No newline at end of file
diff --git a/repos/base/include/base/affinity.h b/repos/base/include/base/affinity.h
index a41bcc4a24..2d45725ba2 100644
--- a/repos/base/include/base/affinity.h
+++ b/repos/base/include/base/affinity.h
@@ -93,6 +93,7 @@ class Genode::Affinity
return Affinity::Space(node.attribute_value("width", 0U),
node.attribute_value("height", 0U));
}
+
};
@@ -166,6 +167,13 @@ class Genode::Affinity
node.attribute_value("height", default_height));
}
+ bool operator==(Location const &rhs) {
+ return this->_xpos == rhs._xpos && this->_ypos == rhs._ypos && this->height() == rhs.height() && this->width() == rhs.width();
+ }
+
+ bool operator!=(Location const &rhs) {
+ return !(*this == rhs);
+ }
};
private:
@@ -236,6 +244,30 @@ class Genode::Affinity
}
};
+namespace Genode {
+ static inline void print(Output &out, const Affinity::Space &space)
+ {
+ Genode::print(out, "(");
+ Genode::print(out, space.width());
+ Genode::print(out, ",");
+ Genode::print(out, space.height());
+ Genode::print(out, ")");
+ }
+
+ static inline void print(Output &out, const Affinity::Location &loc)
+ {
+ Genode::print(out, "(");
+ Genode::print(out, loc.xpos());
+ Genode::print(out, ",");
+ Genode::print(out, loc.ypos());
+ Genode::print(out, ",");
+ Genode::print(out, loc.width());
+ Genode::print(out, "×");
+ Genode::print(out, loc.height());
+ Genode::print(out, ")");
+ }
+}
+
Genode::Affinity::Location Genode::Affinity::Space::location_of_index(int index) const
{
diff --git a/repos/base/include/base/attached_ram_dataspace.h b/repos/base/include/base/attached_ram_dataspace.h
index 1f641f06e9..267da5ed4f 100644
--- a/repos/base/include/base/attached_ram_dataspace.h
+++ b/repos/base/include/base/attached_ram_dataspace.h
@@ -14,6 +14,7 @@
#ifndef _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_
#define _INCLUDE__BASE__ATTACHED_RAM_DATASPACE_H_
+#include
#include
#include
#include
@@ -112,6 +113,7 @@ class Genode::Attached_ram_dataspace
_size(size), _ram(&ram), _rm(&rm), _cache(cache)
{
_alloc_and_attach();
+ memset(_local_addr, 0, _size);
}
/**
diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h
index 7c70c369bd..2d30aa2f2a 100644
--- a/repos/base/include/base/child.h
+++ b/repos/base/include/base/child.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
@@ -334,6 +335,8 @@ class Genode::Child : protected Rpc_object,
/* arguments fetched by the child in response to a yield signal */
Mutex _yield_request_mutex { };
Resource_args _yield_request_args { };
+ Mutex _resource_gain_mutex { };
+ Resource_args _gained_resources { };
/* number of unanswered heartbeat signals */
unsigned _outstanding_heartbeats = 0;
@@ -613,6 +616,7 @@ class Genode::Child : protected Rpc_object,
Env_connection _cpu { *this, Env::cpu(), _policy.name() };
Env_connection _log { *this, Env::log(), _policy.name() };
Env_connection _binary { *this, Env::binary(), _policy.binary_name() };
+ Env_connection _topo { *this, Env::topo(), _policy.name() };
Constructible > _linker { };
@@ -764,6 +768,7 @@ class Genode::Child : protected Rpc_object,
Ram_allocator &ram() { return _pd.session(); }
Ram_allocator const &ram() const { return _pd.session(); }
Cpu_session &cpu() { return _cpu.session(); }
+ Topo_session &topo() { return _topo.session(); }
Pd_session &pd() { return _pd.session(); }
Pd_session const &pd() const { return _pd.session(); }
@@ -782,6 +787,14 @@ class Genode::Child : protected Rpc_object,
*/
void yield(Resource_args const &args);
+ /**
+ * Bestow resources on the child
+ *
+ * By calling this method, the child will be notified about
+ * the having gained the specified amount of resources.
+ */
+ void accept(Resource_args const &args);
+
/**
* Notify the child about newly available resources
*/
@@ -818,6 +831,7 @@ class Genode::Child : protected Rpc_object,
void resource_request(Resource_args const &) override;
void yield_sigh(Signal_context_capability) override;
Resource_args yield_request() override;
+ Resource_args gained_resources() override;
void yield_response() override;
void heartbeat_sigh(Signal_context_capability) override;
void heartbeat_response() override;
diff --git a/repos/base/include/base/env.h b/repos/base/include/base/env.h
index 57842dad8b..3425abbe67 100644
--- a/repos/base/include/base/env.h
+++ b/repos/base/include/base/env.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
namespace Genode { struct Env; }
@@ -48,6 +49,12 @@ struct Genode::Env : Interface
*/
Ram_allocator &ram() { return pd(); }
+ /**
+ * @brief Topology model
+ *
+ */
+ virtual Topo_session &topo() = 0;
+
/**
* Entrypoint for handling RPC requests and signals
*/
@@ -63,6 +70,12 @@ struct Genode::Env : Interface
*/
virtual Pd_session_capability pd_session_cap() = 0;
+ /**
+ * @brief Return the Topo-session capability
+ *
+ */
+ virtual Topo_session_capability topo_session_cap() = 0;
+
/**
* ID space of sessions obtained from the parent
*/
diff --git a/repos/base/include/base/local_connection.h b/repos/base/include/base/local_connection.h
index dbacb8bca9..264951f8d9 100644
--- a/repos/base/include/base/local_connection.h
+++ b/repos/base/include/base/local_connection.h
@@ -93,8 +93,15 @@ struct Genode::Local_connection_base : Noncopyable
if (_session_state->phase == Session_state::INSUFFICIENT_RAM_QUOTA
|| _session_state->phase == Session_state::INSUFFICIENT_CAP_QUOTA)
- warning("giving up to increase session quota for ", service.name(), " session "
+ {
+ warning("[", label, "] giving up to increase session quota for ", service.name(), " session "
"after ", (int)NUM_ATTEMPTS, " attempts");
+ if (_session_state->phase == Session_state::INSUFFICIENT_RAM_QUOTA)
+ warning("Insufficient RAM quota: ", resources.ram_quota.value);
+
+ if (_session_state->phase == Session_state::INSUFFICIENT_CAP_QUOTA)
+ warning("Insufficient CAP quota ", resources.cap_quota.value);
+ }
}
void close()
diff --git a/repos/base/include/base/ram_allocator.h b/repos/base/include/base/ram_allocator.h
index a11d3f6a4d..316fd06d74 100644
--- a/repos/base/include/base/ram_allocator.h
+++ b/repos/base/include/base/ram_allocator.h
@@ -40,6 +40,8 @@ struct Genode::Ram_allocator : Interface
struct Denied : Exception { };
+ typedef unsigned Numa_id;
+
/**
* Allocate RAM dataspace
*
@@ -50,6 +52,7 @@ struct Genode::Ram_allocator : Interface
* \return capability to RAM dataspace, or error code of type 'Alloc_error'
*/
virtual Alloc_result try_alloc(size_t size, Cache cache = CACHED) = 0;
+ virtual Alloc_result try_alloc(size_t size, Numa_id numa_id, Cache cache = CACHED) = 0;
/**
* Allocate RAM dataspace
@@ -154,6 +157,10 @@ class Genode::Constrained_ram_allocator : public Ram_allocator
);
}
+ Alloc_result try_alloc(size_t size, Numa_id, Cache cache = CACHED) override {
+ return this->Constrained_ram_allocator::try_alloc(size, cache); /* overriden in platform specific code */
+ }
+
void free(Ram_dataspace_capability ds) override
{
size_t const size = _ram_alloc.dataspace_size(ds);
diff --git a/repos/base/include/base/regional_heap.h b/repos/base/include/base/regional_heap.h
new file mode 100644
index 0000000000..f9332383f1
--- /dev/null
+++ b/repos/base/include/base/regional_heap.h
@@ -0,0 +1,230 @@
+/*
+ * \brief Heap partition
+ * \author Norman Feske
+ * \date 2006-05-15
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ * Copyright (C) 2006-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__BASE__REGIONAL_HEAP_H_
+#define _INCLUDE__BASE__REGIONAL_HEAP_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode {
+
+ class Regional_heap;
+ class Sliced_regional_heap;
+}
+
+
+/**
+ * Heap that uses dataspaces as backing store and has a physical memory range limited to a single NUMA region
+ *
+ * The heap class provides an allocator that uses a list of dataspaces of a RAM
+ * allocator as backing store. One dataspace may be used for holding multiple
+ * blocks.
+ */
+class Genode::Regional_heap : public Allocator
+{
+ private:
+
+ class Dataspace : public List::Element
+ {
+ private:
+
+ /*
+ * Noncopyable
+ */
+ Dataspace(Dataspace const &);
+ Dataspace &operator = (Dataspace const &);
+
+ public:
+
+ Ram_dataspace_capability cap;
+ void *local_addr;
+ size_t size;
+
+ Dataspace(Ram_dataspace_capability c, void *local_addr, size_t size)
+ : cap(c), local_addr(local_addr), size(size) { }
+ };
+
+ /*
+ * This structure exists only to make sure that the dataspaces are
+ * destroyed after the AVL allocator.
+ */
+ class Dataspace_pool : public List
+ {
+ private:
+
+ /*
+ * Noncopyable
+ */
+ Dataspace_pool(Dataspace_pool const &);
+ Dataspace_pool &operator = (Dataspace_pool const &);
+
+ public:
+
+ Ram_allocator *ram_alloc; /* backing store */
+ Region_map *region_map;
+
+ Dataspace_pool(Ram_allocator *ram, Region_map *rm)
+ : ram_alloc(ram), region_map(rm) { }
+
+ ~Dataspace_pool();
+
+ void remove_and_free(Dataspace &);
+
+ void reassign_resources(Ram_allocator *ram, Region_map *rm) {
+ ram_alloc = ram, region_map = rm; }
+ };
+
+ Mutex mutable _mutex { };
+ Reconstructible _alloc; /* local allocator */
+ Dataspace_pool _ds_pool; /* list of dataspaces */
+ size_t _quota_limit { 0 };
+ size_t _quota_used { 0 };
+ size_t _chunk_size { 0 };
+ Ram_allocator::Numa_id _numa_id; /* ID of NUMA region to serve allocations from */
+
+ using Alloc_ds_result = Attempt;
+
+ /**
+ * Allocate a new dataspace of the specified size
+ *
+ * \param size number of bytes to allocate
+ * \param enforce_separate_metadata if true, the new dataspace
+ * will not contain any meta data
+ */
+ Alloc_ds_result _allocate_dataspace(size_t size, bool enforce_separate_metadata);
+
+ /**
+ * Try to allocate block at our local allocator
+ */
+ Alloc_result _try_local_alloc(size_t size);
+
+ /**
+ * Unsynchronized implementation of 'try_alloc'
+ */
+ Alloc_result _unsynchronized_alloc(size_t size);
+
+ public:
+
+ enum { UNLIMITED = ~0 };
+
+ Regional_heap(Ram_allocator *ram_allocator,
+ Region_map *region_map,
+ Topology::Numa_region ®ion,
+ size_t quota_limit = UNLIMITED,
+ void *static_addr = 0,
+ size_t static_size = 0);
+
+ Regional_heap(Ram_allocator &ram, Region_map &rm, Topology::Numa_region ®ion) : Regional_heap(&ram, &rm, region) { }
+
+ ~Regional_heap();
+
+ /**
+ * Reconfigure quota limit
+ *
+ * \return negative error code if new quota limit is higher than
+ * currently used quota.
+ */
+ int quota_limit(size_t new_quota_limit);
+
+ /**
+ * Re-assign RAM allocator and region map
+ */
+ void reassign_resources(Ram_allocator *ram, Region_map *rm) {
+ _ds_pool.reassign_resources(ram, rm); }
+
+ /**
+ * Call 'fn' with the start and size of each backing-store region
+ */
+ template
+ void for_each_region(FN const &fn) const
+ {
+ Mutex::Guard guard(_mutex);
+ for (Dataspace const *ds = _ds_pool.first(); ds; ds = ds->next())
+ fn(ds->local_addr, ds->size);
+ }
+
+
+ /*************************
+ ** Allocator interface **
+ *************************/
+
+ Alloc_result try_alloc(size_t) override;
+ void free(void *, size_t) override;
+ size_t consumed() const override { return _quota_used; }
+ size_t overhead(size_t size) const override { return _alloc->overhead(size); }
+ bool need_size_for_free() const override { return false; }
+};
+
+
+/**
+ * Heap that allocates each block at a separate dataspace
+ */
+class Genode::Sliced_regional_heap : public Allocator
+{
+ private:
+
+ /**
+ * Meta-data header placed in front of each allocated block
+ */
+ struct Block : List::Element
+ {
+ Ram_dataspace_capability const ds;
+ size_t const size;
+
+ Block(Ram_dataspace_capability ds, size_t size) : ds(ds), size(size)
+ { }
+ };
+
+ Ram_allocator &_ram_alloc; /* RAM allocator for backing store */
+ Region_map &_region_map; /* region map of the address space */
+ size_t _consumed = 0; /* number of allocated bytes */
+ List _blocks { }; /* list of allocated blocks */
+ Mutex _mutex { }; /* serialize allocations */
+
+ public:
+
+ /**
+ * Return size of header prepended to each allocated block in bytes
+ */
+ static constexpr size_t meta_data_size() { return sizeof(Block); }
+
+ /**
+ * Constructor
+ */
+ Sliced_regional_heap(Ram_allocator &ram_alloc, Region_map ®ion_map);
+
+ /**
+ * Destructor
+ */
+ ~Sliced_regional_heap();
+
+
+ /*************************
+ ** Allocator interface **
+ *************************/
+
+ Alloc_result try_alloc(size_t) override;
+ void free(void *, size_t) override;
+ size_t consumed() const override { return _consumed; }
+ size_t overhead(size_t size) const override;
+ bool need_size_for_free() const override { return false; }
+};
+
+#endif /* _INCLUDE__BASE__HEAP_H_ */
diff --git a/repos/base/include/base/thread.h b/repos/base/include/base/thread.h
index af3c86d929..f01673c565 100644
--- a/repos/base/include/base/thread.h
+++ b/repos/base/include/base/thread.h
@@ -48,6 +48,7 @@ class Genode::Thread
using Location = Affinity::Location;
using Name = Cpu_session::Name;
using Weight = Cpu_session::Weight;
+ typedef unsigned Numa_id;
struct Stack_info { addr_t base; addr_t top;
addr_t libc_tls_pointer_offset; };
@@ -432,6 +433,8 @@ class Genode::Thread
* Thread affinity
*/
Affinity::Location affinity() const { return _affinity; }
+
+ void pin(Affinity::Location &loc);
};
#endif /* _INCLUDE__BASE__THREAD_H_ */
diff --git a/repos/base/include/base/trace/perf.h b/repos/base/include/base/trace/perf.h
new file mode 100644
index 0000000000..e2eb6ee81b
--- /dev/null
+++ b/repos/base/include/base/trace/perf.h
@@ -0,0 +1,93 @@
+/*
+ * \brief Performance Counter infrastructure
+ * \author Michael Müller
+ * \date 2022-12-15
+ */
+
+#pragma once
+
+#include
+
+namespace Genode { namespace Trace {
+
+ class Pfc_no_avail {
+ };
+
+ class Performance_counter
+ {
+
+ private:
+ static unsigned long private_freemask;
+ static unsigned long shared_freemask;
+
+ static unsigned _alloc(unsigned long *free_mask)
+ {
+ unsigned long current_mask, new_mask;
+ unsigned bit;
+
+ do
+ {
+ current_mask = *free_mask;
+ bit = __builtin_ffsl(current_mask);
+ new_mask = current_mask & ~(1 << (bit - 1));
+ } while (!__atomic_compare_exchange(free_mask, ¤t_mask, &new_mask, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED));
+
+ if (!bit) // Allocation failed
+ throw Pfc_no_avail();
+
+ return bit - 1; // number of the allocated counter
+ }
+
+ static void _init_masks();
+
+ public:
+ typedef unsigned int Counter;
+
+ enum Type
+ {
+ CORE = 0,
+ CACHE = 1
+ };
+
+ static unsigned acquire(Type type) {
+ return (type == Type::CORE) ? alloc_core() : alloc_cbo();
+ }
+
+ static unsigned alloc_cbo() {
+ if (shared_freemask == 0xffff0000)
+ _init_masks();
+ return _alloc(&shared_freemask);
+ }
+
+ static unsigned alloc_core() {
+ if (private_freemask == 0xffff)
+ _init_masks();
+ return _alloc(&private_freemask);
+ }
+
+ static void release(unsigned counter) {
+ bool core = static_cast(counter >> 4);
+ if (core)
+ private_freemask |= (1 << counter);
+ else
+ shared_freemask |= (1 << counter);
+ }
+
+ static void setup(unsigned counter, Genode::uint64_t event, Genode::uint64_t mask, Genode::uint64_t flags);
+ static void start(unsigned counter);
+ static void stop(unsigned counter);
+ static void reset(unsigned counter, unsigned val=0);
+ static uint64_t read(unsigned counter);
+ };
+
+ class Pfc_access_error {
+ private:
+ Genode::uint8_t _rc;
+
+ public:
+ Pfc_access_error(uint8_t rc) : _rc(rc) {}
+ Genode::uint8_t error_code() { return _rc; }
+ };
+
+ }
+}
\ No newline at end of file
diff --git a/repos/base/include/cpu_session/client.h b/repos/base/include/cpu_session/client.h
index 48ed7ad007..5fa2e8940d 100644
--- a/repos/base/include/cpu_session/client.h
+++ b/repos/base/include/cpu_session/client.h
@@ -33,12 +33,19 @@ struct Genode::Cpu_session_client : Rpc_client
void kill_thread(Thread_capability thread) override {
call(thread); }
+ void migrate_thread(Thread_capability thread, Affinity::Location loc) override {
+ call(thread, loc); }
+
void exception_sigh(Signal_context_capability sigh) override {
call(sigh); }
Affinity::Space affinity_space() const override {
return call(); }
+ void move(const Affinity::Location loc) override {
+ call(loc);
+ }
+
Dataspace_capability trace_control() override {
return call(); }
diff --git a/repos/base/include/cpu_session/connection.h b/repos/base/include/cpu_session/connection.h
index aedbb5d385..bf56413284 100644
--- a/repos/base/include/cpu_session/connection.h
+++ b/repos/base/include/cpu_session/connection.h
@@ -22,6 +22,8 @@ namespace Genode { struct Cpu_connection; }
struct Genode::Cpu_connection : Connection, Cpu_session_client
{
+ enum { RAM_QUOTA = 72*1024 };
+
/**
* Constructor
*
diff --git a/repos/base/include/cpu_session/cpu_session.h b/repos/base/include/cpu_session/cpu_session.h
index f47e6c1993..d313c9d8d0 100644
--- a/repos/base/include/cpu_session/cpu_session.h
+++ b/repos/base/include/cpu_session/cpu_session.h
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
namespace Genode {
@@ -105,6 +106,14 @@ struct Genode::Cpu_session : Session
*/
virtual void kill_thread(Thread_capability thread) = 0;
+ /**
+ * Migrate a thread to a new location
+ *
+ * \param thread capability of the thread to migrate
+ * \param loc component-local location to migrate the thread to
+ */
+ virtual void migrate_thread(Thread_capability thread, Genode::Affinity::Location loc) = 0;
+
/**
* Register default signal handler for exceptions
*
@@ -125,6 +134,12 @@ struct Genode::Cpu_session : Session
*/
virtual Affinity::Space affinity_space() const = 0;
+ /**
+ * @brief Update affinity location of this CPU session
+ *
+ */
+ virtual void move(const Genode::Affinity::Location ) = 0;
+
/**
* Translate generic priority value to kernel-specific priority levels
*
@@ -231,8 +246,10 @@ struct Genode::Cpu_session : Session
Capability, Name const &, Affinity::Location,
Weight, addr_t);
GENODE_RPC(Rpc_kill_thread, void, kill_thread, Thread_capability);
+ GENODE_RPC(Rpc_migrate_thread, void, migrate_thread, Thread_capability, Affinity::Location);
GENODE_RPC(Rpc_exception_sigh, void, exception_sigh, Signal_context_capability);
GENODE_RPC(Rpc_affinity_space, Affinity::Space, affinity_space);
+ GENODE_RPC(Rpc_move, void, move, Affinity::Location);
GENODE_RPC(Rpc_trace_control, Dataspace_capability, trace_control);
GENODE_RPC(Rpc_ref_account, int, ref_account, Cpu_session_capability);
GENODE_RPC(Rpc_transfer_quota, int, transfer_quota, Cpu_session_capability, size_t);
@@ -241,7 +258,7 @@ struct Genode::Cpu_session : Session
GENODE_RPC_INTERFACE(Rpc_create_thread, Rpc_kill_thread, Rpc_exception_sigh,
Rpc_affinity_space, Rpc_trace_control, Rpc_ref_account,
- Rpc_transfer_quota, Rpc_quota, Rpc_native_cpu);
+ Rpc_transfer_quota, Rpc_quota, Rpc_native_cpu, Rpc_migrate_thread, Rpc_move);
};
diff --git a/repos/base/include/parent/client.h b/repos/base/include/parent/client.h
index e160c4b938..f318636ec3 100644
--- a/repos/base/include/parent/client.h
+++ b/repos/base/include/parent/client.h
@@ -67,6 +67,8 @@ struct Genode::Parent_client : Rpc_client
call(sigh); }
Resource_args yield_request() override { return call(); }
+
+ Resource_args gained_resources() override { return call(); }
void yield_response() override { call(); }
diff --git a/repos/base/include/parent/parent.h b/repos/base/include/parent/parent.h
index 99f783c54c..20b3d70eb7 100644
--- a/repos/base/include/parent/parent.h
+++ b/repos/base/include/parent/parent.h
@@ -71,7 +71,8 @@ class Genode::Parent
static Client::Id log() { return { 3 }; }
static Client::Id binary() { return { 4 }; }
static Client::Id linker() { return { 5 }; }
- static Client::Id last() { return { 5 }; }
+ static Client::Id topo() { return { 6 }; }
+ static Client::Id last() { return { 6 }; }
/**
* True if session ID refers to an environment session
@@ -283,6 +284,12 @@ class Genode::Parent
*/
virtual void yield_response() = 0;
+ /**
+ * Obtain information about the resources gained, e.g. from a resource request
+ *
+ */
+ virtual Resource_args gained_resources() = 0;
+
/*
* Health monitoring
*/
@@ -328,6 +335,7 @@ class Genode::Parent
Resource_args const &);
GENODE_RPC(Rpc_yield_sigh, void, yield_sigh, Signal_context_capability);
GENODE_RPC(Rpc_yield_request, Resource_args, yield_request);
+ GENODE_RPC(Rpc_gained_resources, Resource_args, gained_resources);
GENODE_RPC(Rpc_yield_response, void, yield_response);
GENODE_RPC(Rpc_heartbeat_sigh, void, heartbeat_sigh, Signal_context_capability);
GENODE_RPC(Rpc_heartbeat_response, void, heartbeat_response);
@@ -337,7 +345,7 @@ class Genode::Parent
Rpc_close, Rpc_session_response, Rpc_main_thread,
Rpc_deliver_session_cap, Rpc_resource_avail_sigh,
Rpc_resource_request, Rpc_yield_sigh,
- Rpc_yield_request, Rpc_yield_response,
+ Rpc_yield_request, Rpc_yield_response, Rpc_gained_resources,
Rpc_heartbeat_sigh, Rpc_heartbeat_response);
};
diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h
index 5c8007d10a..507be653ea 100644
--- a/repos/base/include/pd_session/client.h
+++ b/repos/base/include/pd_session/client.h
@@ -80,6 +80,11 @@ struct Genode::Pd_session_client : Rpc_client
{
return call(size, cache);
}
+
+ Alloc_result try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cache = CACHED) override
+ {
+ return call(size, numa_id, cache);
+ }
void free(Ram_dataspace_capability ds) override { call(ds); }
@@ -106,6 +111,16 @@ struct Genode::Pd_session_client : Rpc_client
Attach_dma_result attach_dma(Dataspace_capability ds, addr_t at) override {
return call(ds, at); }
+
+ void create_cell(long prioritiy, const Affinity::Location &loc) override
+ {
+ call(prioritiy, loc);
+ }
+
+ void update_cell(const Affinity::Location &loc) override
+ {
+ call(loc);
+ }
};
#endif /* _INCLUDE__PD_SESSION__CLIENT_H_ */
diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h
index c487129690..4b61ff78e1 100644
--- a/repos/base/include/pd_session/pd_session.h
+++ b/repos/base/include/pd_session/pd_session.h
@@ -21,7 +21,7 @@
#include
#include
#include
-
+#include
namespace Genode {
struct Pd_session;
struct Pd_session_client;
@@ -29,7 +29,6 @@ namespace Genode {
struct Signal_context;
}
-
struct Genode::Pd_session : Session, Ram_allocator
{
/**
@@ -273,6 +272,11 @@ struct Genode::Pd_session : Session, Ram_allocator
*/
Ram_quota avail_ram() const { return { ram_quota().value - used_ram().value }; }
+ /**
+ * \brief Create new dataspace factory for given NUMA node
+ * \param
+ */
+
/*****************************************
** Access to kernel-specific interface **
@@ -345,6 +349,12 @@ struct Genode::Pd_session : Session, Ram_allocator
*/
virtual Attach_dma_result attach_dma(Dataspace_capability, addr_t at) = 0;
+ /*
+ * Create a new cell at the kernel for this protection domain
+ */
+ virtual void create_cell(long prioritiy, const Affinity::Location &loc) = 0;
+
+ virtual void update_cell(const Affinity::Location &loc) = 0;
/*********************
** RPC declaration **
@@ -370,6 +380,7 @@ struct Genode::Pd_session : Session, Ram_allocator
GENODE_RPC(Rpc_cap_quota, Cap_quota, cap_quota);
GENODE_RPC(Rpc_used_caps, Cap_quota, used_caps);
GENODE_RPC(Rpc_try_alloc, Alloc_result, try_alloc, size_t, Cache);
+ GENODE_RPC(Rpc_try_alloc_numa, Alloc_result, try_alloc, size_t, Ram_allocator::Numa_id, Cache);
GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability);
GENODE_RPC(Rpc_transfer_ram_quota, Transfer_ram_quota_result, transfer_quota,
Capability, Ram_quota);
@@ -382,16 +393,21 @@ struct Genode::Pd_session : Session, Ram_allocator
GENODE_RPC(Rpc_attach_dma, Attach_dma_result, attach_dma,
Dataspace_capability, addr_t);
+ GENODE_RPC(Rpc_create_cell, void, create_cell, long, Affinity::Location const &);
+
+ GENODE_RPC(Rpc_update_cell, void, update_cell, Affinity::Location const &);
+
GENODE_RPC_INTERFACE(Rpc_assign_parent, Rpc_assign_pci, Rpc_map,
Rpc_signal_source, Rpc_free_signal_source,
Rpc_alloc_context, Rpc_free_context, Rpc_submit,
Rpc_alloc_rpc_cap, Rpc_free_rpc_cap, Rpc_address_space,
Rpc_stack_area, Rpc_linker_area, Rpc_ref_account,
Rpc_transfer_cap_quota, Rpc_cap_quota, Rpc_used_caps,
- Rpc_try_alloc, Rpc_free,
+ Rpc_try_alloc, Rpc_try_alloc_numa, Rpc_free,
Rpc_transfer_ram_quota, Rpc_ram_quota, Rpc_used_ram,
Rpc_native_pd, Rpc_system_control_cap,
- Rpc_dma_addr, Rpc_attach_dma);
+ Rpc_dma_addr, Rpc_attach_dma,
+ Rpc_create_cell, Rpc_update_cell);
};
#endif /* _INCLUDE__PD_SESSION__PD_SESSION_H_ */
diff --git a/repos/base/include/topo_session/capability.h b/repos/base/include/topo_session/capability.h
new file mode 100644
index 0000000000..17f7a1a01b
--- /dev/null
+++ b/repos/base/include/topo_session/capability.h
@@ -0,0 +1,22 @@
+/*
+ * \brief Topo-session capability type
+ * \author Michael Müller
+ * \date 2022-10-06
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalanOS, witch is based on Genode OS framework
+ * distributed under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Genode
+{
+ typedef Capability Topo_session_capability;
+} // namespace Genode
\ No newline at end of file
diff --git a/repos/base/include/topo_session/client.h b/repos/base/include/topo_session/client.h
new file mode 100644
index 0000000000..a7ec0a0bb9
--- /dev/null
+++ b/repos/base/include/topo_session/client.h
@@ -0,0 +1,59 @@
+/*
+ * \brief Client-side topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace Genode {
+ struct Topo_session_client;
+ struct Node;
+}
+
+struct Genode::Topo_session_client : Rpc_client
+{
+ explicit Topo_session_client(Topo_session_capability session)
+ : Rpc_client(session) { }
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override {
+ return call(loc);
+ }
+
+ Topology::Numa_region node_at_id(unsigned node_id) override {
+ return call(node_id);
+ }
+
+ unsigned node_count() override {
+ return call();
+ }
+
+ void reconstruct(const Affinity affinity) override
+ {
+ call(affinity);
+ }
+
+ unsigned phys_id(const Affinity::Location &loc) override
+ {
+ return call(loc);
+ }
+
+ Affinity::Space const global_affinity_space() override
+ {
+ return call();
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/connection.h b/repos/base/include/topo_session/connection.h
new file mode 100644
index 0000000000..f2ff65b994
--- /dev/null
+++ b/repos/base/include/topo_session/connection.h
@@ -0,0 +1,50 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace Genode {
+ struct Topo_connection;
+}
+
+struct Genode::Topo_connection : Connection, Topo_session_client
+{
+ enum
+ {
+ RAM_QUOTA = 2097152UL
+ };
+
+ Topo_connection(Env &env, const char *label = "", Affinity const &affinity = Affinity())
+ :
+ Connection(env,
+ session(env.parent(), affinity, "ram_quota=%u, cap_quota=%u, label=\"%s\"", RAM_QUOTA, CAP_QUOTA, label)),
+ Topo_session_client(cap()) {}
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override {
+ return Topo_session_client::node_affinity_of(loc);
+ }
+
+ Topology::Numa_region node_at_id(unsigned node_id) override {
+ return Topo_session_client::node_at_id(node_id);
+ }
+
+ unsigned node_count() override {
+ return Topo_session_client::node_count();
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/node.h b/repos/base/include/topo_session/node.h
new file mode 100644
index 0000000000..ffc7d631e2
--- /dev/null
+++ b/repos/base/include/topo_session/node.h
@@ -0,0 +1,58 @@
+/*
+ * \brief Representation of a NUMA node
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+
+namespace Topology {
+ struct Numa_region;
+}
+
+struct Topology::Numa_region : Genode::List::Element
+{
+ /* ID presented to component */
+ unsigned _id;
+
+ unsigned _core_count;
+ Genode::List neighbours;
+
+ /* Physical NUMA node ID */
+ unsigned _native_id;
+
+ Numa_region() : _id(0), _core_count(0), neighbours(), _native_id(0) { }
+ Numa_region(unsigned id, unsigned native_id) : _id(id), _core_count(0), neighbours(), _native_id(native_id) {}
+ Numa_region(Numa_region ©) : _id(copy.id()), _core_count(copy.core_count()), neighbours(), _native_id(copy.native_id()) {
+ }
+
+ unsigned native_id() { return _native_id; }
+ unsigned id() { return _id; }
+ unsigned core_count() { return _core_count; }
+ void core_count(unsigned count) { _core_count = count; }
+ void increment_core_count() { _core_count++; }
+ Numa_region &operator=(const Numa_region ©) {
+ if (this == ©)
+ return *this;
+
+ this->_id = copy._id;
+ this->_core_count = copy._core_count;
+ this->_native_id = copy._native_id;
+
+ /* At the moment, we do not copy the list of neighbours, as it is not used by any our applications. */
+ /* TODO: Copy list onf neighbours, as soons as any application is going to use that information. */
+
+ return *this;
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/topo_session.h b/repos/base/include/topo_session/topo_session.h
new file mode 100644
index 0000000000..1d3b0c8d0e
--- /dev/null
+++ b/repos/base/include/topo_session/topo_session.h
@@ -0,0 +1,64 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Genode {
+
+ struct Topo_session;
+ struct Topo_session_client;
+}
+
+namespace Topology
+{
+ struct Numa_region;
+} // namespace EalanOS
+
+struct Genode::Topo_session : Session
+{
+ /**
+ * \nooapi
+ *
+ */
+ static const char *service_name() { return "TOPO"; }
+
+ enum
+ {
+ CAP_QUOTA = 2
+ };
+
+ typedef Topo_session_client Client;
+
+ virtual ~Topo_session() { }
+
+ virtual Topology::Numa_region node_affinity_of(Affinity::Location const &) = 0;
+ virtual Topology::Numa_region node_at_id(unsigned node_id) = 0;
+ virtual unsigned node_count() = 0;
+ virtual void reconstruct(const Affinity) = 0;
+ virtual unsigned phys_id(Affinity::Location const &) = 0;
+ virtual Affinity::Space const global_affinity_space() = 0;
+
+ GENODE_RPC(Rpc_node_affinity, Topology::Numa_region, node_affinity_of, Affinity::Location const &);
+ GENODE_RPC(Rpc_node_id, Topology::Numa_region, node_at_id, unsigned);
+ GENODE_RPC(Rpc_node_count, unsigned, node_count);
+ GENODE_RPC(Rpc_reconstruct, void, reconstruct, Affinity);
+ GENODE_RPC(Rpc_phys_id, unsigned, phys_id, Affinity::Location const &);
+ GENODE_RPC(Rpc_total_core_count, Affinity::Space const, global_affinity_space);
+
+ GENODE_RPC_INTERFACE(Rpc_node_affinity, Rpc_node_id, Rpc_node_count, Rpc_reconstruct, Rpc_phys_id, Rpc_total_core_count);
+};
\ No newline at end of file
diff --git a/repos/base/lib/mk/base-common.inc b/repos/base/lib/mk/base-common.inc
index fc66779e1d..cef38996ba 100644
--- a/repos/base/lib/mk/base-common.inc
+++ b/repos/base/lib/mk/base-common.inc
@@ -8,6 +8,7 @@ SRC_CC += avl_tree.cc
SRC_CC += slab.cc
SRC_CC += allocator_avl.cc
SRC_CC += heap.cc sliced_heap.cc
+SRC_CC += regional_heap.cc
SRC_CC += registry.cc
SRC_CC += output.cc
SRC_CC += child.cc
diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld
index 5c705f5af1..774550697a 100644
--- a/repos/base/lib/symbols/ld
+++ b/repos/base/lib/symbols/ld
@@ -38,6 +38,13 @@
# under the terms of the GNU Affero General Public License version 3.
#
+__atomic_store T
+__atomic_load T
+_Unwind_GetLanguageSpecificData T
+_Unwind_GetRegionStart T
+_Unwind_GetIP T
+_Unwind_SetGR T
+_Unwind_SetIP T
_Z11genode_exiti T
_Z16main_thread_utcbv T
_Z22__ldso_raise_exceptionv T
@@ -45,6 +52,9 @@ _ZN5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handler
_ZN5Timer10Connection9curr_timeEv T
_ZN5Timer10ConnectionC1ERN6Genode3EnvERNS1_10EntrypointERKNS1_13Session_labelE T
_ZN5Timer10ConnectionC2ERN6Genode3EnvERNS1_10EntrypointERKNS1_13Session_labelE T
+_ZN6Genode5Trace19Performance_counter15shared_freemaskE D 8
+_ZN6Genode5Trace19Performance_counter16private_freemaskE D 8
+_ZN6Genode5Trace19Performance_counter11_init_masksEv T
_ZN6Genode10Entrypoint16_dispatch_signalERNS_6SignalE T
_ZN6Genode10Entrypoint22Signal_proxy_component6signalEv T
_ZN6Genode10Entrypoint25_process_incoming_signalsEv T
@@ -142,6 +152,26 @@ _ZN6Genode17Region_map_client6detachEm T
_ZN6Genode17Region_map_client9dataspaceEv T
_ZN6Genode17Region_map_clientC1ENS_10CapabilityINS_10Region_mapEEE T
_ZN6Genode17Region_map_clientC2ENS_10CapabilityINS_10Region_mapEEE T
+_ZN6Genode13Regional_heap11quota_limitEm T
+_ZN6Genode13Regional_heap14Dataspace_pool15remove_and_freeERNS0_9DataspaceE T
+_ZN6Genode13Regional_heap14Dataspace_poolD1Ev T
+_ZN6Genode13Regional_heap14Dataspace_poolD2Ev T
+_ZN6Genode13Regional_heap16_try_local_allocEm T
+_ZN6Genode13Regional_heap19_allocate_dataspaceEmb T
+_ZN6Genode13Regional_heap21_unsynchronized_allocEm T
+_ZN6Genode13Regional_heap4freeEPvm T
+_ZN6Genode13Regional_heap9try_allocEm T
+_ZN6Genode13Regional_heapC1EPNS_13Ram_allocatorEPNS_10Region_mapERN8Topology11Numa_regionEmPvm T
+_ZN6Genode13Regional_heapC2EPNS_13Ram_allocatorEPNS_10Region_mapERN8Topology11Numa_regionEmPvm T
+_ZN6Genode13Regional_heapD0Ev T
+_ZN6Genode13Regional_heapD1Ev T
+_ZN6Genode13Regional_heapD2Ev T
+_ZNK6Genode13Regional_heap18need_size_for_freeEv T
+_ZNK6Genode13Regional_heap8consumedEv T
+_ZNK6Genode13Regional_heap8overheadEm T
+_ZTIN6Genode13Regional_heapE T
+_ZTSN6Genode13Regional_heapE T
+_ZTVN6Genode13Regional_heapE T
_ZN6Genode17Rm_session_client6createEm T
_ZN6Genode17Rm_session_client7destroyENS_10CapabilityINS_10Region_mapEEE T
_ZN6Genode17Rm_session_clientC1ENS_10CapabilityINS_10Rm_sessionEEE T
@@ -174,6 +204,8 @@ _ZN6Genode18Signal_transmitterC1ENS_10CapabilityINS_14Signal_contextEEE T
_ZN6Genode18Signal_transmitterC2ENS_10CapabilityINS_14Signal_contextEEE T
_ZN6Genode20env_session_id_spaceEv T
_ZN6Genode21cache_invalidate_dataEmm T
+_ZN6Genode22Topo_session_component11reconstructENS_8AffinityE W
+_ZThn136_N6Genode22Topo_session_component11reconstructENS_8AffinityE W
_ZN6Genode25env_stack_area_region_mapE B 8
_ZN6Genode27cache_clean_invalidate_dataEmm T
_ZN6Genode28env_stack_area_ram_allocatorE B 8
@@ -223,6 +255,7 @@ _ZN6Genode5Child23initiate_env_pd_sessionEv T
_ZN6Genode5Child4exitEi T
_ZN6Genode5Child5closeENS_8Id_spaceINS_6Parent6ClientEE2IdE T
_ZN6Genode5Child5yieldERKNS_6StringILm160EEE T
+_ZN6Genode5Child6acceptERKNS_6StringILm160EEE T
_ZN6Genode5Child7sessionENS_8Id_spaceINS_6Parent6ClientEE2IdERKNS_13Rpc_in_bufferILm64EEERKNS6_ILm160EEERKNS_8AffinityE T
_ZN6Genode5Child7upgradeENS_8Id_spaceINS_6Parent6ClientEE2IdERKNS_13Rpc_in_bufferILm160EEE T
_ZN6Genode5Child8announceERKNS_13Rpc_in_bufferILm64EEE T
@@ -239,6 +272,11 @@ _ZN6Genode5Trace6Logger17_evaluate_controlEv T
_ZN6Genode5Trace6Logger3logEPKcm T
_ZN6Genode5Trace6LoggerC1Ev T
_ZN6Genode5Trace6LoggerC2Ev T
+_ZN6Genode5Trace19Performance_counter4readEj T
+_ZN6Genode5Trace19Performance_counter4stopEj T
+_ZN6Genode5Trace19Performance_counter5resetEjj T
+_ZN6Genode5Trace19Performance_counter5setupEjyyy T
+_ZN6Genode5Trace19Performance_counter5startEj T
_ZN6Genode5Trace18Partitioned_buffer4initEm T
_ZN6Genode5Trace18Partitioned_buffer6commitEm T
_ZN6Genode5Trace18Partitioned_buffer7reserveEm T
@@ -271,6 +309,7 @@ _ZN6Genode6Thread23stack_area_virtual_baseEv T
_ZN6Genode6Thread23stack_area_virtual_sizeEv T
_ZN6Genode6Thread4joinEv T
_ZN6Genode6Thread4nameEPcm T
+_ZN6Genode6Thread3pinERNS_8Affinity8LocationE T
_ZN6Genode6Thread4utcbEv T
_ZN6Genode6Thread5startEv T
_ZN6Genode6Thread6myselfEv T
@@ -374,7 +413,7 @@ _ZTVN6Genode18Allocator_avl_baseE D 128
_ZTVN6Genode4HeapE D 72
_ZTVN6Genode4SlabE D 72
_ZTVN6Genode5Child14Initial_threadE D 48
-_ZTVN6Genode5ChildE D 440
+_ZTVN6Genode5ChildE D 456
_ZTVN6Genode6OutputE D 48
_ZTVN6Genode6ThreadE D 48
_ZTVN6Genode7ConsoleE D 48
@@ -599,8 +638,12 @@ _ZTVSt8bad_cast D 40
_ZTVSt9bad_alloc D 40
_ZTVSt9exception D 40
_ZTVSt9type_info D 64
+_ZdaPvSt11align_val_t W
_ZdlPv W
_ZdlPvm W
+_ZdlPvSt11align_val_t W
+_ZdlPvmSt11align_val_t W
+_ZnwmSt11align_val_t W
__aeabi_atexit W
__aeabi_unwind_cpp_pr0 T
__aeabi_unwind_cpp_pr1 T
diff --git a/repos/base/mk/global.mk b/repos/base/mk/global.mk
index 6d0dc55043..32d86197c4 100644
--- a/repos/base/mk/global.mk
+++ b/repos/base/mk/global.mk
@@ -257,7 +257,7 @@ ALL_INC_DIR += $(LIBGCC_INC_DIR)
ALL_INC_DIR += $(HOST_INC_DIR)
VERBOSE ?= @
-VERBOSE_DIR ?= --no-print-directory
+VERBOSE_DIR ?= --print-directory
MSG_LINK ?= @$(ECHO) " LINK "
MSG_COMP ?= @$(ECHO) " COMPILE "
diff --git a/repos/base/src/core/core_log.cc b/repos/base/src/core/core_log.cc
index 88a043804c..7dfaf6124a 100644
--- a/repos/base/src/core/core_log.cc
+++ b/repos/base/src/core/core_log.cc
@@ -51,8 +51,10 @@ void Core::init_core_log(Core_log_range const &r) { range = r; }
void Core::Core_log::output(char const * str)
{
+ acquire();
for (unsigned i = 0; i < Genode::strlen(str); i++) {
out(str[i]);
out_mem(str[i]);
}
+ release();
}
diff --git a/repos/base/src/core/cpu_session_component.cc b/repos/base/src/core/cpu_session_component.cc
index e00093ea92..81e8db242a 100644
--- a/repos/base/src/core/cpu_session_component.cc
+++ b/repos/base/src/core/cpu_session_component.cc
@@ -15,6 +15,7 @@
/* Genode includes */
#include
+#include
/* core includes */
#include
@@ -22,6 +23,7 @@
#include
#include
+
using namespace Core;
@@ -149,6 +151,10 @@ void Cpu_session_component::kill_thread(Thread_capability thread_cap)
}
}
+void Cpu_session_component::migrate_thread(Thread_capability thread_cap, Affinity::Location loc)
+{
+ _thread_ep.apply(thread_cap, [&] (Cpu_thread_component *t) { t->affinity(_thread_affinity(loc)); });
+}
void Cpu_session_component::exception_sigh(Signal_context_capability sigh)
{
@@ -170,6 +176,10 @@ Affinity::Space Cpu_session_component::affinity_space() const
return Affinity::Space(_location.width(), _location.height());
}
+void Cpu_session_component::move(const Affinity::Location destination)
+{
+ _location = destination;
+}
Dataspace_capability Cpu_session_component::trace_control()
{
diff --git a/repos/base/src/core/include/account.h b/repos/base/src/core/include/account.h
index 81412178b8..92ce3438fb 100644
--- a/repos/base/src/core/include/account.h
+++ b/repos/base/src/core/include/account.h
@@ -149,11 +149,16 @@ class Core::Account
/* make sure to stay within the initial limit */
if (amount.value > _transferrable_quota().value)
+ {
+ Genode::log("Limit exceeded : ", _label);
throw Limit_exceeded();
+ }
- /* downgrade from this account */
- if (!_quota_guard.try_downgrade(amount))
- throw Limit_exceeded();
+ /* downgrade from this account */
+ if (!_quota_guard.try_downgrade(amount)) {
+ Genode::log("Limit exceeded: ", _label);
+ throw Limit_exceeded();
+ }
}
/* credit to 'other' */
diff --git a/repos/base/src/core/include/core_env.h b/repos/base/src/core/include/core_env.h
index fef3b37bf8..3338c4fbf7 100644
--- a/repos/base/src/core/include/core_env.h
+++ b/repos/base/src/core/include/core_env.h
@@ -17,6 +17,7 @@
/* Genode includes */
#include
+#include
/* base-internal includes */
#include
@@ -92,6 +93,8 @@ class Core::Core_env : public Noncopyable
Pd_session *pd_session() { return &_pd_session; }
Cpu_session *cpu_session() { ASSERT_NEVER_CALLED; }
Cpu_session_capability cpu_session_cap() { ASSERT_NEVER_CALLED; }
+ Topo_session *topo_session() override { ASSERT_NEVER_CALLED; }
+ Topo_session_capability topo_session_cap() override { ASSERT_NEVER_CALLED; }
Pd_session_capability pd_session_cap() { return _pd_session.cap(); }
};
diff --git a/repos/base/src/core/include/core_log.h b/repos/base/src/core/include/core_log.h
index 88d1b92e7b..70f4de2265 100644
--- a/repos/base/src/core/include/core_log.h
+++ b/repos/base/src/core/include/core_log.h
@@ -33,6 +33,10 @@ namespace Core {
struct Core::Core_log
{
+ void acquire();
+
+ void release();
+
void out(char const c);
void output(char const * str);
diff --git a/repos/base/src/core/include/cpu_session_component.h b/repos/base/src/core/include/cpu_session_component.h
index 78559171e2..da276213bc 100644
--- a/repos/base/src/core/include/cpu_session_component.h
+++ b/repos/base/src/core/include/cpu_session_component.h
@@ -169,8 +169,10 @@ class Core::Cpu_session_component : public Session_object,
Create_thread_result create_thread(Capability, Name const &,
Affinity::Location, Weight, addr_t) override;
void kill_thread(Thread_capability) override;
+ void migrate_thread(Thread_capability, Affinity::Location) override;
void exception_sigh(Signal_context_capability) override;
Affinity::Space affinity_space() const override;
+ void move(const Affinity::Location) override;
Dataspace_capability trace_control() override;
int ref_account(Cpu_session_capability c) override;
int transfer_quota(Cpu_session_capability, size_t) override;
diff --git a/repos/base/src/core/include/cpu_thread_component.h b/repos/base/src/core/include/cpu_thread_component.h
index 626f222464..4f3da327d9 100644
--- a/repos/base/src/core/include/cpu_thread_component.h
+++ b/repos/base/src/core/include/cpu_thread_component.h
@@ -174,6 +174,7 @@ class Core::Cpu_thread_component : public Rpc_object,
_address_space_region_map.add_client(_rm_client);
_platform_thread.pager(_rm_client);
+ _platform_thread.affinity(location);
_trace_sources.insert(&_trace_source);
}
diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h
index a897de79e0..2ea3127751 100644
--- a/repos/base/src/core/include/pd_session_component.h
+++ b/repos/base/src/core/include/pd_session_component.h
@@ -340,6 +340,8 @@ class Core::Pd_session_component : public Session_object
Alloc_result try_alloc(size_t, Cache) override;
+ Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override;
+
void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability) const override;
@@ -372,6 +374,13 @@ class Core::Pd_session_component : public Session_object
addr_t dma_addr(Ram_dataspace_capability) override;
Attach_dma_result attach_dma(Dataspace_capability, addr_t) override;
+
+ /******************************************
+ ** Support for EalánOS cells **
+ ******************************************/
+ void create_cell(long prioritiy, const Affinity::Location &loc) override;
+
+ void update_cell(const Affinity::Location &loc) override;
};
#endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base/src/core/include/ram_dataspace_factory.h b/repos/base/src/core/include/ram_dataspace_factory.h
index c00a2858fb..69fba6607a 100644
--- a/repos/base/src/core/include/ram_dataspace_factory.h
+++ b/repos/base/src/core/include/ram_dataspace_factory.h
@@ -45,7 +45,7 @@ class Core::Ram_dataspace_factory : public Ram_allocator,
Rpc_entrypoint &_ep;
Range_allocator &_phys_alloc;
- Phys_range const _phys_range;
+ Phys_range _phys_range;
/*
@@ -82,6 +82,11 @@ class Core::Ram_dataspace_factory : public Ram_allocator,
*/
void _clear_ds(Dataspace_component &ds);
+ /**
+ * Remove core-local mappings of dataspace
+ */
+ void _unmap_ds_from_core(Dataspace_component &ds);
+
public:
Ram_dataspace_factory(Rpc_entrypoint &ep,
@@ -109,6 +114,7 @@ class Core::Ram_dataspace_factory : public Ram_allocator,
*****************************/
Alloc_result try_alloc(size_t, Cache) override;
+ Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override;
void free(Ram_dataspace_capability) override;
size_t dataspace_size(Ram_dataspace_capability ds) const override;
};
diff --git a/repos/base/src/core/include/synced_ram_allocator.h b/repos/base/src/core/include/synced_ram_allocator.h
index 6b94e1dde6..5ac67fa768 100644
--- a/repos/base/src/core/include/synced_ram_allocator.h
+++ b/repos/base/src/core/include/synced_ram_allocator.h
@@ -41,6 +41,12 @@ class Core::Synced_ram_allocator : public Ram_allocator
Mutex::Guard mutex_guard(_mutex);
return _alloc.try_alloc(size, cache);
}
+
+ Alloc_result try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cache) override
+ {
+ Mutex::Guard mutex_guard(_mutex);
+ return _alloc.try_alloc(size, numa_id, cache);
+ }
void free(Ram_dataspace_capability ds) override
{
diff --git a/repos/base/src/core/include/topo_root.h b/repos/base/src/core/include/topo_root.h
new file mode 100644
index 0000000000..52e369d8eb
--- /dev/null
+++ b/repos/base/src/core/include/topo_root.h
@@ -0,0 +1,71 @@
+/*
+ * \brief Topology service root component
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+
+#include
+
+#include
+
+namespace Genode {
+
+ class Topo_root : public Root_component
+ {
+ private:
+ Ram_allocator &_ram_alloc;
+ Region_map &_local_rm;
+
+ protected:
+
+ Topo_session_component *_create_session(char const *args, Affinity const &affinity) override {
+ size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
+
+ if (ram_quota < Trace::Control_area::SIZE)
+ throw Insufficient_ram_quota();
+
+ if (!affinity.valid()) {
+ log("Location ", affinity.location(), " not within space ", affinity.space());
+ throw Service_denied();
+ }
+
+ return new (md_alloc())
+ Topo_session_component(*this->ep(),
+ session_resources_from_args(args),
+ session_label_from_args(args),
+ session_diag_from_args(args),
+ _ram_alloc, _local_rm,
+ const_cast(affinity));
+ }
+
+ void _upgrade_session(Topo_session_component *topo, const char *args) override
+ {
+ topo->upgrade(ram_quota_from_args(args));
+ topo->upgrade(cap_quota_from_args(args));
+ }
+
+ public:
+
+ Topo_root(Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Rpc_entrypoint &session_ep,
+ Allocator &md_alloc)
+ :
+ Root_component(&session_ep, &md_alloc),
+ _ram_alloc(ram_alloc), _local_rm(local_rm)
+ { }
+ };
+}
\ No newline at end of file
diff --git a/repos/base/src/core/include/topo_session_component.h b/repos/base/src/core/include/topo_session_component.h
new file mode 100644
index 0000000000..2632bbdedc
--- /dev/null
+++ b/repos/base/src/core/include/topo_session_component.h
@@ -0,0 +1,86 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode {
+ class Topo_session_component;
+}
+
+class Genode::Topo_session_component : public Session_object
+{
+ private:
+ Genode::Affinity _affinity;
+ Sliced_heap _md_alloc;
+
+ Topology::Numa_region _node_affinities[Genode::Platform::MAX_SUPPORTED_CPUS][Genode::Platform::MAX_SUPPORTED_CPUS];
+ unsigned _node_count;
+ Topology::Numa_region _nodes[64];
+
+ public:
+ Topo_session_component(Rpc_entrypoint &session_ep,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Affinity affinity
+ );
+
+ void construct();
+
+ /**
+ * @brief Topology session interface
+ */
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override
+ {
+ return _node_affinities[loc.xpos()][loc.ypos()];
+ }
+
+ Topology::Numa_region node_at_id(unsigned numa_id) override
+ {
+ return _nodes[numa_id];
+ }
+
+ unsigned node_count() override
+ {
+ return _node_count;
+ }
+
+ void reconstruct(Affinity affinity) override
+ {
+ _affinity = affinity;
+ construct();
+ }
+
+ unsigned phys_id(const Affinity::Location &loc) override
+ {
+ return platform_specific().kernel_cpu_id(loc);
+ }
+
+ Affinity::Space const global_affinity_space() override
+ {
+ return platform_specific().affinity_space();
+ }
+};
diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc
index 66064508dd..9b393c29f4 100644
--- a/repos/base/src/core/main.cc
+++ b/repos/base/src/core/main.cc
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
using namespace Core;
@@ -184,7 +185,7 @@ class Core_child : public Child_policy
Pd_session &ref_pd() override { return _core_pd; }
Pd_session_capability ref_pd_cap() const override { return _core_pd_cap; }
- size_t session_alloc_batch_size() const override { return 128; }
+ size_t session_alloc_batch_size() const override { return 2*128; }
Id_space &server_id_space() override { return _server_ids; }
};
@@ -278,6 +279,7 @@ void Genode::bootstrap_component(Genode::Platform &)
platform().irq_alloc(), sliced_heap);
static Trace_root trace_root (core_ram_alloc, local_rm, ep, sliced_heap,
Core::Trace::sources(), trace_policies);
+ static Topo_root topo_root(core_ram_alloc, local_rm, ep, sliced_heap);
static Core_service rom_service (services, rom_root);
static Core_service rm_service (services, rm_root);
@@ -287,6 +289,7 @@ void Genode::bootstrap_component(Genode::Platform &)
static Core_service io_mem_service (services, io_mem_root);
static Core_service irq_service (services, irq_root);
static Core_service trace_service (services, trace_root);
+ static Core_service topo_service(services, topo_root);
/* make platform-specific services known to service pool */
platform_add_local_services(ep, sliced_heap, services, Core::Trace::sources(), core_ram_alloc);
@@ -294,7 +297,7 @@ void Genode::bootstrap_component(Genode::Platform &)
size_t const avail_ram_quota = core_pd.avail_ram().value;
size_t const avail_cap_quota = core_pd.avail_caps().value;
- size_t const preserved_ram_quota = 224*1024;
+ size_t const preserved_ram_quota = 224*1024+(1<<20);
size_t const preserved_cap_quota = 1000;
if (avail_ram_quota < preserved_ram_quota) {
diff --git a/repos/base/src/core/pd_session_component.cc b/repos/base/src/core/pd_session_component.cc
index ad9a88649a..b0f8d4b6bb 100644
--- a/repos/base/src/core/pd_session_component.cc
+++ b/repos/base/src/core/pd_session_component.cc
@@ -71,6 +71,58 @@ Pd_session_component::try_alloc(size_t ds_size, Cache cache)
);
}
+Ram_allocator::Alloc_result
+Pd_session_component::try_alloc(size_t ds_size, Ram_allocator::Numa_id numa_id, Cache cache)
+{
+ /* zero-sized dataspaces are not allowed */
+ if (!ds_size)
+ return Alloc_error::DENIED;
+
+ /* dataspace allocation granularity is page size */
+ ds_size = align_addr(ds_size, 12);
+
+ using Result = Ram_allocator::Alloc_result;
+ using Reservation = Genode::Reservation;
+
+ /* track quota use */
+ return _ram_quota_guard().with_reservation(Ram_quota{ds_size},
+
+ [&] (Reservation &ram_reservation) -> Result {
+
+ /*
+ * In the worst case, we need to allocate a new slab block for
+ * the meta data of the dataspace to be created. Therefore, we
+ * temporarily withdraw the slab block size here to trigger an
+ * exception if the account does not have enough room for the meta
+ * data.
+ */
+ Ram_quota const overhead { Ram_dataspace_factory::SLAB_BLOCK_SIZE };
+
+ if (!_ram_quota_guard().have_avail(overhead)) {
+ ram_reservation.cancel();
+ return Ram_allocator::Alloc_error::OUT_OF_RAM;
+ }
+
+ /*
+ * Each dataspace is an RPC object and thereby consumes a
+ * capability.
+ */
+ return _cap_quota_guard().with_reservation(Cap_quota{1},
+
+ [&] (Genode::Reservation &) -> Result {
+ return _ram_ds_factory.try_alloc(ds_size, numa_id, cache);
+ },
+ [&] () -> Result {
+ ram_reservation.cancel();
+ return Ram_allocator::Alloc_error::OUT_OF_CAPS;
+ }
+ );
+ },
+ [&] () -> Result {
+ return Ram_allocator::Alloc_error::OUT_OF_RAM;
+ }
+ );
+}
void Pd_session_component::free(Ram_dataspace_capability ds_cap)
{
diff --git a/repos/base/src/core/ram_dataspace_factory.cc b/repos/base/src/core/ram_dataspace_factory.cc
index 8c37503834..889864b4c8 100644
--- a/repos/base/src/core/ram_dataspace_factory.cc
+++ b/repos/base/src/core/ram_dataspace_factory.cc
@@ -13,6 +13,8 @@
/* core includes */
#include
+#include
+#include
using namespace Core;
@@ -126,6 +128,7 @@ Ram_dataspace_factory::try_alloc(size_t ds_size, Cache cache)
Dataspace_component &ds = *ds_ptr;
/* create native shared memory representation of dataspace */
+#ifdef ZERO_AT_ALLOC
try { _export_ram_ds(ds); }
catch (Core_virtual_memory_exhausted) {
warning("could not export RAM dataspace of size ", ds.size());
@@ -140,8 +143,8 @@ Ram_dataspace_factory::try_alloc(size_t ds_size, Cache cache)
* function must also make sure to flush all cache lines related to the
* address range used by the dataspace.
*/
- _clear_ds(ds);
-
+ _unmap_ds_from_core(ds);
+#endif
Dataspace_capability ds_cap = _ep.manage(&ds);
phys_alloc_guard.keep = true;
@@ -149,6 +152,14 @@ Ram_dataspace_factory::try_alloc(size_t ds_size, Cache cache)
return static_cap_cast(ds_cap);
}
+Ram_allocator::Alloc_result Ram_dataspace_factory::try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cached=CACHED)
+{
+ Ram_dataspace_factory::Phys_range old = {_phys_range.start, _phys_range.end};
+ _phys_range = {platform_specific().mem_range(numa_id).start, platform_specific().mem_range(numa_id).end};
+ Ram_allocator::Alloc_result result = Ram_dataspace_factory::try_alloc(size, cached);
+ _phys_range = {old.start, old.end};
+ return result;
+}
void Ram_dataspace_factory::free(Ram_dataspace_capability ds_cap)
{
@@ -176,8 +187,25 @@ void Ram_dataspace_factory::free(Ram_dataspace_capability ds_cap)
});
/* call dataspace destructor and free memory */
- if (ds)
+ if (ds) {
+ try { _export_ram_ds(*ds); }
+ catch (Core_virtual_memory_exhausted) {
+ warning("could not export RAM dataspace of size ", ds->size());
+
+ /* cleanup unneeded resources */
+ destroy(_ds_slab, ds);
+ return;
+ }
+
+ /*
+ * Fill new dataspaces with zeros. For non-cached RAM dataspaces, this
+ * function must also make sure to flush all cache lines related to the
+ * address range used by the dataspace.
+ */
+ _clear_ds(*ds);
+ _unmap_ds_from_core(*ds);
destroy(_ds_slab, ds);
+ }
}
diff --git a/repos/base/src/core/stack_area.cc b/repos/base/src/core/stack_area.cc
index a8116e91d1..6ad9ea6f80 100644
--- a/repos/base/src/core/stack_area.cc
+++ b/repos/base/src/core/stack_area.cc
@@ -132,6 +132,10 @@ struct Stack_area_ram_allocator : Ram_allocator
Alloc_result try_alloc(size_t, Cache) override {
return reinterpret_cap_cast(Native_capability()); }
+ Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override {
+ return reinterpret_cap_cast(Native_capability()); }
+
+
void free(Ram_dataspace_capability) override { }
size_t dataspace_size(Ram_dataspace_capability) const override { return 0; }
diff --git a/repos/base/src/core/topo_session_component.cc b/repos/base/src/core/topo_session_component.cc
new file mode 100644
index 0000000000..736ff8ae17
--- /dev/null
+++ b/repos/base/src/core/topo_session_component.cc
@@ -0,0 +1,80 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+#include
+#include
+#include
+#include
+
+using namespace Genode;
+
+Topo_session_component::Topo_session_component(Rpc_entrypoint &session_ep,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Affinity affinity)
+ : Session_object(session_ep, resources, label, diag),
+ _affinity(affinity),
+ _md_alloc(ram_alloc, local_rm),
+ _node_count(0)
+{
+ construct();
+}
+
+void Topo_session_component::construct()
+{
+ Affinity::Location location = _affinity.location();
+ const unsigned height = location.height();
+ unsigned width = location.width();
+ unsigned curr_node_id = 0;
+ Topology::Numa_region *node_created = new (_md_alloc) Topology::Numa_region[64]();
+
+ //Genode::log("[", label(), "] Creating new topology model of size ", width, "x", height);
+
+ for (unsigned x = 0; x < width; x++)
+ {
+ for (unsigned y = 0; y < height; y++)
+ {
+ /* Map component's affinity matrix to its position in the affinity space.
+ * In order to get the correct physical CPU id for a coordinate in the affinity matrix of a component,
+ * we need the global coordination for it relative to the whole affinity space.
+ * But, every component's maintains a local view on its affinity matrix starting by (0,0), since
+ * affinity locations can have arbitrary coordinates in the affinity space, we need to transpose the
+ * component's affinity matrix to the global view of the affinity space. */
+ Affinity::Location loc = location.transpose(x, y);
+ unsigned cpu_id = platform_specific().kernel_cpu_id(loc);
+ unsigned native_id = platform_specific().domain_of_cpu(cpu_id);
+
+ //log("[", label(), "] CPU (", x, "x", y, ") is native CPU ", cpu_id, " on node ", native_id);
+
+ if (node_created[native_id].core_count() == 0)
+ {
+ _nodes[curr_node_id] = _node_affinities[x][y] = Topology::Numa_region(curr_node_id, native_id);
+ _node_affinities[x][y].increment_core_count();
+ node_created[native_id] = _node_affinities[x][y];
+ //log("[", label(), "] Found new native NUMA region ", native_id, " for CPU (", x, "x", y, ")");
+ _node_count++;
+ curr_node_id++;
+ }
+ else
+ {
+ (_node_affinities[x][y] = node_created[native_id]).increment_core_count();
+ _nodes[curr_node_id].increment_core_count();
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/repos/base/src/include/base/internal/expanding_topo_session_client.h b/repos/base/src/include/base/internal/expanding_topo_session_client.h
new file mode 100644
index 0000000000..654577e6a2
--- /dev/null
+++ b/repos/base/src/include/base/internal/expanding_topo_session_client.h
@@ -0,0 +1,51 @@
+/*
+ * \brief Topology session client that upgrades its session quota on demand
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+
+namespace Genode {
+ struct Expanding_topo_session_client;
+}
+
+struct Genode::Expanding_topo_session_client : Upgradeable_client
+{
+ Expanding_topo_session_client(Parent &parent, Genode::Topo_session_capability cap, Parent::Client::Id id)
+ :
+ Upgradeable_client
+ (parent, static_cap_cast(cap), id)
+ { }
+
+ Topology::Numa_region node_affinity_of(Affinity::Location const &loc) override
+ {
+ return retry(
+ [&]()
+ {
+ return retry(
+ [&]()
+ {
+ return Topo_session_client::node_affinity_of(loc);
+ },
+ [&]()
+ { upgrade_caps(2); });
+ },
+ [&]()
+ { upgrade_ram(8 * 1024); });
+ }
+};
\ No newline at end of file
diff --git a/repos/base/src/lib/base/child.cc b/repos/base/src/lib/base/child.cc
index 98834b8a60..5e9dc53010 100644
--- a/repos/base/src/lib/base/child.cc
+++ b/repos/base/src/lib/base/child.cc
@@ -45,6 +45,15 @@ void Child::yield(Resource_args const &args)
Signal_transmitter(_yield_sigh).submit();
}
+void Child::accept(Resource_args const &args)
+{
+ Mutex::Guard guard{_resource_gain_mutex};
+
+ _gained_resources = args;
+
+ if (_resource_avail_sigh.valid())
+ Signal_transmitter(_resource_avail_sigh).submit();
+}
void Child::notify_resource_avail() const
{
@@ -690,6 +699,12 @@ Parent::Resource_args Child::yield_request()
return _yield_request_args;
}
+Parent::Resource_args Child::gained_resources()
+{
+ Mutex::Guard guard(_resource_gain_mutex);
+
+ return _gained_resources;
+}
void Child::yield_response() { _policy.yield_response(); }
@@ -734,7 +749,7 @@ void Child::_try_construct_env_dependent_members()
{
/* check if the environment sessions are complete */
if (!_pd.cap().valid() || !_cpu.cap().valid() || !_log.cap().valid()
- || !_binary.cap().valid())
+ || !_binary.cap().valid() || !_topo.cap().valid())
return;
/*
@@ -803,6 +818,7 @@ void Child::initiate_env_sessions()
_cpu .initiate();
_log .initiate();
_binary.initiate();
+ _topo.initiate();
/*
* Issue environment-session request for obtaining the linker binary. We
@@ -885,6 +901,7 @@ void Child::close_all_sessions()
* Issue close requests to the providers of the environment sessions,
* which may be async services.
*/
+ _topo.close();
_log.close();
_binary.close();
if (_linker.constructed())
@@ -898,6 +915,7 @@ void Child::close_all_sessions()
_discard_env_session(Env::log());
_discard_env_session(Env::binary());
_discard_env_session(Env::linker());
+ _discard_env_session(Env::topo());
/*
* Remove dynamically created sessions from the child's ID space.
diff --git a/repos/base/src/lib/base/component.cc b/repos/base/src/lib/base/component.cc
index 530df9ae3e..838484bf15 100644
--- a/repos/base/src/lib/base/component.cc
+++ b/repos/base/src/lib/base/component.cc
@@ -21,6 +21,7 @@
/* base-internal includes */
#include
+#include
#include
namespace Genode { struct Component_env; }
@@ -86,6 +87,7 @@ struct Genode::Component_env : Env
Region_map &rm() override { return _rm; }
Pd_session &pd() override { return _pd; }
Entrypoint &ep() override { return _ep; }
+ Genode::Topo_session &topo() override { return *Genode::env_deprecated()->topo_session(); }
Cpu_session_capability cpu_session_cap() override { return _cpu_cap; }
Pd_session_capability pd_session_cap() override { return _pd_cap; }
diff --git a/repos/base/src/lib/base/env_session_id_space.cc b/repos/base/src/lib/base/env_session_id_space.cc
index 4749f42469..d45fe80e8b 100644
--- a/repos/base/src/lib/base/env_session_id_space.cc
+++ b/repos/base/src/lib/base/env_session_id_space.cc
@@ -34,7 +34,8 @@ Id_space &Genode::env_session_id_space()
cpu { dummy, id_space, Parent::Env::cpu() },
log { dummy, id_space, Parent::Env::log() },
binary { dummy, id_space, Parent::Env::binary() },
- linker { dummy, id_space, Parent::Env::linker() };
+ linker { dummy, id_space, Parent::Env::linker() },
+ topo { dummy, id_space, Parent::Env::topo() };
return id_space;
}
diff --git a/repos/base/src/lib/base/regional_heap.cc b/repos/base/src/lib/base/regional_heap.cc
new file mode 100644
index 0000000000..2ca2a36d08
--- /dev/null
+++ b/repos/base/src/lib/base/regional_heap.cc
@@ -0,0 +1,348 @@
+/*
+ * \brief Implementation of Genode heap partition
+ * \author Norman Feske
+ * \date 2006-05-17
+ */
+
+/*
+ * Copyright (C) 2006-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#include
+#include
+#include
+#include
+
+using namespace Genode;
+
+
+namespace {
+
+ enum {
+ MIN_CHUNK_SIZE = 4*1024, /* in machine words */
+ MAX_CHUNK_SIZE = 256*1024,
+ /*
+ * Allocation sizes >= this value are considered as big
+ * allocations, which get their own dataspace. In contrast
+ * to smaller allocations, this memory is released to
+ * the RAM session when 'free()' is called.
+ */
+ BIG_ALLOCATION_THRESHOLD = 64*1024 /* in bytes */
+ };
+}
+
+
+void Regional_heap::Dataspace_pool::remove_and_free(Dataspace &ds)
+{
+ /*
+ * read dataspace capability and modify _ds_list before detaching
+ * possible backing store for Dataspace - we rely on LIFO list
+ * manipulation here!
+ */
+
+ Ram_dataspace_capability ds_cap = ds.cap;
+ void *ds_local_addr = ds.local_addr;
+
+ remove(&ds);
+
+ /*
+ * Call 'Dataspace' destructor to properly release the RAM dataspace
+ * capabilities. Note that we don't free the 'Dataspace' object at the
+ * local allocator because this is already done by the 'Regional_heap'
+ * destructor prior executing the 'Dataspace_pool' destructor.
+ */
+ ds.~Dataspace();
+
+ region_map->detach(ds_local_addr);
+ ram_alloc->free(ds_cap);
+}
+
+
+Regional_heap::Dataspace_pool::~Dataspace_pool()
+{
+ /* free all ram_dataspaces */
+ for (Dataspace *ds; (ds = first()); )
+ remove_and_free(*ds);
+}
+
+
+int Regional_heap::quota_limit(size_t new_quota_limit)
+{
+ if (new_quota_limit < _quota_used) return -1;
+ _quota_limit = new_quota_limit;
+ return 0;
+}
+
+
+Regional_heap::Alloc_ds_result
+Regional_heap::_allocate_dataspace(size_t size, bool enforce_separate_metadata)
+{
+ using Result = Alloc_ds_result;
+
+ return _ds_pool.ram_alloc->try_alloc(size, _numa_id).convert(
+
+ [&] (Ram_dataspace_capability ds_cap) -> Result {
+
+ struct Alloc_guard
+ {
+ Ram_allocator &ram;
+ Ram_dataspace_capability ds;
+ bool keep = false;
+
+ Alloc_guard(Ram_allocator &ram, Ram_dataspace_capability ds)
+ : ram(ram), ds(ds) { }
+
+ ~Alloc_guard() { if (!keep) ram.free(ds); }
+
+ } alloc_guard(*_ds_pool.ram_alloc, ds_cap);
+
+ struct Attach_guard
+ {
+ Region_map &rm;
+ struct { void *ptr = nullptr; };
+ bool keep = false;
+
+ Attach_guard(Region_map &rm) : rm(rm) { }
+
+ ~Attach_guard() { if (!keep && ptr) rm.detach(ptr); }
+
+ } attach_guard(*_ds_pool.region_map);
+
+ try {
+ attach_guard.ptr = _ds_pool.region_map->attach(ds_cap);
+ }
+ catch (Out_of_ram) { return Alloc_error::OUT_OF_RAM; }
+ catch (Out_of_caps) { return Alloc_error::OUT_OF_CAPS; }
+ catch (Region_map::Invalid_dataspace) { return Alloc_error::DENIED; }
+ catch (Region_map::Region_conflict) { return Alloc_error::DENIED; }
+
+ Alloc_result metadata = Alloc_error::DENIED;
+
+ /* allocate the 'Dataspace' structure */
+ if (enforce_separate_metadata) {
+ metadata = _unsynchronized_alloc(sizeof(Regional_heap::Dataspace));
+
+ } else {
+
+ /* add new local address range to our local allocator */
+ _alloc->add_range((addr_t)attach_guard.ptr, size).with_result(
+ [&] (Range_allocator::Range_ok) {
+ metadata = _alloc->alloc_aligned(sizeof(Regional_heap::Dataspace), log2(64U)); },
+ [&] (Alloc_error error) {
+ metadata = error; });
+ }
+
+ return metadata.convert(
+ [&] (void *md_ptr) -> Result {
+ Dataspace &ds = *construct_at(md_ptr, ds_cap,
+ attach_guard.ptr, size);
+ _ds_pool.insert(&ds);
+ alloc_guard.keep = attach_guard.keep = true;
+ return &ds;
+ },
+ [&] (Alloc_error error) {
+ return error; });
+ },
+ [&] (Alloc_error error) {
+ return error; });
+}
+
+
+Allocator::Alloc_result Regional_heap::_try_local_alloc(size_t size)
+{
+ return _alloc->alloc_aligned(size, log2(64U)).convert(
+
+ [&] (void *ptr) {
+ _quota_used += size;
+ return ptr; },
+
+ [&] (Alloc_error error) {
+ return error; });
+}
+
+
+Allocator::Alloc_result Regional_heap::_unsynchronized_alloc(size_t size)
+{
+ if (size >= BIG_ALLOCATION_THRESHOLD) {
+
+ /*
+ * big allocation
+ *
+ * In this case, we allocate one dataspace without any meta data in it
+ * and return its local address without going through the allocator.
+ */
+
+ /* align to 4K page */
+ size_t const dataspace_size = align_addr(size, 12);
+
+ return _allocate_dataspace(dataspace_size, true).convert(
+
+ [&] (Dataspace *ds_ptr) {
+ _quota_used += ds_ptr->size;
+ return ds_ptr->local_addr; },
+
+ [&] (Alloc_error error) {
+ return error; });
+ }
+
+ /* try allocation at our local allocator */
+ {
+ Alloc_result result = _try_local_alloc(size);
+ if (result.ok())
+ return result;
+ }
+
+ size_t dataspace_size = size
+ + Allocator_avl::slab_block_size()
+ + sizeof(Regional_heap::Dataspace);
+ /* align to 4K page */
+ dataspace_size = align_addr(dataspace_size, 12);
+
+ /*
+ * '_chunk_size' is a multiple of 4K, so 'dataspace_size' becomes
+ * 4K-aligned, too.
+ */
+ size_t const request_size = _chunk_size * sizeof(umword_t);
+
+ Alloc_ds_result result = Alloc_error::DENIED;
+
+ if (dataspace_size < request_size) {
+
+ result = _allocate_dataspace(request_size, false);
+ if (result.ok()) {
+
+ /*
+ * Exponentially increase chunk size with each allocated chunk until
+ * we hit 'MAX_CHUNK_SIZE'.
+ */
+ _chunk_size = min(2*_chunk_size, (size_t)MAX_CHUNK_SIZE);
+ }
+ } else {
+ result = _allocate_dataspace(dataspace_size, false);
+ }
+
+ if (result.failed())
+ return result.convert(
+ [&] (Dataspace *) { return Alloc_error::DENIED; },
+ [&] (Alloc_error error) { return error; });
+
+ /* allocate originally requested block */
+ return _try_local_alloc(size);
+}
+
+
+Allocator::Alloc_result Regional_heap::try_alloc(size_t size)
+{
+
+ if (size == 0)
+ error("attempt to allocate zero-size block from heap");
+
+ /* serialize access of heap functions */
+ Mutex::Guard guard(_mutex);
+
+ /* check requested allocation against quota limit */
+ if (size + _quota_used > _quota_limit)
+ return Alloc_error::DENIED;
+
+ return _unsynchronized_alloc(size);
+}
+
+
+void Regional_heap::free(void *addr, size_t)
+{
+ /* serialize access of heap functions */
+ Mutex::Guard guard(_mutex);
+
+ using Size_at_error = Allocator_avl::Size_at_error;
+
+ Allocator_avl::Size_at_result size_at_result = _alloc->size_at(addr);
+
+ if (size_at_result.ok()) {
+ /* forward request to our local allocator */
+ size_at_result.with_result(
+ [&] (size_t size) {
+ /* forward request to our local allocator */
+ _alloc->free(addr, size);
+ _quota_used -= size;
+ },
+ [&] (Size_at_error) { });
+
+ return;
+ }
+
+ if (size_at_result == Size_at_error::MISMATCHING_ADDR) {
+ /* address was found in local allocator but is not a block start address */
+ error("heap could not free memory block: given address ", addr,
+ " is not a block start adress");
+ return;
+ }
+
+ /*
+ * Block could not be found in local allocator. So it is either a big
+ * allocation or invalid address.
+ */
+
+ Regional_heap::Dataspace *ds = nullptr;
+ for (ds = _ds_pool.first(); ds; ds = ds->next())
+ if (((addr_t)addr >= (addr_t)ds->local_addr) &&
+ ((addr_t)addr <= (addr_t)ds->local_addr + ds->size - 1))
+ break;
+
+ if (!ds) {
+ //warning("heap could not free memory block: invalid address");
+ throw Region_map::Invalid_dataspace();
+ return;
+ }
+
+ _quota_used -= ds->size;
+
+ _ds_pool.remove_and_free(*ds);
+ _alloc->free(ds);
+}
+
+
+Regional_heap::Regional_heap(Ram_allocator *ram_alloc,
+ Region_map *region_map,
+ Topology::Numa_region ®ion,
+ size_t quota_limit,
+ void *static_addr,
+ size_t static_size)
+:
+ _alloc(nullptr),
+ _ds_pool(ram_alloc, region_map),
+ _quota_limit(quota_limit), _quota_used(0),
+ _chunk_size(MIN_CHUNK_SIZE),
+ _numa_id(region.native_id())
+{
+ if (static_addr)
+ _alloc->add_range((addr_t)static_addr, static_size);
+}
+
+
+Regional_heap::~Regional_heap()
+{
+ /*
+ * Revert allocations of heap-internal 'Dataspace' objects. Otherwise, the
+ * subsequent destruction of the 'Allocator_avl' would detect those blocks
+ * as dangling allocations.
+ *
+ * Since no new allocations can occur at the destruction time of the
+ * 'Regional_heap', it is safe to release the 'Dataspace' objects at the allocator
+ * yet still access them afterwards during the destruction of the
+ * 'Allocator_avl'.
+ */
+ for (Regional_heap::Dataspace *ds = _ds_pool.first(); ds; ds = ds->next())
+ _alloc->free(ds, sizeof(Dataspace));
+
+ /*
+ * Destruct 'Allocator_avl' before destructing the dataspace pool. This
+ * order is important because some dataspaces of the dataspace pool are
+ * used as backing store for the allocator's meta data. If we destroyed
+ * the object pool before the allocator, the subsequent attempt to destruct
+ * the allocator would access no-longer-present backing store.
+ */
+ _alloc.destruct();
+}
diff --git a/repos/base/src/lib/base/thread.cc b/repos/base/src/lib/base/thread.cc
index b8ebd7d83b..70f4a961a7 100644
--- a/repos/base/src/lib/base/thread.cc
+++ b/repos/base/src/lib/base/thread.cc
@@ -241,6 +241,11 @@ size_t Thread::stack_area_virtual_size()
return Genode::stack_area_virtual_size();
}
+void Thread::pin(Affinity::Location &loc)
+{
+ _cpu_session->migrate_thread(_thread_cap, loc);
+ _affinity = loc;
+}
Thread::Thread(size_t weight, const char *name, size_t stack_size,
Type type, Cpu_session *cpu_session, Affinity::Location affinity)
diff --git a/repos/gems/recipes/raw/drivers_nic-pc/drivers.config b/repos/gems/recipes/raw/drivers_nic-pc/drivers.config
index 309ac11198..ccd6af3e6a 100644
--- a/repos/gems/recipes/raw/drivers_nic-pc/drivers.config
+++ b/repos/gems/recipes/raw/drivers_nic-pc/drivers.config
@@ -11,6 +11,7 @@
+
@@ -18,8 +19,8 @@
-
-
+
+
@@ -27,12 +28,13 @@
+
-
+
@@ -45,26 +47,28 @@
+
-
+
+
-
-
+
+
@@ -77,6 +81,7 @@
+
@@ -85,32 +90,15 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/repos/libports/lib/import/import-libpfm4.mk b/repos/libports/lib/import/import-libpfm4.mk
new file mode 100644
index 0000000000..ba6094e1cf
--- /dev/null
+++ b/repos/libports/lib/import/import-libpfm4.mk
@@ -0,0 +1 @@
+INC_DIR += $(call select_from_ports,libpfm4)/include
\ No newline at end of file
diff --git a/repos/libports/lib/import/import-stdcxx.mk b/repos/libports/lib/import/import-stdcxx.mk
index 0431165dcb..aeb5948698 100644
--- a/repos/libports/lib/import/import-stdcxx.mk
+++ b/repos/libports/lib/import/import-stdcxx.mk
@@ -36,7 +36,7 @@ include $(call select_from_repositories,lib/import/import-libc.mk)
CC_OPT += -D_GLIBCXX_HAVE_MBSTATE_T
# use compiler-builtin atomic operations
-CC_OPT += -D_GLIBCXX_ATOMIC_BUILTINS_4
+CC_OPT += -D_GLIBCXX_ATOMIC_BUILTINS_8 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
# No isinf isnan
CC_OPT += -D_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC
diff --git a/repos/libports/lib/mk/libpfm4.mk b/repos/libports/lib/mk/libpfm4.mk
new file mode 100644
index 0000000000..c998bfad52
--- /dev/null
+++ b/repos/libports/lib/mk/libpfm4.mk
@@ -0,0 +1,204 @@
+LIBPFM4_DIR := $(call select_from_ports,libpfm4)/src/lib/libpfm4
+
+CC_OPT += -D_REENTRANT -fvisibility=hidden
+
+SRC_CC = $(LIBPFM4_DIR)/lib/pfmlib_common.c
+
+# build libpfm only for x86_64 for now
+CONFIG_PFMLIB_ARCH_X86_64=y
+CONFIG_PFMLIB_ARCH_X86=y
+
+CONFIG_PFMLIB_SHARED?=n
+CONFIG_PFMLIB_DEBUG?=y
+CONFIG_PFMLIB_NOPYTHON?=y
+
+#
+# list all library support modules
+#
+ifeq ($(CONFIG_PFMLIB_ARCH_IA64),y)
+INCARCH = $(INC_IA64)
+#SRCS += pfmlib_gen_ia64.c pfmlib_itanium.c pfmlib_itanium2.c pfmlib_montecito.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_IA64
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_X86),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_intel_x86_perf_event.c pfmlib_amd64_perf_event.c \
+ pfmlib_intel_netburst_perf_event.c \
+ pfmlib_intel_snbep_unc_perf_event.c
+endif
+
+INCARCH = $(INC_X86)
+SRCS += pfmlib_amd64.c pfmlib_intel_core.c pfmlib_intel_x86.c \
+ pfmlib_intel_x86_arch.c pfmlib_intel_atom.c \
+ pfmlib_intel_nhm_unc.c pfmlib_intel_nhm.c \
+ pfmlib_intel_wsm.c \
+ pfmlib_intel_snb.c pfmlib_intel_snb_unc.c \
+ pfmlib_intel_ivb.c pfmlib_intel_ivb_unc.c \
+ pfmlib_intel_hsw.c \
+ pfmlib_intel_bdw.c \
+ pfmlib_intel_skl.c \
+ pfmlib_intel_icl.c \
+ pfmlib_intel_spr.c \
+ pfmlib_intel_rapl.c \
+ pfmlib_intel_snbep_unc.c \
+ pfmlib_intel_snbep_unc_cbo.c \
+ pfmlib_intel_snbep_unc_ha.c \
+ pfmlib_intel_snbep_unc_imc.c \
+ pfmlib_intel_snbep_unc_pcu.c \
+ pfmlib_intel_snbep_unc_qpi.c \
+ pfmlib_intel_snbep_unc_ubo.c \
+ pfmlib_intel_snbep_unc_r2pcie.c \
+ pfmlib_intel_snbep_unc_r3qpi.c \
+ pfmlib_intel_ivbep_unc_cbo.c \
+ pfmlib_intel_ivbep_unc_ha.c \
+ pfmlib_intel_ivbep_unc_imc.c \
+ pfmlib_intel_ivbep_unc_pcu.c \
+ pfmlib_intel_ivbep_unc_qpi.c \
+ pfmlib_intel_ivbep_unc_ubo.c \
+ pfmlib_intel_ivbep_unc_r2pcie.c \
+ pfmlib_intel_ivbep_unc_r3qpi.c \
+ pfmlib_intel_ivbep_unc_irp.c \
+ pfmlib_intel_hswep_unc_cbo.c \
+ pfmlib_intel_hswep_unc_ha.c \
+ pfmlib_intel_hswep_unc_imc.c \
+ pfmlib_intel_hswep_unc_pcu.c \
+ pfmlib_intel_hswep_unc_qpi.c \
+ pfmlib_intel_hswep_unc_ubo.c \
+ pfmlib_intel_hswep_unc_r2pcie.c \
+ pfmlib_intel_hswep_unc_r3qpi.c \
+ pfmlib_intel_hswep_unc_irp.c \
+ pfmlib_intel_hswep_unc_sbo.c \
+ pfmlib_intel_bdx_unc_cbo.c \
+ pfmlib_intel_bdx_unc_ubo.c \
+ pfmlib_intel_bdx_unc_sbo.c \
+ pfmlib_intel_bdx_unc_ha.c \
+ pfmlib_intel_bdx_unc_imc.c \
+ pfmlib_intel_bdx_unc_irp.c \
+ pfmlib_intel_bdx_unc_pcu.c \
+ pfmlib_intel_bdx_unc_qpi.c \
+ pfmlib_intel_bdx_unc_r2pcie.c \
+ pfmlib_intel_bdx_unc_r3qpi.c \
+ pfmlib_intel_skx_unc_cha.c \
+ pfmlib_intel_skx_unc_iio.c \
+ pfmlib_intel_skx_unc_imc.c \
+ pfmlib_intel_skx_unc_irp.c \
+ pfmlib_intel_skx_unc_m2m.c \
+ pfmlib_intel_skx_unc_m3upi.c \
+ pfmlib_intel_skx_unc_pcu.c \
+ pfmlib_intel_skx_unc_ubo.c \
+ pfmlib_intel_skx_unc_upi.c \
+ pfmlib_intel_knc.c \
+ pfmlib_intel_slm.c \
+ pfmlib_intel_tmt.c \
+ pfmlib_intel_knl.c \
+ pfmlib_intel_knl_unc_imc.c \
+ pfmlib_intel_knl_unc_edc.c \
+ pfmlib_intel_knl_unc_cha.c \
+ pfmlib_intel_knl_unc_m2pcie.c \
+ pfmlib_intel_glm.c \
+ pfmlib_intel_netburst.c \
+ pfmlib_amd64_k7.c pfmlib_amd64_k8.c pfmlib_amd64_fam10h.c \
+ pfmlib_amd64_fam11h.c pfmlib_amd64_fam12h.c \
+ pfmlib_amd64_fam14h.c pfmlib_amd64_fam15h.c \
+ pfmlib_amd64_fam17h.c pfmlib_amd64_fam16h.c \
+ pfmlib_amd64_fam19h.c pfmlib_amd64_rapl.c \
+ pfmlib_amd64_fam19h_l3.c
+
+CFLAGS += -DCONFIG_PFMLIB_ARCH_X86
+
+ifeq ($(CONFIG_PFMLIB_ARCH_I386),y)
+SRCS += pfmlib_intel_coreduo.c pfmlib_intel_p6.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_I386
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_X86_64),y)
+CFLAGS += -DCONFIG_PFMLIB_ARCH_X86_64
+endif
+
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_POWERPC),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_powerpc_perf_event.c
+endif
+
+INCARCH = $(INC_POWERPC)
+SRCS += pfmlib_powerpc.c pfmlib_power4.c pfmlib_ppc970.c pfmlib_power5.c \
+ pfmlib_power6.c pfmlib_power7.c pfmlib_torrent.c pfmlib_power8.c \
+ pfmlib_power9.c pfmlib_powerpc_nest.c pfmlib_power10.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_POWERPC
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_S390X),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_s390x_perf_event.c
+endif
+
+INCARCH = $(INC_S390X)
+SRCS += pfmlib_s390x_cpumf.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_S390X
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_SPARC),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_sparc_perf_event.c
+endif
+
+INCARCH = $(INC_SPARC)
+SRCS += pfmlib_sparc.c pfmlib_sparc_ultra12.c pfmlib_sparc_ultra3.c pfmlib_sparc_ultra4.c pfmlib_sparc_niagara.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_SPARC
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_ARM),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_arm_perf_event.c
+endif
+
+INCARCH = $(INC_ARM)
+SRCS += pfmlib_arm.c pfmlib_arm_armv7_pmuv1.c pfmlib_arm_armv6.c pfmlib_arm_armv8.c pfmlib_tx2_unc_perf_event.c pfmlib_kunpeng_unc_perf_event.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_ARM64),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_arm_perf_event.c
+endif
+
+INCARCH = $(INC_ARM64)
+SRCS += pfmlib_arm.c pfmlib_arm_armv8.c pfmlib_tx2_unc_perf_event.c pfmlib_kunpeng_unc_perf_event.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM64
+endif
+
+ifeq ($(CONFIG_PFMLIB_ARCH_MIPS),y)
+
+ifeq ($(SYS),Linux)
+SRCS += pfmlib_mips_perf_event.c
+endif
+
+INCARCH = $(INC_MIPS)
+SRCS += pfmlib_mips.c pfmlib_mips_74k.c
+CFLAGS += -DCONFIG_PFMLIB_ARCH_MIPS
+endif
+
+ifeq ($(CONFIG_PFMLIB_CELL),y)
+INCARCH = $(INC_CELL)
+#SRCS += pfmlib_cell.c
+CFLAGS += -DCONFIG_PFMLIB_CELL
+endif
+
+SRC_CC += $(addprefix $(LIBPFM4_DIR)/lib/,$(SRCS))
+vpath %.c $(LIBPFM4_DIR)/lib
+
+CC_OPT += $(CFLAGS)
+
+INC_DIR += $(LIBPFM4_DIR)/include $(LIBPFM4_DIR)/lib/events
+vpath %.h $(INC_DIR)
+
+LIBS += base libm libc
diff --git a/repos/libports/lib/mk/mxtasking.mk b/repos/libports/lib/mk/mxtasking.mk
index f78b4f5d97..19f7cc6386 100644
--- a/repos/libports/lib/mk/mxtasking.mk
+++ b/repos/libports/lib/mk/mxtasking.mk
@@ -1,19 +1,27 @@
MXTASKING_DIR := $(call select_from_ports,mxtasking)/src/lib/mxtasking
+GENODE_GCC_TOOLCHAIN_DIR := /usr/local/genode/tool/21.05
SRC_CC = $(shell find $(MXTASKING_DIR)/src/mx -name '*.cpp')
vpath %.cpp $(MXTASKING_DIR)/src/mx
INC_DIR += $(MXTASKING_DIR)/src $(MXTASKING_DIR)/lib
vpath %.h ${INC_DIR}
+INC_DIR += $(call select_from_repositories,src/lib/libc)
+INC_DIR += $(call select_from_repositories,src/lib/libc)/spec/x86_64
-CC_OPT += -pedantic -Wall \
+CUSTOM_CXX = /usr/local/genode/tool/bin/clang++
+CUSTOM_CC = /usr/local/genode/tool/bin/clang
+
+CC_OPT += --target=x86_64-genode --sysroot=/does/not/exist --gcc-toolchain=$(GENODE_GCC_TOOLCHAIN_DIR) -DCLANG_CXX11_ATOMICS
+CC_OPT += -std=c++20 -pedantic -Wall \
-Wno-invalid-offsetof -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization \
-Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Woverloaded-virtual \
-Wredundant-decls -Wshadow -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef \
- -Wno-unused -Wold-style-cast -Wno-uninitialized -O1 -g3 -fno-aligned-new
+ -Wno-unused -Wold-style-cast -Wno-uninitialized -O2 -g
-CC_OPT += $(addprefix -I ,$(INC_DIR))
+CC_OPT += $(addprefix -I ,$(INC_DIR))
CC_CXX_WARN_STRICT =
LIBS += base libm libc stdcxx
+EXT_OBJECTS += /usr/local/genode/tool/lib/clang/14.0.5/lib/linux/libclang_rt.builtins-x86_64.a /usr/local/genode/tool/lib/libatomic.a
#SHARED_LIB = yes
diff --git a/repos/libports/lib/symbols/libc b/repos/libports/lib/symbols/libc
index 0bde0b6ea0..de073087a1 100644
--- a/repos/libports/lib/symbols/libc
+++ b/repos/libports/lib/symbols/libc
@@ -1183,8 +1183,12 @@ _ZTVSt8bad_cast D 40
_ZTVSt9bad_alloc D 40
_ZTVSt9exception D 40
_ZTVSt9type_info D 64
+_ZdaPvSt11align_val_t W
_ZdlPv W
_ZdlPvm W
+_ZdlPvSt11align_val_t W
+_ZdlPvmSt11align_val_t W
+_ZnwmSt11align_val_t W
__aeabi_atexit T
__aeabi_unwind_cpp_pr0 T
__aeabi_unwind_cpp_pr1 T
diff --git a/repos/libports/lib/symbols/stdcxx b/repos/libports/lib/symbols/stdcxx
index e7a2643251..3fcd01da1b 100644
--- a/repos/libports/lib/symbols/stdcxx
+++ b/repos/libports/lib/symbols/stdcxx
@@ -129,6 +129,7 @@ _ZNK11__gnu_debug16_Error_formatter8_M_errorEv T
_ZNK11__gnu_debug19_Safe_iterator_base11_M_singularEv T
_ZNK11__gnu_debug19_Safe_iterator_base14_M_can_compareERKS0_ T
_ZNK11__gnu_debug25_Safe_local_iterator_base16_M_get_containerEv T
+_ZNSo6sentryD2Ev W
_ZNKSt10bad_typeid4whatEv T
_ZNKSt10error_code23default_error_conditionEv T
_ZNKSt11logic_error4whatEv T
@@ -136,6 +137,7 @@ _ZNKSt12bad_weak_ptr4whatEv T
_ZNKSt12future_error4whatEv T
_ZNKSt13random_device13_M_getentropyEv T
_ZNKSt13runtime_error4whatEv T
+_ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1ERKNSt7__cxx1112basic_stringIcS1_SaIcEEESt13_Ios_Openmode W
_ZNKSt16bad_array_length4whatEv T
_ZNKSt17bad_function_call4whatEv T
_ZNKSt19__iosfail_type_info11__do_upcastEPKN10__cxxabiv117__class_type_infoEPPv T
@@ -151,6 +153,7 @@ _ZNKSt6locale4nameEv T
_ZNKSt6locale5facet11_M_cow_shimEPKNS_2idE T
_ZNKSt6locale5facet11_M_sso_shimEPKNS_2idE T
_ZNKSt6localeeqERKS_ T
+_ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1ERKNSt7__cxx1112basic_stringIcS1_SaIcEEESt13_Ios_Openmode W
_ZNKSt8__detail20_Prime_rehash_policy11_M_next_bktEm T
_ZNKSt8__detail20_Prime_rehash_policy14_M_need_rehashEmmm T
_ZNKSt8bad_cast4whatEv T
@@ -320,6 +323,7 @@ _ZNSt13__future_base12_Result_baseD1Ev T
_ZNSt13__future_base12_Result_baseD2Ev T
_ZNSt13__future_base13_State_baseV211_Make_ready6_M_setEv T
_ZNSt13__future_base13_State_baseV211_Make_ready6_S_runEPv T
+_ZNSt13basic_filebufIcSt11char_traitsIcEED2Ev W
_ZNSt13basic_fstreamIcSt11char_traitsIcEE5closeEv T
_ZNSt13random_device14_M_init_pretr1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE T
_ZNSt13random_device14_M_init_pretr1ERKSs T
diff --git a/repos/libports/ports/libpfm4.hash b/repos/libports/ports/libpfm4.hash
new file mode 100644
index 0000000000..6eeb6653d7
--- /dev/null
+++ b/repos/libports/ports/libpfm4.hash
@@ -0,0 +1 @@
+b0ec09148c2be9f4a96203a3d2de4ebed6ce2da0
diff --git a/repos/libports/ports/libpfm4.port b/repos/libports/ports/libpfm4.port
new file mode 100644
index 0000000000..f0d7542ca3
--- /dev/null
+++ b/repos/libports/ports/libpfm4.port
@@ -0,0 +1,13 @@
+LICENSE := PD
+DOWNLOADS := libpfm4.git
+VERSION := git
+
+URL(libpfm4) := https://github.com/wcohen/libpfm4.git
+REV(libpfm4) := 8aaaf1747e96031a47ed6bd9337ff61a21f8cc64
+DIR(libpfm4) := src/lib/libpfm4
+
+DIRS += include
+DIRS += include/perfmon
+
+DIR_CONTENT(include) += src/lib/libpfm4/include/perfmon
+DIR_CONTENT(include/perfmon) += src/lib/libpfm4/include/perfmon/*.h
\ No newline at end of file
diff --git a/repos/libports/ports/mxtasking.hash b/repos/libports/ports/mxtasking.hash
index 55a1d66141..78dfa7fce1 100644
--- a/repos/libports/ports/mxtasking.hash
+++ b/repos/libports/ports/mxtasking.hash
@@ -1 +1 @@
-dafcd5b6d7029c2626ead3b36f755a9fbd5acb13
+6074b9fabac4e9ad3df2ec7fb39bbae5b6ffa520
diff --git a/repos/libports/ports/mxtasking.port b/repos/libports/ports/mxtasking.port
index 69155a9dcd..67151fb939 100644
--- a/repos/libports/ports/mxtasking.port
+++ b/repos/libports/ports/mxtasking.port
@@ -3,7 +3,7 @@ DOWNLOADS := mxtasking.git
VERSION := git
URL(mxtasking) := https://github.com/mmueller41/mxtasking.git
-REV(mxtasking) := c81b9168104be5fceebf35674b867bb965e95d43
+REV(mxtasking) := yritys
DIR(mxtasking) := src/lib/mxtasking
DIRS += include/mx/memory
@@ -42,6 +42,12 @@ DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/vector.h
DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/mpsc_queue.h
DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/queue.h
DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/random.h
+DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/bits.h
+DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/compiler.h
+DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/atomic.h
+DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/bit_alloc.h
+DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/field_alloc.h
+DIR_CONTENT(include/mx/util) += src/lib/mxtasking/src/mx/util/util.h
DIR_CONTENT(include/mx/system) += src/lib/mxtasking/src/mx/system/builtin.h
DIR_CONTENT(include/mx/system) += src/lib/mxtasking/src/mx/system/cpuid.h
DIR_CONTENT(include/mx/system) += src/lib/mxtasking/src/mx/system/cache.h
diff --git a/repos/libports/recipes/src/libpfm4/api b/repos/libports/recipes/src/libpfm4/api
new file mode 100644
index 0000000000..954b4ab6ae
--- /dev/null
+++ b/repos/libports/recipes/src/libpfm4/api
@@ -0,0 +1 @@
+libpfm4
\ No newline at end of file
diff --git a/repos/libports/recipes/src/libpfm4/content.mk b/repos/libports/recipes/src/libpfm4/content.mk
new file mode 100644
index 0000000000..1301d4f0ba
--- /dev/null
+++ b/repos/libports/recipes/src/libpfm4/content.mk
@@ -0,0 +1,17 @@
+MIRROR_FROM_REP_DIR := lib/mk/libpfm4.mk lib/import/import-libpfm4.mk
+
+content: src/lib/libpfm4 COPYING $(MIRROR_FROM_REP_DIR)
+
+PORT_DIR := $(call port_dir,$(REP_DIR)/ports/libpfm4)
+
+src/lib/libpfm4:
+ mkdir -p $@
+ cp -r $(PORT_DIR)/src/lib/libpfm4/* $@
+ rm -rf $@/.git
+ echo "LIBS = libpfm4" > $@/target.mk
+
+$(MIRROR_FROM_REP_DIR):
+ $(mirror_from_rep_dir)
+
+LICENSE:
+ echo "libpfm license, see src/lib/libpfm4/COPYING" > $@
\ No newline at end of file
diff --git a/repos/libports/recipes/src/libpfm4/used_api b/repos/libports/recipes/src/libpfm4/used_api
new file mode 100644
index 0000000000..186e29c4c6
--- /dev/null
+++ b/repos/libports/recipes/src/libpfm4/used_api
@@ -0,0 +1,3 @@
+base
+libm
+libc
\ No newline at end of file
diff --git a/repos/libports/run/acpica.run b/repos/libports/run/acpica.run
index 336353ece0..570efada90 100644
--- a/repos/libports/run/acpica.run
+++ b/repos/libports/run/acpica.run
@@ -39,13 +39,14 @@ set config {
+
-
+
diff --git a/repos/libports/run/netty.inc b/repos/libports/run/netty.inc
index 96c8b795e0..100aa4b716 100644
--- a/repos/libports/run/netty.inc
+++ b/repos/libports/run/netty.inc
@@ -22,6 +22,7 @@ import_from_depot [depot_user]/src/[base_src] \
[depot_user]/src/dynamic_rom \
[depot_user]/src/init \
[depot_user]/src/libc \
+ [depot_user]/src/stdcxx \
[depot_user]/src/nic_router \
[depot_user]/src/vfs_audit \
[depot_user]/src/vfs_[ipstack] \
@@ -39,6 +40,7 @@ append config {
+
@@ -48,12 +50,12 @@ append config {
-
+
-
+
@@ -64,7 +66,7 @@ append config {
-
+
@@ -73,7 +75,7 @@ append config {
-
+
-
+
@@ -106,14 +108,14 @@ append config {
append_if [use_dynamic_rom] config {
-
+
- <} [ipstack] { ip_addr="10.0.3.55" netmask="255.255.255.0" gateway="10.0.3.1" nameserver="8.8.8.8"/>
+
@@ -268,4 +270,4 @@ append_qemu_nic_args "host=10.0.2.1,dhcpstart=10.0.2.55,hostfwd=tcp::10080-:80,h
run_genode_until forever
-# vi: set ft=tcl :
+# vi: set ft=tcl
diff --git a/repos/libports/src/lib/libc/component.cc b/repos/libports/src/lib/libc/component.cc
index 237ec974dc..f89036e8d1 100644
--- a/repos/libports/src/lib/libc/component.cc
+++ b/repos/libports/src/lib/libc/component.cc
@@ -77,4 +77,4 @@ void Component::construct(Genode::Env &env)
* Default stack size for libc-using components
*/
Genode::size_t Libc::Component::stack_size() __attribute__((weak));
-Genode::size_t Libc::Component::stack_size() { return 32UL*1024*sizeof(long); }
+Genode::size_t Libc::Component::stack_size() { return 96UL*1024*sizeof(long); }
diff --git a/repos/libports/src/lib/libc/internal/env.h b/repos/libports/src/lib/libc/internal/env.h
index 815fe23184..370e11e02b 100644
--- a/repos/libports/src/lib/libc/internal/env.h
+++ b/repos/libports/src/lib/libc/internal/env.h
@@ -100,6 +100,7 @@ class Libc::Env_implementation : public Libc::Env, public Config_accessor
Region_map &rm() override { return _env.rm(); }
Pd_session &pd() override { return _env.pd(); }
Entrypoint &ep() override { return _env.ep(); }
+ Topo_session &topo() override { return _env.topo(); }
Cpu_session_capability cpu_session_cap() override {
return _env.cpu_session_cap(); }
@@ -110,6 +111,10 @@ class Libc::Env_implementation : public Libc::Env, public Config_accessor
Id_space &id_space() override {
return _env.id_space(); }
+ Topo_session_capability topo_session_cap() override {
+ return _env.topo_session_cap();
+ }
+
Session_capability session(Parent::Service_name const &name,
Parent::Client::Id id,
Parent::Session_args const &args,
diff --git a/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h b/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h
index faf28e9a00..749468d2f7 100644
--- a/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h
+++ b/repos/libports/src/lib/libc/internal/malloc_ram_allocator.h
@@ -64,6 +64,18 @@ struct Libc::Malloc_ram_allocator : Ram_allocator
[&] (Alloc_error error) {
return error; });
}
+
+ Alloc_result try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cache) override
+ {
+ return _ram.try_alloc(size, numa_id, cache).convert(
+
+ [&] (Ram_dataspace_capability cap) {
+ new (_md_alloc) Registered(_dataspaces, cap);
+ return cap; },
+
+ [&] (Alloc_error error) {
+ return error; });
+ }
void free(Ram_dataspace_capability ds_cap) override
{
diff --git a/repos/libports/src/lib/libc/malloc.cc b/repos/libports/src/lib/libc/malloc.cc
index 1a9e67b3b7..6c4bca7e36 100644
--- a/repos/libports/src/lib/libc/malloc.cc
+++ b/repos/libports/src/lib/libc/malloc.cc
@@ -86,7 +86,7 @@ class Libc::Malloc
SLAB_START = 5, /* 32 bytes (log2) */
SLAB_STOP = 11, /* 2048 bytes (log2) */
NUM_SLABS = (SLAB_STOP - SLAB_START) + 1,
- DEFAULT_ALIGN = 16
+ DEFAULT_ALIGN = 64
};
struct Metadata
diff --git a/repos/libports/src/test/netty/tcp/main.cc b/repos/libports/src/test/netty/tcp/main.cc
index 4c15a07a56..8ea8a72566 100644
--- a/repos/libports/src/test/netty/tcp/main.cc
+++ b/repos/libports/src/test/netty/tcp/main.cc
@@ -13,7 +13,7 @@
/* Local includes */
#include
-
+#include
namespace Netty { struct Tcp; }
@@ -59,56 +59,69 @@ void Netty::Tcp::server(int const sd, bool const nonblock, bool const read_write
Genode::log("okay, accept will not block");
}
- Genode::log("test in ", nonblock ? "non-blocking" : "blocking", " mode");
+ //Genode::log("test in ", nonblock ? "non-blocking" : "blocking", " mode");
int const cd = accept(sd, pcaddr, &scaddr);
- Genode::log("cd=", cd);
+ //Genode::log("cd=", cd);
if (cd == -1) DIE("accept");
- getnames(cd);
+ //getnames(cd);
- size_t count = 0;
- static char data[64*1024];
if (nonblock) nonblocking(cd);
- while (true) {
- int ret = read_write
- ? read(cd, data, sizeof(data))
- : recv(cd, data, sizeof(data), 0);
+ auto con_handler = std::thread{[cd, read_write, nonblock]()
+ {
+ size_t count = 0;
+ static char data[64*1024];
+ while (true)
+ {
+ //GENODE_LOG_TSC_NAMED(10, "netty_read");
+ int ret = read_write
+ ? read(cd, data, sizeof(data))
+ : recv(cd, data, sizeof(data), 0);
- if (ret == 0) {
- Genode::log("experienced EOF");
- break;
- }
+ if (ret == 0)
+ {
+ // Genode::log("experienced EOF");
+ break;
+ }
- if (ret > 0) {
- /* echo received data */
- ret = read_write
- ? write(cd, data, ret)
- : send(cd, data, ret, 0);
- if (ret == -1) DIE(read_write ? "write" : "send");
+ if (ret > 0)
+ {
+ //GENODE_LOG_TSC_NAMED(10, "netty_write");
+ /* echo received data */
+ ret = read_write
+ ? write(cd, data, ret)
+ : send(cd, data, ret, 0);
+ if (ret == -1)
+ DIE(read_write ? "write" : "send");
- count += ret;
- continue;
- }
+ count += ret;
+ continue;
+ }
- if (!nonblock || errno != EAGAIN)
- DIE(read_write ? "read" : "recv");
+ if (!nonblock || errno != EAGAIN)
+ DIE(read_write ? "read" : "recv");
- Genode::log("block in select because of EAGAIN");
- fd_set read_fds; FD_ZERO(&read_fds); FD_SET(cd, &read_fds);
- ret = select(cd + 1, &read_fds, nullptr, nullptr, nullptr);
- if (ret == -1) DIE("select");
- }
+ Genode::log("block in select because of EAGAIN");
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(cd, &read_fds);
+ ret = select(cd + 1, &read_fds, nullptr, nullptr, nullptr);
+ if (ret == -1)
+ DIE("select");
- Genode::log("echoed ", count, " bytes");
+ ret = shutdown(cd, SHUT_RDWR);
+ if (ret == -1) DIE("shutdown");
- ret = shutdown(cd, SHUT_RDWR);
- if (ret == -1) DIE("shutdown");
+ ret = close(cd);
+ if (ret == -1) DIE("close");
+ }
+ }};
+ con_handler.detach();
- ret = close(cd);
- if (ret == -1) DIE("close");
+ //Genode::log("echoed ", count, " bytes");
}
}
diff --git a/repos/libports/src/test/netty/tcp/target.mk b/repos/libports/src/test/netty/tcp/target.mk
index 14113d8715..b330e810cf 100644
--- a/repos/libports/src/test/netty/tcp/target.mk
+++ b/repos/libports/src/test/netty/tcp/target.mk
@@ -1,6 +1,6 @@
TARGET = test-netty_tcp
SRC_CC = main.cc netty.cc
-LIBS = base libc
+LIBS = base libc stdcxx
INC_DIR += $(PRG_DIR)/..
diff --git a/repos/mml/include/mxip/arch/cc.h b/repos/mml/include/mxip/arch/cc.h
new file mode 100644
index 0000000000..b09a2aaefd
--- /dev/null
+++ b/repos/mml/include/mxip/arch/cc.h
@@ -0,0 +1,66 @@
+/*
+ * \brief Some size definitions and macros needed by LwIP.
+ * \author Stefan Kalkowski
+ * \author Emery Hemingway
+ * \date 2009-11-10
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__ARCH__CC_H__
+#define __LWIP__ARCH__CC_H__
+
+#ifdef LITTLE_ENDIAN
+#undef LITTLE_ENDIAN
+#endif
+
+#ifdef BIG_ENDIAN
+#undef BIG_ENDIAN
+#endif
+
+#ifndef LWIP_RAND
+genode_uint32_t genode_rand();
+#define LWIP_RAND() genode_rand()
+#endif
+
+#include
+#include
+#include
+
+#ifndef LWIP_PLATFORM_DIAG
+void lwip_printf(const char *format, ...);
+#define LWIP_PLATFORM_DIAG(x) do { lwip_printf x; } while(0)
+#endif /* LWIP_PLATFORM_DIAG */
+
+
+#ifdef GENODE_RELEASE
+#define LWIP_PLATFORM_ASSERT(x)
+#else /* GENODE_RELEASE */
+void lwip_platform_assert(char const* msg, char const *file, int line);
+#define LWIP_PLATFORM_ASSERT(x) \
+ do { \
+ lwip_platform_assert(x, __FILE__, __LINE__); \
+ } while (0)
+#endif /* GENODE_RELEASE */
+
+
+/*
+ * XXX: Should these be inlined?
+ */
+void genode_memcpy( void *dst, const void *src, size_t len);
+void *genode_memmove(void *dst, const void *src, size_t len);
+
+void genode_free(void *ptr);
+void *genode_malloc(unsigned long size);
+void *genode_calloc(unsigned long number, unsigned long size);
+
+#define mem_clib_free genode_free
+#define mem_clib_malloc genode_malloc
+#define mem_clib_calloc genode_calloc
+
+#endif /* __LWIP__ARCH__CC_H__ */
diff --git a/repos/mml/include/mxip/arch/perf.h b/repos/mml/include/mxip/arch/perf.h
new file mode 100644
index 0000000000..eea977777f
--- /dev/null
+++ b/repos/mml/include/mxip/arch/perf.h
@@ -0,0 +1,20 @@
+/*
+ * \brief Header file with macros needed by LwIP.
+ * \author Stefan Kalkowski
+ * \date 2009-11-10
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__ARCH__PERF_H__
+#define __LWIP__ARCH__PERF_H__
+
+#define PERF_START
+#define PERF_STOP(x)
+
+#endif /* __LWIP__ARCH__PERF_H__ */
diff --git a/repos/mml/include/mxip/genode_init.h b/repos/mml/include/mxip/genode_init.h
new file mode 100644
index 0000000000..6076a5839b
--- /dev/null
+++ b/repos/mml/include/mxip/genode_init.h
@@ -0,0 +1,26 @@
+/*
+ * \brief Genode native lwIP initalization
+ * \author Emery Hemingway
+ * \date 2017-08-21
+ */
+
+/*
+ * Copyright (C) 2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__LWIP__GENODE_INIT_H_
+#define _INCLUDE__LWIP__GENODE_INIT_H_
+
+#include
+#include
+
+namespace Mxip {
+ void mxip_init(mx::memory::dynamic::Allocator &heap, ::Timer::Connection &timer);
+
+ Genode::Mutex &mutex();
+}
+
+#endif
diff --git a/repos/mml/include/mxip/lwipopts.h b/repos/mml/include/mxip/lwipopts.h
new file mode 100644
index 0000000000..41ac70f175
--- /dev/null
+++ b/repos/mml/include/mxip/lwipopts.h
@@ -0,0 +1,154 @@
+/*
+ * \brief Configuration file for LwIP, adapt it to your needs.
+ * \author Stefan Kalkowski
+ * \author Emery Hemingway
+ * \date 2009-11-10
+ *
+ * See lwip/src/include/lwip/opt.h for all options
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__LWIPOPTS_H__
+#define __LWIP__LWIPOPTS_H__
+
+/* Genode includes */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Use lwIP without OS-awareness
+ */
+#define NO_SYS 1
+#define SYS_LIGHTWEIGHT_PROT 0
+
+#define LWIP_DNS 0 /* DNS support */
+#define LWIP_DHCP 0 /* DHCP support */
+#define LWIP_SOCKET 0 /* LwIP socket API */
+#define LWIP_NETIF_LOOPBACK 0 /* Looping back to same address? */
+#define LWIP_STATS 0 /* disable stating */
+#define LWIP_ICMP 0
+#define LWIP_SNMP 0
+#define LWIP_TCP_TIMESTAMPS 0
+#define TCP_LISTEN_BACKLOG 255
+#define TCP_MSS 1460
+#define TCP_WND (46 * TCP_MSS)
+#define TCP_SND_BUF (46 * TCP_MSS)
+#define LWIP_WND_SCALE 3
+#define TCP_RCV_SCALE 2
+#define TCP_SND_QUEUELEN ((512 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))
+
+#define LWIP_NETIF_STATUS_CALLBACK 1 /* callback function used for interface changes */
+#define LWIP_NETIF_LINK_CALLBACK 1 /* callback function used for link-state changes */
+#define LWIP_SUPPORT_CUSTOM_PBUF 1
+
+#define LWIP_SINGLE_NETIF 1
+
+#define TCP_QUEUE_OOSEQ 1
+#define LWIP_PCB_ARRAY 1
+/***********************************
+ ** Checksum calculation settings **
+ ***********************************/
+
+/* checksum calculation for outgoing packets can be disabled if the hardware supports it */
+#define LWIP_CHECKSUM_ON_COPY 1 /* calculate checksum during memcpy */
+
+/*********************
+ ** Memory settings **
+ *********************/
+
+#define MEM_LIBC_MALLOC 1
+#define MEMP_MEM_MALLOC 1
+#define MEMP_MEM_INIT 0
+#define MEMP_NUM_TCP_SEG (2*TCP_SND_QUEUELEN)
+/* MEM_ALIGNMENT > 4 e.g. for x86_64 are not supported, see Genode issue #817 */
+#define MEM_ALIGNMENT 4
+
+#define DEFAULT_ACCEPTMBOX_SIZE 128
+#define TCPIP_MBOX_SIZE 128
+
+#define RECV_BUFSIZE_DEFAULT (512*1024)
+
+#define PBUF_POOL_SIZE 8192
+
+#define MEMP_NUM_SYS_TIMEOUT 64
+#define MEMP_NUM_TCP_PCB 512
+#define MEMP_NUM_PBUF (128*4096)
+
+#ifndef MEMCPY
+#define MEMCPY(dst,src,len) genode_memcpy(dst,src,len)
+#endif
+
+#ifndef MEMMOVE
+#define MEMMOVE(dst,src,len) genode_memmove(dst,src,len)
+#endif
+
+/********************
+ ** Debug settings **
+ ********************/
+#define LWIP_NOASSERT 1
+
+/* #define LWIP_DEBUG */
+/* #define DHCP_DEBUG LWIP_DBG_ON */
+/* #define ETHARP_DEBUG LWIP_DBG_ON */
+/* #define NETIF_DEBUG LWIP_DBG_ON */
+/* #define PBUF_DEBUG LWIP_DBG_ON */
+/* #define API_LIB_DEBUG LWIP_DBG_ON */
+/* #define API_MSG_DEBUG LWIP_DBG_ON */
+/* #define SOCKETS_DEBUG LWIP_DBG_ON */
+/* #define ICMP_DEBUG LWIP_DBG_ON */
+/* #define INET_DEBUG LWIP_DBG_ON */
+/* #define IP_DEBUG LWIP_DBG_ON */
+/* #define IP_REASS_DEBUG LWIP_DBG_ON */
+/* #define RAW_DEBUG LWIP_DBG_ON */
+/* #define MEM_DEBUG LWIP_DBG_ON */
+/* #define MEMP_DEBUG LWIP_DBG_ON */
+/* #define SYS_DEBUG LWIP_DBG_ON */
+/* #define TCP_DEBUG LWIP_DBG_ON */
+
+
+/*
+ ----------------------------------
+ ---------- DHCP options ----------
+ ----------------------------------
+*/
+
+#define LWIP_DHCP_CHECK_LINK_UP 1
+
+
+/*
+ ----------------------------------------------
+ ---------- Sequential layer options ----------
+ ----------------------------------------------
+*/
+/* no Netconn API */
+#define LWIP_NETCONN 0
+
+
+/*
+ ---------------------------------------
+ ---------- IPv6 options ---------------
+ ---------------------------------------
+*/
+
+#define LWIP_IPV6 0
+#define IPV6_FRAG_COPYHEADER 1
+
+#define LWIP_IPV4 1
+#define IPV4_FRAG_COPYHEADER 0
+#define IP_REASSEMBLY 0
+#define IP_FRAG 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LWIP__LWIPOPTS_H__ */
diff --git a/repos/mml/include/mxip/mxnic_netif.h b/repos/mml/include/mxip/mxnic_netif.h
new file mode 100644
index 0000000000..040fecbe13
--- /dev/null
+++ b/repos/mml/include/mxip/mxnic_netif.h
@@ -0,0 +1,555 @@
+/*
+ * \brief LwIP netif for the Nic session
+ * \author Emery Hemingway
+ * \date 2016-09-28
+ *
+ * If you want to use the lwIP API in a native Genode
+ * component then this is the Nic client to use.
+ */
+
+/*
+ * Copyright (C) 2016-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__NIC_NETIF_H__
+#define __LWIP__NIC_NETIF_H__
+
+#if ETH_PAD_SIZE
+#error ETH_PAD_SIZE defined but unsupported by lwip/nic_netif.h
+#endif
+
+#ifndef __cplusplus
+#error lwip/nic_netif.h is a C++ only header
+#endif
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+/* MxTasking includes */
+#include
+#include
+#include
+
+namespace Lwip {
+
+extern "C" {
+/* LwIP includes */
+#include
+#include
+#if LWIP_IPV6
+#include
+#endif
+#include
+#include
+#include
+#include
+#include
+}
+
+ class Nic_netif;
+ class Receive_task;
+ class Tx_ready_task;
+ class Link_state_task;
+ class Finished_rx_task;
+
+ extern "C" {
+
+ static void nic_netif_pbuf_free(pbuf *p);
+ static err_t nic_netif_init(struct netif *netif);
+ static err_t nic_netif_linkoutput(struct netif *netif, struct pbuf *p);
+ static void nic_netif_status_callback(struct netif *netif);
+ }
+
+ /**
+ * Metadata for packet backed pbufs
+ */
+ struct Nic_netif_pbuf
+ {
+ struct pbuf_custom p { };
+ Nic_netif &netif;
+ Nic::Packet_descriptor packet;
+
+ Nic_netif_pbuf(Nic_netif &nic, Nic::Packet_descriptor &pkt)
+ : netif(nic), packet(pkt)
+ {
+ p.custom_free_function = nic_netif_pbuf_free;
+ }
+ };
+
+}
+
+class Lwip::Nic_netif
+{
+ friend class Lwip::Receive_task;
+ friend class Lwip::Tx_ready_task;
+ friend class Lwip::Link_state_task;
+
+private:
+ enum
+ {
+ PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
+ BUF_SIZE = 128*PACKET_SIZE,
+ };
+
+ Genode::Tslab _pbuf_alloc;
+
+ Nic::Packet_allocator _nic_tx_alloc;
+ Nic::Connection _nic;
+
+ Genode::Entrypoint &_ep;
+
+ struct netif _netif
+ { };
+
+ ip_addr_t ip { };
+ ip_addr_t nm { };
+ ip_addr_t gw { };
+
+ Genode::Io_signal_handler _link_state_handler;
+ Genode::Io_signal_handler _rx_packet_handler;
+ Genode::Io_signal_handler _tx_ready_handler;
+
+ bool _dhcp { false };
+
+ std::unique_ptr _handler_allocator{nullptr};
+
+ public:
+
+ void free_pbuf(Nic_netif_pbuf &pbuf)
+ {
+ bool message_once = true;
+ while (!_nic.rx()->ready_to_ack()) {
+ if (message_once)
+ Genode::error("Nic rx acknowledge queue congested.");
+ message_once = false;
+ _ep.wait_and_dispatch_one_io_signal();
+ }
+
+ _nic.rx()->try_ack_packet(pbuf.packet);
+ wake_up_nic_server();
+
+ destroy(_pbuf_alloc, &pbuf);
+ }
+
+ Lwip::pbuf *alloc_pbuf(size_t len, const char *payload)
+ {
+ Lwip::pbuf_custom *pbuf = new (this->_pbuf_alloc) Lwip::pbuf_custom();
+
+ Lwip::pbuf *p = pbuf_alloced_custom(PBUF_TRANSPORT, len, PBUF_RAM, pbuf, static_cast(const_cast(payload)), len);
+
+ return p;
+ }
+
+ /*************************
+ ** Nic signal handlers **
+ *************************/
+
+ void handle_link_state();
+ void handle_rx_packets();
+
+ /**
+ * Handle tx ack_avail and ready_to_submit signals
+ */
+ void handle_tx_ready();
+
+ void configure(Genode::Xml_node const &config)
+ {
+ _dhcp = config.attribute_value("dhcp", false);
+
+ typedef Genode::String Str;
+ Str ip_str = config.attribute_value("ip_addr", Str());
+
+ Genode::log("Static IP: ", ip_str);
+
+ if (_dhcp && ip_str != "") {
+ _dhcp = false;
+ netif_set_down(&_netif);
+ Genode::error("refusing to configure lwIP interface with both DHCP and a static IPv4 address");
+ return;
+ }
+
+ netif_set_up(&_netif);
+
+ if (ip_str != "") {
+ ip_addr_t ipaddr;
+ if (!ipaddr_aton(ip_str.string(), &ipaddr)) {
+ Genode::error("lwIP configured with invalid IP address '",ip_str,"'");
+ throw ip_str;
+ }
+
+ netif_set_ipaddr(&_netif, ip_2_ip4(&ipaddr));
+
+ if (config.has_attribute("netmask")) {
+ Str str = config.attribute_value("netmask", Str());
+ ip_addr_t ip;
+ ipaddr_aton(str.string(), &ip);
+ netif_set_netmask(&_netif, ip_2_ip4(&ip));
+ }
+
+ if (config.has_attribute("gateway")) {
+ Str str = config.attribute_value("gateway", Str());
+ ip_addr_t ip;
+ ipaddr_aton(str.string(), &ip);
+ netif_set_gw(&_netif, ip_2_ip4(&ip));
+ }
+
+ }
+
+ if (config.has_attribute("nameserver")) {
+ /*
+ * LwIP does not use DNS internally, but the application
+ * should expect "dns_getserver" to work regardless of
+ * how the netif configures itself.
+ */
+ Str str = config.attribute_value("nameserver", Str());
+ ip_addr_t ip;
+ ipaddr_aton(str.string(), &ip);
+ //dns_setserver(0, &ip);
+ }
+
+ handle_link_state();
+ }
+
+ Nic_netif(Genode::Env &env,
+ Genode::Allocator &alloc,
+ Genode::Xml_node config)
+ :
+ _pbuf_alloc(alloc), _nic_tx_alloc(&alloc),
+ _nic(env, &_nic_tx_alloc,
+ BUF_SIZE, BUF_SIZE,
+ config.attribute_value("label", Genode::String<160>("lwip")).string()), _ep(env.ep()),
+ _link_state_handler(env.ep(), *this, &Nic_netif::handle_link_state),
+ _rx_packet_handler( env.ep(), *this, &Nic_netif::handle_rx_packets),
+ _tx_ready_handler( env.ep(), *this, &Nic_netif::handle_tx_ready)
+ {
+ Genode::memset(&_netif, 0x00, sizeof(_netif));
+
+ _handler_allocator.reset(new (mx::memory::GlobalHeap::allocate_cache_line_aligned(sizeof(mx::memory::dynamic::Allocator))) mx::memory::dynamic::Allocator());
+
+ {
+ ip4_addr_t v4dummy;
+ IP4_ADDR(&v4dummy, 0, 0, 0, 0);
+
+ netif* r = netif_add(&_netif, &v4dummy, &v4dummy, &v4dummy,
+ this, nic_netif_init, ethernet_input);
+ if (r == NULL) {
+ Genode::error("failed to initialize Nic to lwIP interface");
+ throw r;
+ }
+ }
+
+ netif_set_default(&_netif);
+ netif_set_status_callback(
+ &_netif, nic_netif_status_callback);
+ nic_netif_status_callback(&_netif);
+
+ configure(config);
+ }
+
+ virtual ~Nic_netif() { }
+
+ Lwip::netif& lwip_netif() { return _netif; }
+
+ /**
+ * Status callback to override in subclass
+ */
+ virtual void status_callback() { }
+
+ /**
+ * Callback issued by lwIP to initialize netif struct
+ *
+ * \noapi
+ */
+ err_t init()
+ {
+ /*
+ * XXX: hostname and MTU could probably be
+ * set in the Nic client constructor
+ */
+
+#if LWIP_NETIF_HOSTNAME
+ /* Initialize interface hostname */
+ _netif.hostname = "";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+ Genode::log("Setting name to en");
+ _netif.name[0] = 'e';
+ _netif.name[1] = 'n';
+
+ Genode::log("Setting callbacks");
+ _netif.output = etharp_output;
+#if LWIP_IPV6
+ _netif.output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
+
+ _netif.linkoutput = nic_netif_linkoutput;
+
+ /* Set physical MAC address */
+ Genode::log("Setting MAC address");
+ Nic::Mac_address const mac = _nic.mac_address();
+ for(int i=0; i<6; ++i)
+ _netif.hwaddr[i] = mac.addr[i];
+
+ Genode::log("Setting MTU and flags");
+ _netif.mtu = 1500; /* XXX: just a guess */
+ _netif.hwaddr_len = ETHARP_HWADDR_LEN;
+ _netif.flags = NETIF_FLAG_BROADCAST |
+ NETIF_FLAG_ETHARP |
+ NETIF_FLAG_LINK_UP;
+
+ /* set Nic session signal handlers */
+ Genode::log("Setting NIC handlers");
+ _nic.link_state_sigh(_link_state_handler);
+ _nic.rx_channel()->sigh_packet_avail(_rx_packet_handler);
+ _nic.rx_channel()->sigh_ready_to_ack(_rx_packet_handler);
+ _nic.tx_channel()->sigh_ready_to_submit(_tx_ready_handler);
+ _nic.tx_channel()->sigh_ack_avail (_tx_ready_handler);
+
+ Genode::log("Finished init of netif");
+ return ERR_OK;
+ }
+
+ /**
+ * Callback issued by lwIP to write a Nic packet
+ *
+ * \noapi
+ */
+ err_t linkoutput(struct pbuf *p)
+ {
+ auto &tx = *_nic.tx();
+ //GENODE_LOG_TSC(1);
+
+ /* flush acknowledgements */
+ while (tx.ack_avail())
+ tx.release_packet(tx.get_acked_packet());
+
+ if (!tx.ready_to_submit()) {
+ Genode::error("lwIP: Nic packet queue congested, cannot send packet");
+ return ERR_WOULDBLOCK;
+ }
+
+ Nic::Packet_descriptor packet;
+ try { packet = tx.alloc_packet(p->tot_len); }
+ catch (...) {
+ Genode::error("lwIP: Nic packet allocation failed, cannot send packet");
+ return ERR_WOULDBLOCK;
+ }
+
+ /*
+ * We iterate over the pbuf chain until we have read the entire
+ * pbuf into the packet.
+ */
+ char *dst = tx.packet_content(packet);
+ for(struct pbuf *q = p; q != 0; q = q->next) {
+ char const *src = (char*)q->payload;
+ Genode::memcpy(dst, src, q->len);
+ dst += q->len;
+ }
+
+ tx.try_submit_packet(packet);
+ wake_up_nic_server();
+ LINK_STATS_INC(link.xmit);
+ return ERR_OK;
+ }
+
+ bool ready()
+ {
+ return netif_is_up(&_netif) &&
+ !ip_addr_isany(&_netif.ip_addr);
+ }
+
+ void wake_up_nic_server()
+ {
+ _nic.rx()->wakeup();
+ _nic.tx()->wakeup();
+ }
+};
+
+class Lwip::Finished_rx_task : public mx::tasking::TaskInterface
+{
+ public:
+ Finished_rx_task(Lwip::Nic_netif &netif, Nic_netif_pbuf *pbuf) : _netif(netif), _pbuf(pbuf) {}
+
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ //Genode::log("Executing finished rx task");
+ _netif.free_pbuf(*_pbuf);
+
+ return mx::tasking::TaskResult::make_null();
+ }
+
+ private:
+ Lwip::Nic_netif &_netif;
+ struct Lwip::Nic_netif_pbuf *_pbuf;
+};
+
+class Lwip::Receive_task : public mx::tasking::TaskInterface
+{
+public:
+ Receive_task(Lwip::pbuf *pbuf, struct netif &netif, Lwip::Nic_netif &net, Lwip::Nic_netif_pbuf *npbuf) : _netif(netif), _pbuf(pbuf), _npbuf(npbuf), _net(net) {}
+
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ Lwip::err_t rc = _netif.input(_pbuf, &_netif);
+
+
+ if (rc != Lwip::ERR_OK)
+ {
+ Genode::error("error forwarding Nic packet to lwIP: error=", static_cast(rc));
+ pbuf_free(_pbuf);
+ }
+
+ _net._handler_allocator->free(this);
+ return mx::tasking::TaskResult::make_null();
+ }
+
+private:
+ struct netif &_netif;
+ struct Lwip::pbuf *_pbuf;
+ Lwip::Nic_netif_pbuf *_npbuf;
+ Lwip::Nic_netif &_net;
+};
+
+class Lwip::Tx_ready_task : public mx::tasking::TaskInterface
+{
+ public:
+ Tx_ready_task(Nic::Connection &nic, Lwip::Nic_netif &netif) : _nic(nic), _netif(netif) {}
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ auto &tx = *_nic.tx();
+ bool progress = false;
+
+ while (tx.ack_avail())
+ {
+ tx.release_packet(tx.try_get_acked_packet());
+ progress = true;
+ }
+
+ if (progress)
+ _netif.wake_up_nic_server();
+
+ _netif._handler_allocator->free(this);
+ return mx::tasking::TaskResult::make_null();
+
+ /* notify subclass to resume pending transmissions */
+ //status_callback();
+ }
+
+ private:
+ Nic::Connection &_nic;
+ Lwip::Nic_netif &_netif;
+};
+
+class Lwip::Link_state_task : public mx::tasking::TaskInterface
+{
+ public:
+ Link_state_task(Nic::Connection &nic, Lwip::netif &netif, Lwip::Nic_netif &nic_netif, bool dhcp) : _nic(nic), _nic_netif(nic_netif), _netif(netif), _dhcp(dhcp) {}
+
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ /*
+ * if the application wants to be informed of the
+ * link state then it should use 'set_link_callback'
+ */
+ if (_nic.link_state()) {
+ netif_set_link_up(&_netif);
+ /*if (_dhcp) {
+ err_t err = dhcp_start(&_netif);
+ if (err != ERR_OK) {
+ Genode::error("failed to configure lwIP interface with DHCP, error ", -err);
+ }
+ } else {
+ //dhcp_inform(&_netif);
+ }*/
+ } else {
+ netif_set_link_down(&_netif);
+ if (_dhcp) {
+ //dhcp_release_and_stop(&_netif);
+ }
+ }
+ _nic_netif._handler_allocator->free(this);
+ return mx::tasking::TaskResult::make_null();
+ }
+ private:
+ Nic::Connection &_nic;
+ Lwip::Nic_netif &_nic_netif;
+ Lwip::netif &_netif;
+ bool _dhcp;
+};
+
+
+/**************************
+ ** LwIP netif callbacks **
+ **************************/
+
+namespace Lwip
+{
+ extern "C" {
+
+/**
+ * Free a packet buffer backed pbuf
+ */
+static void nic_netif_pbuf_free(pbuf *p)
+{
+ Nic_netif_pbuf *nic_pbuf = reinterpret_cast(p);
+ nic_pbuf->netif.free_pbuf(*nic_pbuf);
+}
+
+
+/**
+ * Initialize the netif
+ */
+static err_t nic_netif_init(struct netif *netif)
+{
+ Lwip::Nic_netif *nic_netif = (Lwip::Nic_netif *)netif->state;
+ return nic_netif->init();
+}
+
+
+/**
+ * Send a raw packet to the Nic session
+ */
+static err_t nic_netif_linkoutput(struct netif *netif, struct pbuf *p)
+{
+ Lwip::Nic_netif *nic_netif = (Lwip::Nic_netif *)netif->state;
+ return nic_netif->linkoutput(p);
+}
+
+
+static void nic_netif_status_callback(struct netif *netif)
+{
+ Lwip::Nic_netif *nic_netif = (Lwip::Nic_netif *)netif->state;
+
+ if (netif_is_up(netif)) {
+ /*if (IP_IS_V6_VAL(netif->ip_addr)) {
+ Genode::log("lwIP Nic interface up"
+ ", address=",(char const*)ip6addr_ntoa(netif_ip6_addr(netif, 0)));
+ } else */if (!ip4_addr_isany(netif_ip4_addr(netif))) {
+ typedef Genode::String Str;
+ Str address((char const*)ip4addr_ntoa(netif_ip4_addr(netif)));
+ Str netmask((char const*)ip4addr_ntoa(netif_ip4_netmask(netif)));
+ Str gateway((char const*)ip4addr_ntoa(netif_ip4_gw(netif)));
+
+ Genode::log("lwIP Nic interface up"
+ " address=", address,
+ " netmask=", netmask,
+ " gateway=", gateway);
+ }
+ } else {
+ Genode::log("lwIP Nic interface down");
+ }
+
+ nic_netif->status_callback();
+}
+
+ }
+}
+
+#endif /* __LWIP__NIC_NETIF_H__ */
diff --git a/repos/mml/lib/import/import-mxip.mk b/repos/mml/lib/import/import-mxip.mk
new file mode 100644
index 0000000000..0176efdfea
--- /dev/null
+++ b/repos/mml/lib/import/import-mxip.mk
@@ -0,0 +1,2 @@
+INC_DIR += $(call select_from_ports,lwip)/include/lwip
+INC_DIR += $(call select_from_repositories,include/mxip)
diff --git a/repos/mml/lib/mk/mxip.mk b/repos/mml/lib/mk/mxip.mk
new file mode 100644
index 0000000000..ac0c7ad764
--- /dev/null
+++ b/repos/mml/lib/mk/mxip.mk
@@ -0,0 +1,49 @@
+#
+# lwIP TCP/IP library
+#
+# The library implements TCP and UDP as well as DNS and DHCP.
+#
+
+LWIP_PORT_DIR := $(call select_from_ports,mxip)
+LWIPDIR := $(LWIP_PORT_DIR)/src/lib/lwip/src
+
+-include $(LWIPDIR)/Filelists.mk
+
+# Genode platform files
+SRC_CC = printf.cc rand.cc sys_arch.cc mxnic_netif.cc
+
+# Core files
+SRC_C += $(notdir $(COREFILES))
+
+# IPv4 files
+SRC_C += $(notdir $(CORE4FILES))
+
+# IPv6 files
+SRC_C += $(notdir $(CORE6FILES))
+
+# Network interface files
+SRC_C += $(notdir $(NETIFFILES))
+
+INC_DIR += $(REP_DIR)/include/mxip \
+ $(LWIP_PORT_DIR)/include/lwip \
+ $(LWIPDIR)/include \
+ $(LWIPDIR)/include/ipv4 \
+ $(LWIPDIR)/include/api \
+ $(LWIPDIR)/include/netif \
+
+vpath %.cc $(REP_DIR)/src/lib/mxip/platform
+vpath %.c $(sort $(dir \
+ $(COREFILES) $(CORE4FILES) $(CORE6FILES) $(NETIFFILES)))
+
+GENODE_GCC_TOOLCHAIN_DIR ?= /usr/local/genode/tool/21.05
+
+CUSTOM_CXX = /usr/local/genode/tool/bin/clang++
+CUSTOM_CC = /usr/local/genode/tool/bin/clang
+
+CC_OPT := --target=x86_64-genode --sysroot=/does/not/exist --gcc-toolchain=$(GENODE_GCC_TOOLCHAIN_DIR) -DCLANG_CXX11_ATOMICS -Wno-error=all -Wno-error=conversion -Wno-error=effc++ -Wno-error=unknown-attributes -g -DNDEBUG -I$(MXINC_DIR) -std=c++20 -mssse3 #-D_GLIBCXX_ATOMIC_BUILTINS_8 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+
+CC_OLEVEL = -O3
+
+LIBS += libm libc stdcxx mxtasking
+EXT_OBJECTS += /usr/local/genode/tool/lib/clang/14.0.5/lib/linux/libclang_rt.builtins-x86_64.a /usr/local/genode/tool/lib/libatomic.a
+
diff --git a/repos/mml/ports/ciao-ip.hash b/repos/mml/ports/ciao-ip.hash
new file mode 100644
index 0000000000..d3d8276f72
--- /dev/null
+++ b/repos/mml/ports/ciao-ip.hash
@@ -0,0 +1 @@
+9428aff1932ed69e452867f71012ee91412fc1fa
diff --git a/repos/mml/ports/ciao-ip.port b/repos/mml/ports/ciao-ip.port
new file mode 100644
index 0000000000..5bdbb6a2f5
--- /dev/null
+++ b/repos/mml/ports/ciao-ip.port
@@ -0,0 +1,146 @@
+LICENSE := GPL
+DOWNLOADS := ciao-ip.git
+VERSION := git
+
+URL(ciao-ip) := git@ess-git.inf.uos.de:software/ciao-ip.git
+REV(ciao-ip) := master
+DIR(ciao-ip) := src/lib/ciao-ip
+
+CC_OPT += "--target x86_64-linux-gnu"
+#ifndef CIAO_IP_CONFIG
+# CIAO_IP_CONFIG = $(realpath $(dir $(PORT)))/.ciao-ip-config
+#endif
+
+# Include the configuration file
+#include $(CIAO_IP_CONFIG)
+
+#ACXX := $(which ag++)
+#ASPECTSRC = $(shell find -L ./src/lib/ciao-ip/src/ -name "*.ah" -not -name ".*"|cut -b 3-)
+
+# Apply rules for conditional compilation, i.e., remove files if not selected
+#include $(realpath $(dir $(PORT)))/ciao-ip-config.mk
+
+#ACXXFLAGS += $(foreach file,$(ASPECTSRC),-a $(file)) -p ./src/lib/ciao-ip/src/
+
+DIRS += include/ciao-ip/hw/hal
+DIRS += include/ciao-ip/ipstack/router
+DIRS += include/ciao-ip/ipstack/api
+DIRS += include/ciao-ip/ipstack/arp
+DIRS += include/ciao-ip/ipstack/arp/ipv4
+DIRS += include/ciao-ip/ipstack/demux
+DIRS += include/ciao-ip/ipstack/icmp
+DIRS += include/ciao-ip/ipstack/ipv4/ipv4_icmp
+DIRS += include/ciao-ip/ipstack/ipv4/ipv4_tcp
+DIRS += include/ciao-ip/ipstack/ipv4/ipv4_udp
+DIRS += include/ciao-ip/ipstack/ipv4
+DIRS += include/ciao-ip/ipstack/router
+DIRS += include/ciao-ip/ipstack/tcp/tcp_history
+DIRS += include/ciao-ip/ipstack/tcp/tcp_receivebuffer
+DIRS += include/ciao-ip/ipstack/tcp/sws
+DIRS += include/ciao-ip/ipstack/tcp/statemachine
+DIRS += include/ciao-ip/ipstack/tcp/tcp_options
+DIRS += include/ciao-ip/ipstack/tcp
+DIRS += include/ciao-ip/ipstack/udp
+DIRS += include/ciao-ip/ipstack/util
+DIRS += include/ciao-ip/ipstack
+DIRS += include/ciao-ip/util
+
+
+
+# for f in $(find build -name "*.ah"); do DST=$(dirname $f | sed -s 's/build\/header/include\/ciao-ip/' | sed -s "s/include/DIR_CONTENT(include/" | sed -s "s/$/) += /"); echo $DST $f; done
+DIR_CONTENT(include/ciao-ip/hw/hal) += src/lib/ciao-ip/build/header/hw/hal/NetworkDevice.h
+DIR_CONTENT(include/ciao-ip/ipstack/icmp) += src/lib/ciao-ip/build/header/ipstack/icmp/ICMP.h
+DIR_CONTENT(include/ciao-ip/ipstack/router) += src/lib/ciao-ip/build/header/ipstack/router/Interface.h
+DIR_CONTENT(include/ciao-ip/ipstack/router) += src/lib/ciao-ip/build/header/ipstack/router/Router.h
+DIR_CONTENT(include/ciao-ip/ipstack/util) += src/lib/ciao-ip/build/header/ipstack/util/MempoolBase.h
+DIR_CONTENT(include/ciao-ip/ipstack/util) += src/lib/ciao-ip/build/header/ipstack/util/RingbufferBase.h
+DIR_CONTENT(include/ciao-ip/ipstack/util) += src/lib/ciao-ip/build/header/ipstack/util/Mempool.h
+DIR_CONTENT(include/ciao-ip/ipstack/util) += src/lib/ciao-ip/build/header/ipstack/util/Ringbuffer.h
+DIR_CONTENT(include/ciao-ip/ipstack) += src/lib/ciao-ip/build/header/ipstack/Eth_Frame.h
+DIR_CONTENT(include/ciao-ip/ipstack/as) += src/lib/ciao-ip/build/header/ipstack/as/EventSupport.h
+DIR_CONTENT(include/ciao-ip/ipstack) += src/lib/ciao-ip/build/header/ipstack/Clock.h
+DIR_CONTENT(include/ciao-ip/ipstack) += src/lib/ciao-ip/build/header/ipstack/IPStack_Config_kconf.h
+DIR_CONTENT(include/ciao-ip/ipstack/udp) += src/lib/ciao-ip/build/header/ipstack/udp/UDP.h
+DIR_CONTENT(include/ciao-ip/ipstack/udp) += src/lib/ciao-ip/build/header/ipstack/udp/UDP_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp) += src/lib/ciao-ip/build/header/ipstack/tcp/TCP.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_receivebuffer) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_receivebuffer/TCP_ReceiveBuffer.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_receivebuffer) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_receivebuffer/TCP_RecvElement.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp) += src/lib/ciao-ip/build/header/ipstack/tcp/TCP_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp) += src/lib/ciao-ip/build/header/ipstack/tcp/TCP_Config.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_history) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_history/TCP_Record.h
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_history) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_history/TCP_History.h
+DIR_CONTENT(include/ciao-ip/ipstack/api) += src/lib/ciao-ip/build/header/ipstack/api/Setup.h
+DIR_CONTENT(include/ciao-ip/ipstack/api) += src/lib/ciao-ip/build/header/ipstack/api/IPv4_UDP_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/api) += src/lib/ciao-ip/build/header/ipstack/api/IPv4_TCP_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/demux) += src/lib/ciao-ip/build/header/ipstack/demux/Demux.h
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/IPv4_TCP_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/IPv4.h
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/IPv4_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_udp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_udp/IPv4_UDP_Socket.h
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/InternetChecksum.h
+DIR_CONTENT(include/ciao-ip/ipstack) += src/lib/ciao-ip/build/header/ipstack/IPStack_Config.h
+DIR_CONTENT(include/ciao-ip/ipstack/arp) += src/lib/ciao-ip/build/header/ipstack/arp/ARP_Cache.h
+DIR_CONTENT(include/ciao-ip/ipstack/arp) += src/lib/ciao-ip/build/header/ipstack/arp/ARP.h
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/Eth_ARP_IPv4_Packet.h
+DIR_CONTENT(include/ciao-ip/util) += src/lib/ciao-ip/build/header/util/types.h
+DIR_CONTENT(include/ciao-ip/ipstack) += src/lib/ciao-ip/build/header/ipstack/Little_Endian.ah
+DIR_CONTENT(include/ciao-ip/ipstack/router) += src/lib/ciao-ip/build/header/ipstack/router/Interface_Delegation.ah
+DIR_CONTENT(include/ciao-ip/ipstack/router) += src/lib/ciao-ip/build/header/ipstack/router/Router.ah
+DIR_CONTENT(include/ciao-ip/ipstack/router) += src/lib/ciao-ip/build/header/ipstack/router/Interface.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/sws) += src/lib/ciao-ip/build/header/ipstack/tcp/sws/SWS_SenderAvoidance.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/sws) += src/lib/ciao-ip/build/header/ipstack/tcp/sws/SWS_ReceiverAvoidance.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/sws) += src/lib/ciao-ip/build/header/ipstack/tcp/sws/SWS_SenderAvoidance_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/synsent.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/synrcvd.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/listen.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/closed.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/closewait.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/finwait2.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/closing.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/established.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/finwait1.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/TCP_Statemachine.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/lastack.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/synsent_dummy.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/statemachine) += src/lib/ciao-ip/build/header/ipstack/tcp/statemachine/timewait.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_options) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_options/MSS.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_options) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_options/MSS_TCP_Segment_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_options) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_options/MSS_TCP_Socket_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_history) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_history/TCP_Record_RetransmissionCounter.ah
+DIR_CONTENT(include/ciao-ip/ipstack/tcp/tcp_history) += src/lib/ciao-ip/build/header/ipstack/tcp/tcp_history/TCP_Record_RetransmissionCounter_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/demux) += src/lib/ciao-ip/build/header/ipstack/demux/Demux.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/IPv4_TCP_Listen.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/IPv4_TCP_Tx_Checksumming.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/IPv4_TCP_Socket_Listen_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/Demux_IPv4_TCP_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/IPv4_TCP_Receive.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_tcp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_tcp/Demux_IPv4_TCP_Listen_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/Demux_IPv4_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/IPv4_Receive_Ethernet.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/Router_IPv4_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/IPv4_Receive.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/IPv4_Socket_Ethernet.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_icmp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_icmp/IPv4_ICMP_Ethernet.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_icmp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_icmp/IPv4_ICMP_Receive.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_icmp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_icmp/IPv4_ICMP_Echo_Reply.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4/ipv4_icmp) += src/lib/ciao-ip/build/header/ipstack/ipv4/ipv4_icmp/Demux_IPv4_ICMP_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/IPv4.ah
+DIR_CONTENT(include/ciao-ip/ipstack/ipv4) += src/lib/ciao-ip/build/header/ipstack/ipv4/Interface_IPv4_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack) += src/lib/ciao-ip/build/header/ipstack/Receive_Ethernet.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp) += src/lib/ciao-ip/build/header/ipstack/arp/ARP_Ethernet.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp) += src/lib/ciao-ip/build/header/ipstack/arp/ARP.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp) += src/lib/ciao-ip/build/header/ipstack/arp/Demux_ARP_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/ARP_Cache_IPv4_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/ARP_Cache_IPv4_Send_Receive_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/ARP_Cache_IPv4_Send_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/IPv4_ARP_Send.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/IPv4_Socket_Ethernet_ARP_Slice.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/IPv4_ARP.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/IPv4_Socket_Ethernet_ARP.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/IPv4_ARP_Receive.ah
+DIR_CONTENT(include/ciao-ip/ipstack/arp/ipv4) += src/lib/ciao-ip/build/header/ipstack/arp/ipv4/IPv4_ARP_Send_Receive.ah
+
+headers:
+ ACXXFLAGS=$(CC_OPT) make -C src/lib/ciao-ip header
+
+_dirs: headers
\ No newline at end of file
diff --git a/repos/mml/ports/mxip.hash b/repos/mml/ports/mxip.hash
new file mode 100644
index 0000000000..edaa2b4e63
--- /dev/null
+++ b/repos/mml/ports/mxip.hash
@@ -0,0 +1 @@
+e310a8d13995d4b3110cb727a298d781b4f03504
diff --git a/repos/mml/ports/mxip.port b/repos/mml/ports/mxip.port
new file mode 100644
index 0000000000..461b4202af
--- /dev/null
+++ b/repos/mml/ports/mxip.port
@@ -0,0 +1,23 @@
+LICENSE := BSD
+VERSION := 2.1.2
+DOWNLOADS := lwip.archive
+
+URL(lwip) := http://git.savannah.nongnu.org/cgit/lwip.git/snapshot/lwip-STABLE-2_1_2_RELEASE.tar.gz
+SHA(lwip) := da6a3e07944505e6add328f6efafea4ad670700731f36b1ba54bd43d4f35243e
+DIR(lwip) := src/lib/lwip
+
+UNPACKED_DIR := src/lib/lwip
+
+PATCHES := $(wildcard $(REP_DIR)/src/lib/lwip/*.patch)
+PATCH_OPT := -p1 -d src/lib/lwip
+
+DIRS := \
+ include/lwip/lwip \
+ include/lwip/lwip/priv \
+ include/lwip/lwip/prot \
+ include/lwip/netif \
+
+DIR_CONTENT(include/lwip/lwip/priv) := $(UNPACKED_DIR)/src/include/lwip/priv/*.h
+DIR_CONTENT(include/lwip/lwip/prot) := $(UNPACKED_DIR)/src/include/lwip/prot/*.h
+DIR_CONTENT(include/lwip/lwip) := $(UNPACKED_DIR)/src/include/lwip/*.h
+DIR_CONTENT(include/lwip/netif) := $(UNPACKED_DIR)/src/include/netif/*.h
diff --git a/repos/mml/recipes/api/mxip/content.mk b/repos/mml/recipes/api/mxip/content.mk
new file mode 100644
index 0000000000..8c28bde149
--- /dev/null
+++ b/repos/mml/recipes/api/mxip/content.mk
@@ -0,0 +1,20 @@
+MIRROR_FROM_REP_DIR := \
+ $(shell cd $(REP_DIR); find include/mxip src/lib/mxip -type f) \
+ lib/import/import-mxip.mk \
+ lib/mk/mxip.mk \
+
+PORT_DIR := $(call port_dir,$(REP_DIR)/ports/mxip)
+
+MIRROR_FROM_PORT_DIR := $(shell cd $(PORT_DIR); find include src -type f)
+
+content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_PORT_DIR) LICENSE
+
+$(MIRROR_FROM_REP_DIR):
+ $(mirror_from_rep_dir)
+
+$(MIRROR_FROM_PORT_DIR):
+ mkdir -p $(dir $@)
+ cp -r $(PORT_DIR)/$@ $@
+
+LICENSE:
+ cp $(PORT_DIR)/src/lib/lwip/COPYING $@
diff --git a/repos/mml/recipes/api/mxip/used_api b/repos/mml/recipes/api/mxip/used_api
new file mode 100644
index 0000000000..7a5f1ab72b
--- /dev/null
+++ b/repos/mml/recipes/api/mxip/used_api
@@ -0,0 +1,5 @@
+base
+libm
+libc
+stdcxx
+mxtasking
\ No newline at end of file
diff --git a/repos/mml/run/antagonist.run b/repos/mml/run/antagonist.run
new file mode 100644
index 0000000000..ce03327a20
--- /dev/null
+++ b/repos/mml/run/antagonist.run
@@ -0,0 +1,95 @@
+set build_components {
+ core init hoitaja timer app/antagonist
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+build $build_components
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+set boot_modules {
+ core init hoitaja timer vfs.lib.so libm.lib.so libc.lib.so stdcxx.lib.so ld.lib.so stress_genode
+}
+build_boot_image $boot_modules
+append qemu_args "-nographic"
+run_genode_until forever
diff --git a/repos/mml/run/bestow_resources.run b/repos/mml/run/bestow_resources.run
new file mode 100644
index 0000000000..97718b6303
--- /dev/null
+++ b/repos/mml/run/bestow_resources.run
@@ -0,0 +1,65 @@
+set build_components {
+ core init hoitaja timer app/grant_bench
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+ install_config $config
+
+ set boot_modules {
+ core init hoitaja timer vfs.lib.so ld.lib.so benchmark_resource_award
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/blinktree.run b/repos/mml/run/blinktree.run
index 24f929c092..c005253351 100644
--- a/repos/mml/run/blinktree.run
+++ b/repos/mml/run/blinktree.run
@@ -1,5 +1,5 @@
set build_components {
- core init timer app/blinktree
+ core init timer app/blinktree hoitaja
}
source ${genode_dir}/repos/base/run/platform_drv.inc
@@ -21,14 +21,16 @@ set config {
+
+
-
-
+
+
@@ -36,41 +38,210 @@ set config {
}
-append_platform_drv_config
-
append config {
-
-
-
-
-
-
-
-
-
-
-
- 2022-07-20 14:30
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
}
install_config $config
set boot_modules {
- core init timer vfs.lib.so ld.lib.so libm.lib.so libc.lib.so stdcxx.lib.so posix.lib.so blinktree fill_randint_workloada mixed_randint_workloada
+ core init timer vfs.lib.so ld.lib.so libm.lib.so libc.lib.so stdcxx.lib.so hoitaja blinktree fill_randint_workloada mixed_randint_workloada
}
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args "-nographic"
+
run_genode_until forever
+
+set rounds 100
+set succeeded 0
+
+for {set r 0} {$r < $rounds} {incr r} {
+ run_genode_until {\[init -> hoitaja -> blinktree1\] Finished\.} 300
+ kill_spawned [output_spawn_id]
+ incr succeeded
+}
+
+puts "$succeeded of $rounds rounds succeeded."
+
diff --git a/repos/mml/run/blinktree_server.run b/repos/mml/run/blinktree_server.run
new file mode 100644
index 0000000000..a9b4801d4f
--- /dev/null
+++ b/repos/mml/run/blinktree_server.run
@@ -0,0 +1,175 @@
+set build_components {
+ core init timer app/blinktree_server hoitaja server/nic_router
+}
+
+
+create_boot_directory
+import_from_depot [depot_user]/pkg/[drivers_nic_pkg] \
+
+build $build_components
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+ install_config $config
+
+ build_boot_image { core init timer ld.lib.so libm.lib.so libc.lib.so stdcxx.lib.so vfs.lib.so blinktree_daemon hoitaja nic_router }
+
+ append qemu_args "-nographic"
+ append_qemu_nic_args "host=10.0.2.1,dhcpstart=10.0.2.55,hostfwd=tcp::12345-:12345,hostfwd=tcp::18080-:12345,hostfwd=udp::10007-:7,hostfwd=udp::17070-:7070"
+
+ run_genode_until forever
+
+ set rounds 100
+ set succeeded 0
+
+ for {set r 0} {$r < $rounds} {incr r} {
+ run_genode_until {\[init -> hoitaja -> blinktree1\] Finished\.} 300
+ kill_spawned [output_spawn_id]
+ incr succeeded
+ }
+
+ puts "$succeeded of $rounds rounds succeeded."
+
diff --git a/repos/mml/run/blinktree_with_antagonist.run b/repos/mml/run/blinktree_with_antagonist.run
new file mode 100644
index 0000000000..867d285940
--- /dev/null
+++ b/repos/mml/run/blinktree_with_antagonist.run
@@ -0,0 +1,136 @@
+set build_components {
+ core init timer app/blinktree app/antagonist hoitaja
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+build $build_components
+
+create_boot_directory
+
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+set boot_modules {
+ core init timer vfs.lib.so ld.lib.so libm.lib.so libc.lib.so stdcxx.lib.so hoitaja blinktree stress_genode fill_randint_workloada mixed_randint_workloada
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic"
+
+run_genode_until forever
+
+set rounds 100
+set succeeded 0
+
+for {set r 0} {$r < $rounds} {incr r} {
+ run_genode_until {\[init -> hoitaja -> blinktree1\] Finished\.} 300
+ kill_spawned [output_spawn_id]
+ incr succeeded
+}
+
+puts "$succeeded of $rounds rounds succeeded."
+
diff --git a/repos/mml/run/hello_mxtask.run b/repos/mml/run/hello_mxtask.run
index de73b12439..39730e2cd0 100644
--- a/repos/mml/run/hello_mxtask.run
+++ b/repos/mml/run/hello_mxtask.run
@@ -1,5 +1,5 @@
set build_components {
- core init timer app/hello_mxtask
+ core init timer hoitaja app/hello_mxtask
}
source ${genode_dir}/repos/base/run/platform_drv.inc
@@ -19,14 +19,18 @@ set config {
+
+
+
+
-
+
@@ -34,20 +38,50 @@ set config {
}
-append_platform_drv_config
-
append config {
-
-
-
-
-
- 2022-07-20 14:30
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
}
@@ -55,11 +89,11 @@ append config {
install_config $config
set boot_modules {
- core init timer vfs.lib.so libm.lib.so libc.lib.so stdcxx.lib.so ld.lib.so hello_mxtask
+ core init timer vfs.lib.so libm.lib.so libc.lib.so stdcxx.lib.so ld.lib.so hello_mxtask hoitaja
}
append_platform_drv_boot_modules
build_boot_image $boot_modules
-append qemu_args "-nographic -m 64"
+append qemu_args "-nographic"
run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/hoitaja_example.run b/repos/mml/run/hoitaja_example.run
new file mode 100644
index 0000000000..1b28a90a51
--- /dev/null
+++ b/repos/mml/run/hoitaja_example.run
@@ -0,0 +1,114 @@
+set build_components {
+ core init hoitaja timer app/persistent_cell app/volatile_cell
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+ install_config $config
+
+ set boot_modules {
+ core init hoitaja timer vfs.lib.so ld.lib.so persistent_cell volatile_cell
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/hpc_test.run b/repos/mml/run/hpc_test.run
new file mode 100644
index 0000000000..11e9f26d63
--- /dev/null
+++ b/repos/mml/run/hpc_test.run
@@ -0,0 +1,80 @@
+set build_components {
+ core init timer app/hpc_test
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append config {
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+set boot_modules {
+ core init timer vfs.lib.so ld.lib.so posix.lib.so libc.lib.so libm.lib.so stdcxx.lib.so hpc_test
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/libpfm_test.run b/repos/mml/run/libpfm_test.run
new file mode 100644
index 0000000000..12d1aec044
--- /dev/null
+++ b/repos/mml/run/libpfm_test.run
@@ -0,0 +1,68 @@
+set build_components {
+ core init timer app/libpfm_test
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append config {
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+set boot_modules {
+ core init timer vfs.lib.so ld.lib.so posix.lib.so libc.lib.so libm.lib.so stdcxx.lib.so libpfm_test
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/livedemo.run b/repos/mml/run/livedemo.run
new file mode 100644
index 0000000000..5e0aa96dd9
--- /dev/null
+++ b/repos/mml/run/livedemo.run
@@ -0,0 +1,116 @@
+set build_components {
+ core init timer app/blinktree
+}
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+set boot_modules {
+ core init timer vfs.lib.so ld.lib.so libm.lib.so libc.lib.so stdcxx.lib.so posix.lib.so blinktree fill_randint_workloada mixed_randint_workloada
+}
+
+build_boot_image $boot_modules
+append qemu_args "-nographic"
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/loopbench.run b/repos/mml/run/loopbench.run
new file mode 100644
index 0000000000..0186cdb92a
--- /dev/null
+++ b/repos/mml/run/loopbench.run
@@ -0,0 +1,108 @@
+set build_components {
+ core init timer hoitaja app/loopbench app/volatile_cell
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+append config {
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+set boot_modules {
+ core init timer vfs.lib.so libm.lib.so libc.lib.so stdcxx.lib.so ld.lib.so hoitaja loopbench volatile_cell
+}
+
+append_platform_drv_boot_modules
+build_boot_image $boot_modules
+append qemu_args "-nographic"
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/pfm_test.run b/repos/mml/run/pfm_test.run
new file mode 100644
index 0000000000..b82a4adedb
--- /dev/null
+++ b/repos/mml/run/pfm_test.run
@@ -0,0 +1,68 @@
+set build_components {
+ core init timer app/pfm_test
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append config {
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+set boot_modules {
+ core init timer vfs.lib.so ld.lib.so posix.lib.so libc.lib.so libm.lib.so stdcxx.lib.so pfm_test
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/portal_experiment.run b/repos/mml/run/portal_experiment.run
new file mode 100644
index 0000000000..b0b786cdcf
--- /dev/null
+++ b/repos/mml/run/portal_experiment.run
@@ -0,0 +1,141 @@
+set build_components {
+ core init hoitaja timer app/portal_experiment app/volatile_cell
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+build $build_components
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2022-07-20 14:30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+set boot_modules {
+ core init hoitaja timer vfs.lib.so libm.lib.so libc.lib.so stdcxx.lib.so ld.lib.so portal_experiment volatile_cell
+}
+build_boot_image $boot_modules
+append qemu_args "-nographic"
+run_genode_until forever
diff --git a/repos/mml/run/raw_nic.run b/repos/mml/run/raw_nic.run
new file mode 100644
index 0000000000..f2c730a1ea
--- /dev/null
+++ b/repos/mml/run/raw_nic.run
@@ -0,0 +1,124 @@
+create_boot_directory
+import_from_depot [depot_user]/src/[base_src] \
+ [depot_user]/pkg/[drivers_nic_pkg] \
+ [depot_user]/src/init \
+ [depot_user]/src/libc \
+ [depot_user]/src/stdcxx \
+ [depot_user]/src/nic_router \
+ [depot_user]/src/vfs_audit \
+ [depot_user]/src/vfs
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+append qemu_args " -nographic "
+append_qemu_nic_args "host=10.0.2.1,dhcpstart=10.0.2.55,hostfwd=tcp::10080-:80,hostfwd=tcp::18080-:8080,hostfwd=udp::10007-:7,hostfwd=udp::17070-:7070"
+
+build { app/raw_nic app/ping }
+
+install_config $config
+build_boot_image { raw_nic ping }
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/resource_yield.run b/repos/mml/run/resource_yield.run
new file mode 100644
index 0000000000..f210d87341
--- /dev/null
+++ b/repos/mml/run/resource_yield.run
@@ -0,0 +1,114 @@
+set build_components {
+ core init hoitaja timer app/yield_bench
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+ install_config $config
+
+ set boot_modules {
+ core init hoitaja timer vfs.lib.so ld.lib.so benchmark_resource_yield
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/suoritin_tester.run b/repos/mml/run/suoritin_tester.run
new file mode 100644
index 0000000000..2bf13a2c10
--- /dev/null
+++ b/repos/mml/run/suoritin_tester.run
@@ -0,0 +1,94 @@
+set build_components {
+ core init hoitaja timer app/suoritin_test
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+build $build_components
+
+create_boot_directory
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+ install_config $config
+
+ set boot_modules {
+ core init hoitaja timer vfs.lib.so ld.lib.so suoritin_tester
+}
+
+append_platform_drv_boot_modules
+
+build_boot_image $boot_modules
+append qemu_args "-nographic "
+
+run_genode_until forever
\ No newline at end of file
diff --git a/repos/mml/run/thread_test.run b/repos/mml/run/thread_test.run
index 05aec30223..e1a38d50fa 100644
--- a/repos/mml/run/thread_test.run
+++ b/repos/mml/run/thread_test.run
@@ -15,10 +15,12 @@ install_config {
+
+
@@ -29,6 +31,7 @@ install_config {
+
@@ -40,4 +43,5 @@ set boot_modules {
core init timer vfs.lib.so ld.lib.so libm.lib.so libc.lib.so stdcxx.lib.so thread_test
}
build_boot_image $boot_modules
-append qemu_args "-nographic -m 64"
+append qemu_args "-nographic"
+run_genode_until forever
diff --git a/repos/mml/run/vscode.run b/repos/mml/run/vscode.run
new file mode 100644
index 0000000000..c4b62c9b4b
--- /dev/null
+++ b/repos/mml/run/vscode.run
@@ -0,0 +1,12 @@
+set build_components {
+ core init timer hoitaja app/blinktree app/hello_mxtask app/hpc_test app/yield_bench app/persistent_cell app/volatile_cell test/resource_yield app/grant_bench app/top app/cpu_burner app/lwip_raw app/blinktree_server
+}
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+build $build_components
+
+create_boot_directory
+
+
+
diff --git a/repos/mml/src/app/antagonist/cpu.h b/repos/mml/src/app/antagonist/cpu.h
new file mode 100644
index 0000000000..1acf27c13d
--- /dev/null
+++ b/repos/mml/src/app/antagonist/cpu.h
@@ -0,0 +1,26 @@
+/*
+ * cpu.h - basic definitions for x86_64 CPUs
+ */
+
+#pragma once
+
+/*
+ * Endianness
+ */
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+
+/*
+ * Word Size
+ */
+
+#define __32BIT_WORDS 32
+#define __64BIT_WORDS 64
+
+#define __WORD_SIZE __64BIT_WORDS
+
+#define CACHE_LINE_SIZE 64
diff --git a/repos/mml/src/app/antagonist/main.cc b/repos/mml/src/app/antagonist/main.cc
new file mode 100644
index 0000000000..a5562a9759
--- /dev/null
+++ b/repos/mml/src/app/antagonist/main.cc
@@ -0,0 +1,254 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CALLS 100
+#define CORES 14
+#define HYPERCALL
+
+ //Genode::Trace::timestamp();
+static Genode::Trace::Timestamp rdtsc_cost = 0;
+Genode::Env *genv = nullptr;
+static Genode::Trace::Timestamp start = 0;
+static const unsigned long loops = 10000UL;
+static Nova::mword_t channel = 0;
+static std::atomic counter(0);
+static std::atomic ready{false};
+static std::atomic restart{true};
+static std::atomic yield_ctr{-(31-CORES)};
+static unsigned long tsc_freq_khz = 0;
+int cores, i;
+
+struct Channel {
+ unsigned long yield_flag : 1,
+ op : 2,
+ tnum : 61;
+ unsigned long delta_alloc;
+ unsigned long delta_activate;
+ unsigned long delta_setflag;
+ unsigned long delta_findborrower;
+ unsigned long delta_block;
+ unsigned long delta_enter;
+ unsigned long delta_return;
+};
+
+struct Cell : public Genode::Thread
+{
+ Genode::uint16_t _id;
+ Libc::Env &env;
+ Timer::Connection &_timer;
+
+ static void *pthread_entry(void *args) {
+ Cell *cell = reinterpret_cast| (args);
+ cell->entry();
+ return nullptr;
+ }
+
+ void entry() override
+ {
+ Genode::Trace::Timestamp latency = 0;
+ Nova::mword_t channel_id = 0;
+ Nova::uint64_t count_allocs = 0;
+ Nova::cpu_id(channel_id);
+ struct Channel *channels = reinterpret_cast(channel);
+ struct Channel volatile *my_channel = &channels[channel_id];
+
+ unsigned long _tsc_freq_ghz = tsc_freq_khz / 1000000UL;
+
+ //Genode::log("Started worker", _id, " on CPU with affinity ", channel_id, Genode::Thread::myself()->affinity(), " signal channel: ", my_channel->yield_flag, " at ", my_channel);
+
+ for (cores = CORES; cores <= 14; cores+=4) {
+ for (i = 0; i < CALLS; ) {
+
+ if ((i == 0 && yield_ctr >= cores-1) || (i > 0 && yield_ctr >= cores-1))
+ ready = true;
+
+ if (_id != 0 && restart.load()) {
+ yield_ctr.fetch_add(1);
+ // Genode::log("Worker ", _id, "yielded, yield_ctr = ", yield_ctr.load());
+ Nova::yield();
+ }
+
+ //Genode::log("Worker ", _id, " on CPU ", channel_id, " woke up");
+ counter.fetch_add(1);
+ if (counter >= cores-1) {
+ ready = true;
+ // Genode::log("{\"allocation:\": ", allocation, ", \"id\":", _id, ",\"clk_total\":", (end-::start), ", \"mean_clk\":", (end-::start)/count_allocs ,", \"count\": ", count_allocs, "\"channel-id\":", channel_id, "},");
+ }
+
+ if (my_channel->op == 2) {
+ Nova::mword_t allocation = 0;
+ Genode::Trace::Timestamp now = Genode::Trace::timestamp();
+ Nova::core_allocation(allocation);
+ my_channel->delta_return = now - my_channel->delta_return;
+ Genode::log("{\"iteration\": ", i, ", \"cores\":", cores, ", \"d_block\": ", my_channel->delta_block / _tsc_freq_ghz, ", \"d_enter\":", my_channel->delta_enter / _tsc_freq_ghz, ", \"d_return\":", my_channel->delta_return / _tsc_freq_ghz, ", \"op\": \"yield\"},");
+ }
+ my_channel->op = 0;
+ if (_id == 0) {
+ //Genode::log("Waiting on start signal");
+ while (ready.load() == false)
+ __builtin_ia32_pause();
+
+ //Genode::log("Got start signal");
+ _timer.msleep(2);
+
+ //Genode::log("Woke up for new iteration");
+ ready = false;
+ restart = false;
+ ::start = Genode::Trace::timestamp();
+ }
+
+ Genode::Trace::Timestamp end = 0;
+ while (_id==0)
+ {
+
+ if (_id == 0) {
+ Nova::mword_t allocated = 0;
+ //Genode::log("Allocating 4 cores");
+
+ my_channel->tnum = i;
+ my_channel->op = 1; /* 1 for alloc, 2 for yield */
+
+ my_channel->delta_enter = Genode::Trace::timestamp();
+ Nova::uint8_t rc = Nova::alloc_cores(cores, allocated);
+ if (rc == Nova::NOVA_OK)
+ {
+
+ while(ready.load() == false)
+ __builtin_ia32_pause();
+ end = Genode::Trace::timestamp();
+ my_channel->delta_return = end - my_channel->delta_return;
+ latency += (end - ::start) / _tsc_freq_ghz;
+ Nova::mword_t allocation = 0;
+ Genode::log("{\"iteration\": ", i, ", \"cores\":", cores, ", \"delta_enter:\" ", my_channel->delta_enter / _tsc_freq_ghz, ", \"delta_alloc\": ", my_channel->delta_alloc / _tsc_freq_ghz, ", \"delta_activate:\": ", my_channel->delta_activate / _tsc_freq_ghz, ", \"delta_setflag\": ", my_channel->delta_setflag / _tsc_freq_ghz, ", \"delta_return\": ", my_channel->delta_return / _tsc_freq_ghz, "},");
+ Nova::core_allocation(allocation);
+ restart = true;
+ counter = 0;
+ yield_ctr = 0;
+ //if (i%100==0) {
+
+ Genode::log("{\"iteration\": ", i, ", \"cores\":", cores, ", \"allocation\": ", allocation, ",\"start\": ", ::start, ", \"end\": ", end, " ,\"ns\": ", (latency), "},");
+ my_channel->delta_setflag = 0;
+ latency = 0;
+ //}
+ i++;
+ break;
+ } else {
+ //Genode::log("cores allocated: ", allocated);
+ break;
+ // Genode::log("cores allocated: ", allocated);
+ }
+ count_allocs++;
+ }
+ }
+ //Genode::log("Finished allocation. Waiting for yield signal, id = ", channel_id, "\n");
+ while (restart.load() == false) {
+ Channel volatile *res = __atomic_load_n(&my_channel, __ATOMIC_SEQ_CST);
+ if (res->yield_flag) {
+ Genode::log("Got yield signal on channel ", channel_id);
+ Nova::yield(true);
+ }
+ }
+ }
+ }
+ Genode::log("Benchmak finished.");
+ }
+ Cell(Libc::Env &env, Timer::Connection &timer, Genode::uint16_t id, Location const &location)
+ : Thread(env, Name("test_", location.xpos(), "x", location.ypos()), 4 * 4096, location, Weight(), env.cpu()), _id(id), env(env), _timer(timer)
+ { }
+};
+
+
+void Libc::Component::construct(Libc::Env &env)
+{
+ Nova::uint8_t res = 0;
+ genv = &env;
+
+ Libc::with_libc([&]()
+ {
+ Timer::Connection _timer{env};
+
+ Genode::Ram_dataspace_capability ds = env.ram().alloc(4096);
+ channel = env.rm().attach(ds);
+
+ Genode::memset(reinterpret_cast(channel), 0, 4096);
+
+ //Genode::Heap _heap{env.ram(), env.rm()};
+
+ //Genode::log("Registering MxTasking entrypoint");
+ if ((res = Nova::mxinit(0, 0, channel))) {
+ Genode::error("Failed to init MxTasking: ", res);
+ }
+ Genode::log("Registered MxTasking, yielding ...");
+
+ try {
+ Genode::Attached_rom_dataspace info(env, "platform_info");
+ tsc_freq_khz = info.xml().sub_node("hardware").sub_node("tsc")
+ .attribute_value("freq_khz", 0ULL);
+ } catch (...) { };
+
+ start = Genode::Trace::timestamp();
+ for (unsigned c = 0; c < 1000; c++) {
+ //Genode::Trace::Timestamp start = Genode::Trace::timestamp();
+
+ /*Nova::uint8_t rc = Nova::yield();
+ if (rc != Nova::NOVA_OK)
+ break;*/
+ Genode::Trace::timestamp();
+ // Genode::Trace::Timestamp end = Genode::Trace::timestamp();
+ // delay += (end - start);
+ }
+ Genode::Trace::Timestamp end = Genode::Trace::timestamp();
+ rdtsc_cost = (end - start) / 1000 / 2;
+
+ Genode::log("My affinity is ", env.cpu().affinity_space(), " of size ", env.cpu().affinity_space().total());
+ Genode::log("Will create workers for affinity space: ", env.topo().global_affinity_space());
+ start = Genode::Trace::timestamp();
+ Genode::Thread *me = Genode::Thread::myself();
+
+ unsigned long cpuid = 0;
+ Nova::cpu_id(cpuid);
+
+ Genode::Affinity::Space space = env.topo().global_affinity_space();
+ Genode::log("My main thread is on phys. CPU ", cpuid);
+
+ pthread_t workers[space.total()];
+ std::cout << "Creating workers" << std::endl;
+ Genode::Trace::Timestamp thread_start = Genode::Trace::timestamp();
+ for (Genode::uint16_t cpu = 1; cpu < space.total(); cpu++)
+ {
+ Genode::String<32> const name{"worker", cpu};
+ if (cpu == (space.total() - cpuid))
+ continue;
+ Cell *worker = new Cell(env, _timer, cpu, space.location_of_index(cpu));
+ Libc::pthread_create_from_session(&workers[cpu], Cell::pthread_entry, worker, 4 * 4096, name.string(), &env.cpu(), space.location_of_index(cpu));
+ // Genode::log("Created worker for CPU ", cpu);
+ // worker->start();
+ }
+ Genode::Trace::Timestamp thread_stop = Genode::Trace::timestamp();
+ Genode::log("Took ", (thread_stop - thread_start) / 2000, " μs to start workers");
+
+ pthread_t main_pt{};
+
+ Genode::Affinity::Location loc = me->affinity();
+ //Genode::log("Starting main worker on CPU ", cpuid);
+ Cell *main_cell = new Cell(env, _timer, 0, loc);
+
+ //Cell *main = new (_heap) Cell(env, 0, Genode::Affinity::Location(20,0));
+ /*Libc::pthread_create_from_thread(&main_pt, *main, &main);
+ main->start();*/
+ // Nova::yield(false);
+ //_timer.msleep(10000);
+ Libc::pthread_create_from_session(&main_pt, Cell::pthread_entry, main_cell, 8 * 4096, "main_worker", &env.cpu(), loc);
+ pthread_join(main_pt, 0); });
+ Genode::log("Leaving component");
+}
\ No newline at end of file
diff --git a/repos/mml/src/app/antagonist/mem.h b/repos/mml/src/app/antagonist/mem.h
new file mode 100644
index 0000000000..dc0fa8ac46
--- /dev/null
+++ b/repos/mml/src/app/antagonist/mem.h
@@ -0,0 +1,61 @@
+/*
+ * mem.h - memory management
+ */
+
+#pragma once
+
+#include "types.h"
+
+enum {
+ PGSHIFT_4KB = 12,
+ PGSHIFT_2MB = 21,
+ PGSHIFT_1GB = 30,
+};
+
+enum {
+ PGSIZE_4KB = (1 << PGSHIFT_4KB), /* 4096 bytes */
+ PGSIZE_2MB = (1 << PGSHIFT_2MB), /* 2097152 bytes */
+ PGSIZE_1GB = (1 << PGSHIFT_1GB), /* 1073741824 bytes */
+};
+
+#define PGMASK_4KB (PGSIZE_4KB - 1)
+#define PGMASK_2MB (PGSIZE_2MB - 1)
+#define PGMASK_1GB (PGSIZE_1GB - 1)
+
+/* page numbers */
+#define PGN_4KB(la) (((uintptr_t)(la)) >> PGSHIFT_4KB)
+#define PGN_2MB(la) (((uintptr_t)(la)) >> PGSHIFT_2MB)
+#define PGN_1GB(la) (((uintptr_t)(la)) >> PGSHIFT_1GB)
+
+#define PGOFF_4KB(la) (((uintptr_t)(la)) & PGMASK_4KB)
+#define PGOFF_2MB(la) (((uintptr_t)(la)) & PGMASK_2MB)
+#define PGOFF_1GB(la) (((uintptr_t)(la)) & PGMASK_1GB)
+
+#define PGADDR_4KB(la) (((uintptr_t)(la)) & ~((uintptr_t)PGMASK_4KB))
+#define PGADDR_2MB(la) (((uintptr_t)(la)) & ~((uintptr_t)PGMASK_2MB))
+#define PGADDR_1GB(la) (((uintptr_t)(la)) & ~((uintptr_t)PGMASK_1GB))
+
+typedef unsigned long physaddr_t; /* physical addresses */
+typedef unsigned long virtaddr_t; /* virtual addresses */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+typedef unsigned int mem_key_t;
+
+extern void *mem_map_anom(void *base, size_t len, size_t pgsize, int node);
+extern void *mem_map_file(void *base, size_t len, int fd, off_t offset);
+extern void *mem_map_shm(mem_key_t key, void *base, size_t len,
+ size_t pgsize, bool exclusive);
+extern void *mem_map_shm_rdonly(mem_key_t key, void *base, size_t len,
+ size_t pgsize);
+extern int mem_unmap_shm(void *base);
+extern int mem_lookup_page_phys_addrs(void *addr, size_t len, size_t pgsize,
+ physaddr_t *maddrs);
+
+static inline int
+mem_lookup_page_phys_addr(void *addr, size_t pgsize, physaddr_t *paddr)
+{
+ return mem_lookup_page_phys_addrs(addr, pgsize, pgsize, paddr);
+}
diff --git a/repos/mml/src/app/antagonist/stress_linux.cc b/repos/mml/src/app/antagonist/stress_linux.cc
new file mode 100644
index 0000000000..2ad780b7a5
--- /dev/null
+++ b/repos/mml/src/app/antagonist/stress_linux.cc
@@ -0,0 +1,145 @@
+
+#include "synthetic_worker.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+namespace
+{
+
+ int threads;
+ uint64_t n;
+ std::string worker_spec;
+
+ class SyntheticWork : public mx::tasking::TaskInterface
+ {
+ private:
+ SyntheticWorker *_w{nullptr};
+ uint64_t *_cnt;
+
+ public:
+ SyntheticWork(SyntheticWorker *w, uint64_t *cnt) : _w(w), _cnt(cnt) {}
+ ~SyntheticWork() override = default;
+
+ mx::tasking::TaskResult execute(const std::uint16_t , const std::uint16_t) override
+ {
+ _w->Work(n);
+ (*_cnt)++;
+ //mx::tasking::runtime::scheduler().allocate_cores(64);
+ return mx::tasking::TaskResult::make_succeed(this);
+ }
+ };
+
+ void
+ MainHandler(void *arg)
+ {
+ std::vector cnt(threads);
+
+ auto cores = mx::util::core_set::build(threads);
+ std::cout << "Core set to use: " << cores << std::endl;
+ mx::tasking::runtime::init(cores, 0, false);
+
+ for (int i = 0; i < threads; ++i)
+ {
+ Genode::log("Creating synthetic worker ", i);
+ auto *w = SyntheticWorkerFactory(worker_spec);
+ if (w == nullptr) {
+ std::cerr << "Failed to create worker." << std::endl;
+ exit(1);
+ }
+ auto *work = mx::tasking::runtime::new_task(i, w, &cnt[i]);
+ work->annotate(static_cast(i));
+ mx::tasking::runtime::spawn(*work, mx::system::topology::core_id());
+ }
+
+ auto monitor = std::thread([&]()
+ {
+ uint64_t last_total = 0;
+ auto last = std::chrono::steady_clock::now();
+ while (1) {
+ std::chrono::seconds sec(1);
+ std::this_thread::sleep_for(sec);
+ auto now = std::chrono::steady_clock::now();
+ uint64_t total = 0;
+ double duration =
+ std::chrono::duration_cast>(now - last)
+ .count();
+ for (int i = 0; i < threads; i++) total += cnt[i];
+ std::cerr << static_cast(total - last_total) / duration
+ << std::endl;
+ last_total = total;
+ last = now;
+ } });
+ mx::tasking::runtime::start_and_wait();
+ monitor.join();
+
+ // never returns
+ }
+
+} // anonymous namespace
+
+void PrintUsage()
+{
+ std::cerr << "usage: [#threads] [#n] [worker_spec] "
+ << std::endl;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ if (argc < 4)
+ {
+ PrintUsage();
+ return -EINVAL;
+ }
+
+ threads = std::stoi(argv[1], nullptr, 0);
+ n = std::stoul(argv[2], nullptr, 0);
+ worker_spec = std::string(argv[3]);
+
+ // ret = base_init();
+ if (ret)
+ return ret;
+
+ // ret = base_init_thread();
+ if (ret)
+ return ret;
+
+ MainHandler(NULL);
+
+ return 0;
+}
+
+void Libc::Component::construct(Libc::Env &env) {
+
+ mx::system::Environment::set_env(&env);
+
+ auto sys_cores = mx::util::core_set::build(64);
+ mx::system::Environment::set_cores(&sys_cores);
+
+ mx::memory::GlobalHeap::myself();
+ std::uint16_t cores = 64;
+ //env.cpu().affinity_space().total();
+
+ char cores_arg[10];
+ sprintf(cores_arg, "%d", cores);
+
+ char *args[] = {"stress_genode", cores_arg, "1", "cacheantagonist:4090880"};
+
+ Libc::with_libc([&]()
+ {
+ std::cout << "Starting Cache Antagonist" << std::endl;
+ main(4, args);
+ });
+}
\ No newline at end of file
diff --git a/repos/mml/src/app/antagonist/synthetic_worker.cc b/repos/mml/src/app/antagonist/synthetic_worker.cc
new file mode 100644
index 0000000000..1d3921c4d6
--- /dev/null
+++ b/repos/mml/src/app/antagonist/synthetic_worker.cc
@@ -0,0 +1,315 @@
+// synthetic_worker.cc - support for generation of synthetic work
+
+extern "C"
+{
+ #include "mem.h"
+#include
+#include
+}
+
+#include "synthetic_worker.h"
+#include "util.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+bool synth_barrier_wait() { }
+
+namespace
+{
+
+ void *memcpy_ermsb(void *dst, const void *src, size_t n)
+ {
+ asm volatile("rep movsb" : "+D"(dst), "+S"(src), "+c"(n)::"memory");
+ return dst;
+ }
+
+ inline void clflush(volatile void *p) { asm volatile("clflush (%0)" ::"r"(p)); }
+
+ // Store data (indicated by the param c) to the cache line using the
+ // non-temporal store.
+ inline void nt_cacheline_store(char *p, int c)
+ {
+ /*__m128i i = _mm_set_epi8(c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c);
+ _mm_stream_si128((__m128i *)&p[0], i);
+ _mm_stream_si128((__m128i *)&p[16], i);
+ _mm_stream_si128((__m128i *)&p[32], i);
+ _mm_stream_si128((__m128i *)&p[48], i);*/
+ }
+
+} // anonymous namespace
+
+void SqrtWorker::Work(uint64_t n)
+{
+ constexpr double kNumber = 2350845.545;
+ for (uint64_t i = 0; i < n; ++i)
+ {
+ volatile double v = sqrt(i * kNumber);
+ std::ignore = v; // silences compiler warning
+ }
+}
+
+#define SQRT(src_var, dest_var, src_xmm, dest_xmm) \
+ asm volatile("movq %1, %%" src_xmm \
+ "\n" \
+ "sqrtsd %%" src_xmm ", %%" dest_xmm \
+ "\n" \
+ "movq %%" dest_xmm ", %0 \n" \
+ : "=r"(dest_var) \
+ : "g"(src_var) \
+ : src_xmm, dest_xmm, "memory")
+
+void AsmSqrtWorker::Work(uint64_t n)
+{
+ constexpr double kNumber = 2350845.545;
+ double src_0, src_1, src_2, src_3;
+ double dest_0, dest_1, dest_2, dest_3;
+ for (uint64_t i = 0; i < n; i += 4)
+ {
+ src_0 = i * kNumber;
+ src_1 = (i + 1) * kNumber;
+ src_2 = (i + 2) * kNumber;
+ src_3 = (i + 3) * kNumber;
+ SQRT(src_0, dest_0, "xmm0", "xmm1");
+ SQRT(src_1, dest_1, "xmm2", "xmm3");
+ SQRT(src_2, dest_2, "xmm4", "xmm5");
+ SQRT(src_3, dest_3, "xmm6", "xmm7");
+ }
+}
+
+StridedMemtouchWorker *StridedMemtouchWorker::Create(std::size_t size,
+ std::size_t stride)
+{
+ char *buf = new char[size]();
+ return new StridedMemtouchWorker(buf, size, stride);
+}
+
+void StridedMemtouchWorker::Work(uint64_t n)
+{
+ for (uint64_t i = 0; i < n; ++i)
+ {
+ volatile char c = buf_[(stride_ * i) % size_];
+ std::ignore = c; // silences compiler warning
+ }
+}
+
+/* TODO: MemStreamWorker is currently broken as clang lacks the intrinsics needed */
+MemStreamWorker *MemStreamWorker::Create(std::size_t size)
+{
+ void *addr;
+ int prot, flags;
+
+ prot = PROT_READ | PROT_WRITE;
+ flags = MAP_PRIVATE | MAP_ANONYMOUS;
+ // | MAP_POPULATE | MAP_HUGETLB |
+ // (PGSHIFT_2MB << MAP_HUGE_SHIFT);
+
+ addr = mmap(NULL, size, prot, flags, -1, 0);
+ if (addr == MAP_FAILED)
+ return nullptr;
+
+ memset(addr, 0xAB, size);
+ return new MemStreamWorker(static_cast(addr), size);
+}
+
+MemStreamWorker::~MemStreamWorker()
+{
+ munmap((void *)buf_, (size_));
+}
+
+void MemStreamWorker::Work(uint64_t n)
+{
+ if (n > size_)
+ n = size_;
+ for (uint64_t i = 0; i < n; ++i)
+ {
+ volatile char c = buf_[i];
+ std::ignore = c; // silences compiler warning
+ }
+}
+
+RandomMemtouchWorker *RandomMemtouchWorker::Create(std::size_t size,
+ unsigned int seed)
+{
+ char *buf = new char[size]();
+ std::vector v(size);
+ std::iota(std::begin(v), std::end(v), 0);
+ std::mt19937 g(seed);
+ std::shuffle(v.begin(), v.end(), g);
+ return new RandomMemtouchWorker(buf, std::move(v));
+}
+
+void RandomMemtouchWorker::Work(uint64_t n)
+{
+ for (uint64_t i = 0; i < n; ++i)
+ buf_[schedule_[i % schedule_.size()]]++;
+}
+
+CacheAntagonistWorker *CacheAntagonistWorker::Create(std::size_t size)
+{
+ char *buf = new char[size]();
+ return new CacheAntagonistWorker(buf, size);
+}
+
+void CacheAntagonistWorker::Work(uint64_t n)
+{
+ for (uint64_t i = 0; i < n; ++i)
+ memcpy_ermsb(&buf_[0], &buf_[size_ / 2], size_ / 2);
+}
+
+MemBWAntagonistWorker *MemBWAntagonistWorker::Create(std::size_t size,
+ int nop_period,
+ int nop_num)
+{
+ // non-temporal store won't bypass cache when accessing the remote memory.
+ auto numa_id = mx::system::topology::node_id(mx::system::topology::core_id());
+ char *buf = reinterpret_cast(mx::memory::GlobalHeap::allocate(numa_id, size));
+ // numa_alloc_* will allocate memory in pages, therefore it must be cacheline
+ // aligned.
+ if (reinterpret_cast(buf) % CACHELINE_SIZE != 0)
+ {
+ // Should never be executed.
+ Genode::error("The allocated memory should be cacheline size aligned.");
+ return nullptr;
+ }
+ // Flush the cache explicitly. Non-temporal store will still write into cache
+ // if the corresponding data is already at cache.
+ for (std::size_t i = 0; i < size; i += CACHELINE_SIZE)
+ {
+ clflush(reinterpret_cast(buf + i));
+ }
+ return new MemBWAntagonistWorker(buf, size, nop_period, nop_num);
+}
+
+void MemBWAntagonistWorker::Work(uint64_t n)
+{
+ int cnt = 0;
+ for (uint64_t k = 0; k < n; k++)
+ {
+ for (std::size_t i = 0; i < size_; i += CACHELINE_SIZE)
+ {
+ nt_cacheline_store(buf_ + i, 0);
+ if (cnt++ == nop_period_)
+ {
+ cnt = 0;
+ for (int j = 0; j < nop_num_; j++)
+ {
+ asm("");
+ }
+ }
+ }
+ }
+}
+
+DynamicCacheAntagonistWorker *DynamicCacheAntagonistWorker::Create(
+ std::size_t size, int period, int nop_num)
+{
+ char *buf = new char[size]();
+ return new DynamicCacheAntagonistWorker(buf, size, period, nop_num);
+}
+
+void DynamicCacheAntagonistWorker::Work(uint64_t n)
+{
+ double *ptr = reinterpret_cast(buf_);
+ size_t offset = size_ / 2 / sizeof(double);
+ for (uint64_t i = 0; i < n; ++i)
+ {
+ for (size_t j = 0; j < offset; j++)
+ {
+ ptr[j + offset] = ptr[j];
+ if (cnt_++ == period_)
+ {
+ //synth_barrier_wait();
+ cnt_ = 0;
+ for (int k = 0; k < nop_num_; k++)
+ {
+ asm("");
+ }
+ }
+ }
+ }
+}
+
+SyntheticWorker *SyntheticWorkerFactory(std::string s)
+{
+ std::vector tokens = split(s, ':');
+
+ // the first token is the type of worker, must be specified
+ if (tokens.size() < 1)
+ return nullptr;
+
+ if (tokens[0] == "sqrt")
+ {
+ if (tokens.size() != 1)
+ return nullptr;
+ return new SqrtWorker();
+ }
+ else if (tokens[0] == "asmsqrt")
+ {
+ if (tokens.size() != 1)
+ return nullptr;
+ return new AsmSqrtWorker();
+ }
+ else if (tokens[0] == "stridedmem")
+ {
+ if (tokens.size() != 3)
+ return nullptr;
+ unsigned long size = std::stoul(tokens[1], nullptr, 0);
+ unsigned long stride = std::stoul(tokens[2], nullptr, 0);
+ return StridedMemtouchWorker::Create(size, stride);
+ }
+ else if (tokens[0] == "randmem")
+ {
+ if (tokens.size() != 3)
+ return nullptr;
+ unsigned long size = std::stoul(tokens[1], nullptr, 0);
+ unsigned long seed = std::stoul(tokens[2], nullptr, 0);
+ if (seed > std::numeric_limits::max())
+ return nullptr;
+ return RandomMemtouchWorker::Create(size, seed);
+ }
+ else if (tokens[0] == "memstream")
+ {
+ if (tokens.size() != 2)
+ return nullptr;
+ unsigned long size = std::stoul(tokens[1], nullptr, 0);
+ return MemStreamWorker::Create(size);
+ }
+ else if (tokens[0] == "cacheantagonist")
+ {
+ if (tokens.size() != 2)
+ return nullptr;
+ unsigned long size = std::stoul(tokens[1], nullptr, 0);
+ return CacheAntagonistWorker::Create(size);
+ }
+ else if (tokens[0] == "membwantagonist")
+ {
+ if (tokens.size() != 4)
+ return nullptr;
+ unsigned long size = std::stoul(tokens[1], nullptr, 0);
+ unsigned long nop_period = std::stoul(tokens[2], nullptr, 0);
+ unsigned long nop_num = std::stoul(tokens[3], nullptr, 0);
+ return MemBWAntagonistWorker::Create(size, nop_period, nop_num);
+ }
+ else if (tokens[0] == "dynamiccacheantagonist")
+ {
+ if (tokens.size() != 4)
+ return nullptr;
+ unsigned long size = std::stoul(tokens[1], nullptr, 0);
+ unsigned long period = std::stoul(tokens[2], nullptr, 0);
+ unsigned long long nop_num = std::stoul(tokens[3], nullptr, 0);
+ return DynamicCacheAntagonistWorker::Create(size, period, nop_num);
+ }
+
+ // invalid type of worker
+ return nullptr;
+}
diff --git a/repos/mml/src/app/antagonist/synthetic_worker.h b/repos/mml/src/app/antagonist/synthetic_worker.h
new file mode 100644
index 0000000000..f7a86685c0
--- /dev/null
+++ b/repos/mml/src/app/antagonist/synthetic_worker.h
@@ -0,0 +1,166 @@
+// synthetic_worker.h - support for generation of synthetic work
+
+#pragma once
+
+//#include
+#include
+#include
+#include
+#include
+#include
+
+#define CACHELINE_SIZE (64)
+
+class SyntheticWorker
+{
+public:
+ virtual ~SyntheticWorker() {}
+ // Perform n iterations of fake work.
+ virtual void Work(uint64_t n) = 0;
+};
+
+class SqrtWorker : public SyntheticWorker
+{
+public:
+ SqrtWorker() {}
+ ~SqrtWorker() {}
+
+ // Performs n iterations of sqrt().
+ void Work(uint64_t n);
+};
+
+class AsmSqrtWorker : public SyntheticWorker
+{
+public:
+ AsmSqrtWorker() {}
+ ~AsmSqrtWorker() {}
+
+ // Performs n iterations of sqrt().
+ void Work(uint64_t n);
+};
+
+class StridedMemtouchWorker : public SyntheticWorker
+{
+public:
+ ~StridedMemtouchWorker() { delete buf_; }
+
+ // Creates a strided memory touching worker.
+ static StridedMemtouchWorker *Create(std::size_t size, size_t stride);
+
+ // Performs n strided memory touches.
+ void Work(uint64_t n);
+
+private:
+ StridedMemtouchWorker(char *buf, std::size_t size, size_t stride)
+ : buf_(buf), size_(size), stride_(stride) {}
+
+ volatile char *buf_;
+ std::size_t size_;
+ std::size_t stride_;
+};
+
+class MemStreamWorker : public SyntheticWorker
+{
+public:
+ ~MemStreamWorker();
+
+ // Creates a memory streaming worker.
+ static MemStreamWorker *Create(std::size_t size);
+
+ // Performs n memory reads.
+ void Work(uint64_t n);
+
+private:
+ MemStreamWorker(char *buf, std::size_t size) : buf_(buf), size_(size) {}
+
+ volatile char *buf_;
+ std::size_t size_;
+};
+
+class RandomMemtouchWorker : public SyntheticWorker
+{
+public:
+ ~RandomMemtouchWorker() { delete buf_; }
+
+ // Creates a random memory touching worker.
+ static RandomMemtouchWorker *Create(std::size_t size, unsigned int seed);
+
+ // Performs n random memory touches.
+ void Work(uint64_t n);
+
+private:
+ RandomMemtouchWorker(char *buf, std::vector schedule)
+ : buf_(buf), schedule_(std::move(schedule)) {}
+
+ volatile char *buf_;
+ std::vector schedule_;
+};
+
+class CacheAntagonistWorker : public SyntheticWorker
+{
+public:
+ ~CacheAntagonistWorker() { delete buf_; }
+
+ // Creates a cache antagonist worker.
+ static CacheAntagonistWorker *Create(std::size_t size);
+
+ // Perform n cache accesses.
+ void Work(uint64_t n);
+
+private:
+ CacheAntagonistWorker(char *buf, std::size_t size) : buf_(buf), size_(size) {}
+
+ char *buf_;
+ std::size_t size_;
+};
+
+class MemBWAntagonistWorker : public SyntheticWorker
+{
+public:
+ ~MemBWAntagonistWorker() { free(buf_); }
+
+ // Creates a memory bandwidth antagonist worker. It allocates an array whose
+ // size is indicated by the parameter.
+ static MemBWAntagonistWorker *Create(std::size_t size, int nop_period,
+ int nop_num);
+
+ // Perform n times array stores.
+ void Work(uint64_t n);
+
+private:
+ MemBWAntagonistWorker(char *buf, std::size_t size, int nop_period,
+ int nop_num)
+ : buf_(buf), size_(size), nop_period_(nop_period), nop_num_(nop_num) {}
+
+ char *buf_;
+ std::size_t size_;
+ int nop_period_;
+ int nop_num_;
+};
+
+class DynamicCacheAntagonistWorker : public SyntheticWorker
+{
+public:
+ ~DynamicCacheAntagonistWorker() { delete buf_; }
+
+ // Creates a cache antagonist worker.
+ static DynamicCacheAntagonistWorker *Create(std::size_t size, int period,
+ int nop_num);
+
+ // Perform n cache accesses.
+ void Work(uint64_t n);
+
+private:
+ DynamicCacheAntagonistWorker(char *buf, std::size_t size, int period,
+ int nop_num)
+ : buf_(buf), size_(size), period_(period), nop_num_(nop_num) {}
+
+ char *buf_;
+ std::size_t size_;
+ int period_;
+ int nop_num_;
+ int cnt_;
+};
+
+// Parses a string to generate one of the above fake workers.
+SyntheticWorker *SyntheticWorkerFactory(std::string s);
diff --git a/repos/mml/src/app/antagonist/target.mk b/repos/mml/src/app/antagonist/target.mk
new file mode 100644
index 0000000000..87052693a5
--- /dev/null
+++ b/repos/mml/src/app/antagonist/target.mk
@@ -0,0 +1,16 @@
+MXINC_DIR=$(REP_DIR)/src/app/antagonist
+GENODE_GCC_TOOLCHAIN_DIR ?= /usr/local/genode/tool/21.05
+
+TARGET = stress_genode
+# soure file for benchmark framework
+
+SRC_CC = stress_linux.cc synthetic_worker.cc util.cc
+LIBS += base libc stdcxx mxtasking
+EXT_OBJECTS += /usr/local/genode/tool/lib/clang/14.0.5/lib/linux/libclang_rt.builtins-x86_64.a /usr/local/genode/tool/lib/libatomic.a
+CUSTOM_CC = /usr/local/genode/tool/bin/clang
+CUSTOM_CXX = /usr/local/genode/tool/bin/clang++
+CC_OPT += --target=x86_64-genode --sysroot=/does/not/exist --gcc-toolchain=$(GENODE_GCC_TOOLCHAIN_DIR) -Wno-error -O2 -g -DNDEBUG -I$(MXINC_DIR) -std=c++20 #-D_GLIBCXX_ATOMIC_BUILTINS_8 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+#CC_OPT += -femulated-tls -DCLANG_CXX11_ATOMICS
+CC_CXX_WARN_STRICT =
+CUSTOM_CXX_LIB := $(CROSS_DEV_PREFIX)g++
+#CXX_LD += $(CROSS_DEV_PREFIX)g++
diff --git a/repos/mml/src/app/antagonist/types.h b/repos/mml/src/app/antagonist/types.h
new file mode 100644
index 0000000000..a28c9a2b5d
--- /dev/null
+++ b/repos/mml/src/app/antagonist/types.h
@@ -0,0 +1,50 @@
+/*
+ * types.h - primitive type definitions
+ */
+
+#pragma once
+
+#include
+#include "cpu.h"
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+
+#ifndef __WORD_SIZE
+#error __WORD_SIZE is undefined
+#endif
+
+#if __WORD_SIZE == __64BIT_WORDS
+
+typedef unsigned long uint64_t;
+typedef signed long int64_t;
+
+#else /* __WORDSIZE == __64BIT_WORDS */
+
+typedef unsigned long long uint64_t;
+typedef signed long long int64_t;
+
+#endif /* __WORDSIZE == __64BIT_WORDS */
+
+typedef unsigned long uintptr_t;
+typedef long intptr_t;
+typedef long off_t;
+typedef unsigned long size_t;
+typedef long ssize_t;
+
+typedef struct {
+ volatile int locked;
+} spinlock_t;
+
+typedef struct {
+ volatile int cnt;
+} atomic_t;
+
+typedef struct {
+ volatile long cnt;
+} atomic64_t;
diff --git a/repos/mml/src/app/antagonist/util.cc b/repos/mml/src/app/antagonist/util.cc
new file mode 100644
index 0000000000..d7cb303509
--- /dev/null
+++ b/repos/mml/src/app/antagonist/util.cc
@@ -0,0 +1,14 @@
+#include "util.h"
+
+std::vector split(const std::string &text, char sep)
+{
+ std::vector tokens;
+ std::string::size_type start = 0, end = 0;
+ while ((end = text.find(sep, start)) != std::string::npos)
+ {
+ tokens.push_back(text.substr(start, end - start));
+ start = end + 1;
+ }
+ tokens.push_back(text.substr(start));
+ return tokens;
+}
diff --git a/repos/mml/src/app/antagonist/util.h b/repos/mml/src/app/antagonist/util.h
new file mode 100644
index 0000000000..46b7006a15
--- /dev/null
+++ b/repos/mml/src/app/antagonist/util.h
@@ -0,0 +1,6 @@
+#pragma once
+#include
+#include
+#include
+
+std::vector split(const std::string &text, char sep);
diff --git a/repos/mml/src/app/blinktree/benchmark/chronometer.h b/repos/mml/src/app/blinktree/benchmark/chronometer.h
index 7014b1aba4..4e2c006dec 100644
--- a/repos/mml/src/app/blinktree/benchmark/chronometer.h
+++ b/repos/mml/src/app/blinktree/benchmark/chronometer.h
@@ -1,14 +1,13 @@
#pragma once
-#ifdef PERF_SUPPORT
#include "perf.h"
-#endif
#include "phase.h"
#include
#include
#include
#include
#include
+#include
#include
#include |