mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
base-hw: Avoid early calls of cmpxchg
This patch eliminates calls of 'cmpxchg' prior enabling the MMU. This is needed because the 'ldrex' and 'strex' instructions do not always work with MMU and L1 cache disabled, i.e., on Raspberry Pi.
This commit is contained in:
parent
ddffc8765e
commit
71cd7b9d2e
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* \brief Genode-console backend
|
||||
* \author Martin Stein
|
||||
* \date 2011-10-17
|
||||
@ -16,6 +16,9 @@
|
||||
#include <base/printf.h>
|
||||
#include <drivers/serial_log.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include "singleton.h"
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
@ -63,8 +66,7 @@ using namespace Genode;
|
||||
*/
|
||||
static Platform_console * platform_console()
|
||||
{
|
||||
static Platform_console static_platform_console;
|
||||
return &static_platform_console;
|
||||
return unsynchronized_singleton<Platform_console>();
|
||||
}
|
||||
|
||||
|
||||
|
53
base-hw/src/base/singleton.h
Normal file
53
base-hw/src/base/singleton.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* \brief Helper for creating singleton objects
|
||||
* \author Norman Feske
|
||||
* \date 2013-05-14
|
||||
*
|
||||
* Before enabling the MMU on ARM, the 'cmpxchg' implementation is not always
|
||||
* guaranteed to work. For example, on the Raspberry Pi, the 'ldrex' as used by
|
||||
* 'cmpxchg' causes the machine to reboot. After enabling the MMU, everything
|
||||
* is fine. Hence, we need to avoid executing 'cmpxchg' prior this point.
|
||||
* Unfortunately, 'cmpxchg' is implicitly called each time when creating a
|
||||
* singleton object via a local-static object pattern. In this case, the
|
||||
* compiler generates code that calls the '__cxa_guard_acquire' function of the
|
||||
* C++ runtime, which, in turn, relies 'cmpxchg' for synchronization.
|
||||
*
|
||||
* The utility provided herein is an alternative way to create single object
|
||||
* instances without implicitly calling 'cmpxchg'. Because object creation is
|
||||
* not synchronized via a spin lock, it must not be used in scenarios where
|
||||
* multiple threads may contend.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SINGLETON_H_
|
||||
#define _SINGLETON_H_
|
||||
|
||||
inline void *operator new(Genode::size_t, void *at) { return at; }
|
||||
|
||||
|
||||
template <typename T, int ALIGN = 2, typename... Args>
|
||||
static inline T *unsynchronized_singleton(Args... args)
|
||||
{
|
||||
/*
|
||||
* Each instantiation of the function template with a different type 'T'
|
||||
* yields a dedicated instance of the local static variables, thereby
|
||||
* creating the living space for the singleton objects.
|
||||
*/
|
||||
static bool initialized;
|
||||
static int inst[sizeof(T)/sizeof(int) + 1] __attribute__((aligned(ALIGN)));
|
||||
|
||||
/* execute constructor on first call */
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
new (&inst) T(args...);
|
||||
}
|
||||
return reinterpret_cast<T *>(inst);
|
||||
}
|
||||
|
||||
#endif /* _SINGLETON_H_ */
|
@ -33,6 +33,9 @@
|
||||
#include <tlb.h>
|
||||
#include <trustzone.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <singleton.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
/* get core configuration */
|
||||
@ -262,7 +265,7 @@ namespace Kernel
|
||||
* Static mode transition control
|
||||
*/
|
||||
static Mode_transition_control * mtc()
|
||||
{ static Mode_transition_control _object; return &_object; }
|
||||
{ return unsynchronized_singleton<Mode_transition_control>(); }
|
||||
|
||||
/**
|
||||
* Kernel object that represents a Genode PD
|
||||
@ -333,7 +336,7 @@ namespace Kernel
|
||||
/**
|
||||
* Access to static interrupt-controller
|
||||
*/
|
||||
static Pic * pic() { static Pic _object; return &_object; }
|
||||
static Pic * pic() { return unsynchronized_singleton<Pic>(); }
|
||||
}
|
||||
|
||||
|
||||
@ -407,9 +410,11 @@ namespace Kernel
|
||||
*/
|
||||
static Pd * core()
|
||||
{
|
||||
static Core_tlb tlb;
|
||||
static Pd _pd(&tlb, 0);
|
||||
return &_pd;
|
||||
constexpr int tlb_align = 1 << Core_tlb::ALIGNM_LOG2;
|
||||
|
||||
Core_tlb *core_tlb = unsynchronized_singleton<Core_tlb, tlb_align>();
|
||||
Pd *pd = unsynchronized_singleton<Pd>(core_tlb, nullptr);
|
||||
return pd;
|
||||
}
|
||||
|
||||
|
||||
@ -1421,6 +1426,12 @@ extern "C" void kernel()
|
||||
/* switch to core address space */
|
||||
Cpu::init_virt_kernel(core()->tlb()->base(), core_id());
|
||||
|
||||
/*
|
||||
* From this point on, it is safe to use 'cmpxchg', i.e., to create
|
||||
* singleton objects via the static-local object pattern. See
|
||||
* the comment in 'src/base/singleton.h'.
|
||||
*/
|
||||
|
||||
/* create the core main thread */
|
||||
static Native_utcb cm_utcb;
|
||||
static char cm_stack[DEFAULT_STACK_SIZE]
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include <timer.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <singleton.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
class Platform_thread;
|
||||
@ -211,8 +214,7 @@ namespace Kernel
|
||||
*/
|
||||
static Id_alloc * _id_alloc()
|
||||
{
|
||||
static Id_alloc _id_alloc;
|
||||
return &_id_alloc;
|
||||
return unsynchronized_singleton<Id_alloc>();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -224,8 +226,7 @@ namespace Kernel
|
||||
*/
|
||||
static Pool * pool()
|
||||
{
|
||||
static Pool _pool;
|
||||
return &_pool;
|
||||
return unsynchronized_singleton<Pool>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,11 +13,15 @@ CC_OPT += -DCORE_MAIN=_main
|
||||
# add library dependencies
|
||||
LIBS += base-common
|
||||
|
||||
# enable C++11 support
|
||||
CC_CXX_OPT += -std=gnu++11
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core \
|
||||
$(REP_DIR)/src/core/include \
|
||||
$(REP_DIR)/include \
|
||||
$(REP_DIR)/src/platform \
|
||||
$(REP_DIR)/src/base \
|
||||
$(BASE_DIR)/src/core/include \
|
||||
$(BASE_DIR)/include \
|
||||
$(BASE_DIR)/src/platform
|
||||
|
@ -106,7 +106,14 @@ namespace Arm
|
||||
/* lookup table for AP bitfield values according to 'w' and 'k' flag */
|
||||
typedef typename T::Ap_1_0 Ap_1_0;
|
||||
typedef typename T::Ap_2 Ap_2;
|
||||
static typename T::access_t const ap_bits[2][2] = {{
|
||||
|
||||
/*
|
||||
* Note: Don't make 'ap_bits' static to avoid implicit use of 'cmpxchg'
|
||||
* prior enabling the MMU.
|
||||
*
|
||||
* XXX Replace array with a simpler-to-grasp switch statement.
|
||||
*/
|
||||
typename T::access_t const ap_bits[2][2] = {{
|
||||
Ap_1_0::bits(Ap_1_0::USER_RO_ACCESS) | /* -- */
|
||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user