From 8fe7fa5532af57668194a98aa44fe27947a9e1b2 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Fri, 16 Dec 2022 14:33:06 +0100 Subject: [PATCH] hw: don't take the log backend's mutex in kernel To prevent the kernel to deadlock, or call itself with a syscall when using a lock potentially hold by a core thread, the log console's backend for core (hw) gets replaced by a specific variant that checks whether it runs in the kernel context before using the mutex. Fix genodelabs/genode#3280 --- repos/base-hw/lib/mk/base-hw-common.mk | 5 ++ repos/base-hw/lib/mk/base-hw.mk | 1 + repos/base-hw/src/core/core_log_out.cc | 81 +++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/repos/base-hw/lib/mk/base-hw-common.mk b/repos/base-hw/lib/mk/base-hw-common.mk index 76b64b739c..58506fd577 100644 --- a/repos/base-hw/lib/mk/base-hw-common.mk +++ b/repos/base-hw/lib/mk/base-hw-common.mk @@ -10,3 +10,8 @@ include $(BASE_DIR)/lib/mk/base-common.inc SRC_CC += rpc_dispatch_loop.cc SRC_CC += thread.cc thread_myself.cc thread_bootstrap.cc SRC_CC += signal_transmitter.cc + +# filter out log.cc from the generic base library +# in core and hw kernel we have to implement it differently +SRC_CC_WITH_LOG_CC := $(SRC_CC) +SRC_CC = $(filter-out log.cc,$(SRC_CC_WITH_LOG_CC)) diff --git a/repos/base-hw/lib/mk/base-hw.mk b/repos/base-hw/lib/mk/base-hw.mk index 8aaf077421..ed1b684450 100644 --- a/repos/base-hw/lib/mk/base-hw.mk +++ b/repos/base-hw/lib/mk/base-hw.mk @@ -1,5 +1,6 @@ include $(BASE_DIR)/lib/mk/base.inc +SRC_CC += log.cc SRC_CC += thread_start.cc SRC_CC += capability.cc SRC_CC += cache.cc diff --git a/repos/base-hw/src/core/core_log_out.cc b/repos/base-hw/src/core/core_log_out.cc index 2d555f12c1..70148f275a 100644 --- a/repos/base-hw/src/core/core_log_out.cc +++ b/repos/base-hw/src/core/core_log_out.cc @@ -12,15 +12,22 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ +#include +#include + /* base-internal includes */ #include #include #include +#include #include +using namespace Genode; -void Genode::Core_log::out(char const c) { Kernel::log(c); } + +void Core_log::out(char const c) { Kernel::log(c); } void Genode::raw_write_string(char const *str) @@ -28,3 +35,75 @@ void Genode::raw_write_string(char const *str) while (char c = *str++) Kernel::log(c); } + + +/************************************************************ + ** Utility to check whether kernel or core code is active ** + ************************************************************/ + +extern void const * const kernel_stack; + +static inline bool running_in_kernel() +{ + addr_t const stack_base = reinterpret_cast(&kernel_stack); + static constexpr size_t stack_size = + NR_OF_CPUS * Kernel::Cpu::KERNEL_STACK_SIZE; + + /* check stack variable against kernel stack area */ + return ((addr_t)&stack_base) >= stack_base && + ((addr_t)&stack_base) < (stack_base + stack_size); +} + + +/******************************************* + ** Implementation of src/lib/base/log.cc ** + *******************************************/ + +void Log::_acquire(Type type) +{ + if (!running_in_kernel()) _mutex.acquire(); + + /* + * Mark warnings and errors via distinct colors. + */ + switch (type) { + case LOG: break; + case WARNING: _output.out_string("\033[34mWarning: "); break; + case ERROR: _output.out_string("\033[31mError: "); break; + }; +} + + +void Log::_release() +{ + /* + * Reset color and add newline + */ + _output.out_string("\033[0m\n"); + + if (!running_in_kernel()) _mutex.release(); +} + + +void Raw::_acquire() +{ + /* + * Mark raw output with distinct color + */ + _output().out_string("\033[32mKernel: "); +} + + +void Raw::_release() +{ + /* + * Reset color and add newline + */ + _output().out_string("\033[0m\n"); +} + + +void Trace_output::Write_trace_fn::operator () (char const *s) +{ + Thread::trace(s); +}