hw: bootstrap into kernel

Put the initialization of the cpu cores, setup of page-tables, enabling of
MMU and caches into a separate component that is only used to bootstrap
the kernel resp. core.

Ref #2092
This commit is contained in:
Stefan Kalkowski 2016-11-07 18:00:24 +01:00 committed by Norman Feske
parent 8aa8423cfd
commit cf943dac65
178 changed files with 2818 additions and 1806 deletions

View File

@ -0,0 +1,2 @@
REQUIRES = x86_64
LIBS = bootstrap-hw-muen_off

View File

@ -0,0 +1,4 @@
REQUIRES = imx53
# add library dependencies
LIBS += bootstrap-hw-trustzone_off

View File

@ -0,0 +1,44 @@
HW_DIR = $(BASE_DIR)/../base-hw
LIBS = cxx
SRC_CC += bootstrap/env.cc
SRC_CC += bootstrap/init.cc
SRC_CC += bootstrap/lock.cc
SRC_CC += bootstrap/platform.cc
SRC_CC += bootstrap/thread.cc
SRC_CC += core/capability.cc
SRC_CC += core/core_log.cc
SRC_CC += core/default_log.cc
SRC_CC += core/dump_alloc.cc
SRC_CC += core/kernel_log.cc
SRC_CC += lib/base/allocator_avl.cc
SRC_CC += lib/base/avl_tree.cc
SRC_CC += lib/base/console.cc
SRC_CC += lib/base/elf_binary.cc
SRC_CC += lib/base/heap.cc
SRC_CC += lib/base/log.cc
SRC_CC += lib/base/output.cc
SRC_CC += lib/base/slab.cc
SRC_CC += lib/base/sleep.cc
SRC_CC += lib/base/sliced_heap.cc
SRC_CC += lib/startup/_main.cc
INC_DIR += $(HW_DIR)/src/bootstrap/include
INC_DIR += $(HW_DIR)/src/core/include
INC_DIR += $(BASE_DIR)/src/core/include
INC_DIR += $(HW_DIR)/src/include
INC_DIR += $(BASE_DIR)/src/include
# configure multiprocessor mode
NR_OF_CPUS ?= 1
CC_OPT += -Wa,--defsym -Wa,NR_OF_CPUS=$(NR_OF_CPUS) -DNR_OF_CPUS=$(NR_OF_CPUS)
vpath lib/base/% $(HW_DIR)/src
vpath lib/muen/% $(HW_DIR)/src
vpath lib/base/% $(BASE_DIR)/src
vpath lib/startup/% $(BASE_DIR)/src
vpath base/% $(HW_DIR)/src
vpath core/% $(HW_DIR)/src
vpath core/% $(BASE_DIR)/src
vpath bootstrap/% $(HW_DIR)/src

View File

@ -1,14 +0,0 @@
#
# \brief Build config for parts of core that depend on Trustzone status
# \author Stefan Kalkowski
# \author Martin Stein
# \date 2012-10-24
#
# add include paths
INC_DIR += $(REP_DIR)/src/core/include
INC_DIR += $(BASE_DIR)/src/core/include
# declare source paths
vpath % $(REP_DIR)/src/core
vpath % $(BASE_DIR)/src/core

View File

@ -5,5 +5,7 @@
# \date 2012-10-24
#
REQUIRES = imx53
# add library dependencies
LIBS += core-hw-trustzone_off

View File

@ -1,5 +0,0 @@
#
# \brief Build config for parts of core that depend on Trustzone status
# \author Martin Stein
# \date 2014-07-23
#

View File

@ -23,6 +23,7 @@ SRC_CC += core_rpc_cap_alloc.cc
SRC_CC += dataspace_component.cc
SRC_CC += default_log.cc
SRC_CC += dump_alloc.cc
SRC_CC += kernel_log.cc
SRC_CC += io_mem_session_component.cc
SRC_CC += io_mem_session_support.cc
SRC_CC += irq_session_component.cc
@ -62,6 +63,7 @@ SRC_CC += capability.cc
include $(BASE_DIR)/src/core/version.inc
# configure multiprocessor mode
NR_OF_CPUS ?= 1
CC_OPT += -Wa,--defsym -Wa,NR_OF_CPUS=$(NR_OF_CPUS) -DNR_OF_CPUS=$(NR_OF_CPUS)
# declare source locations

View File

@ -0,0 +1,4 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm
SRC_S += bootstrap/spec/arm/crt0.s
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc

View File

@ -0,0 +1,4 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_v7
SRC_CC += core/spec/arm_v7/cpu.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/bootstrap-hw.inc

View File

@ -0,0 +1,6 @@
SRC_CC += bootstrap/spec/arndale/cpu.cc
SRC_CC += core/spec/arndale/pic.cc
NR_OF_CPUS = 2
include $(REP_DIR)/lib/mk/spec/exynos5/bootstrap-hw.inc

View File

@ -8,7 +8,6 @@
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v7/virtualization
# add C++ sources
SRC_CC += spec/arndale/cpu.cc
SRC_CC += spec/arndale/pic.cc
SRC_CC += spec/arndale/platform_services.cc
SRC_CC += kernel/vm_thread_on.cc

View File

@ -0,0 +1,4 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a15
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_gic
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc

View File

@ -9,14 +9,10 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a15
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_gic
# add C++ sources
SRC_CC += spec/cortex_a15/cpu.cc
SRC_CC += spec/cortex_a15/kernel/cpu.cc
SRC_CC += spec/arm/smp/kernel/thread_update_pd.cc
SRC_CC += spec/arm/smp/kernel/cpu.cc
# add assembler sources
SRC_S += spec/arm/smp/kernel/crt0.s
# include less specific configuration
include $(BASE_DIR)/../base-hw/lib/mk/spec/smp/core-hw.inc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/core-hw.inc

View File

@ -0,0 +1,9 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/smp
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_gic
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a9
SRC_CC += core/spec/arm_gic/pic.cc
SRC_CC += core/spec/cortex_a9/board.cc
SRC_CC += bootstrap/spec/cortex_a9/platform.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc

View File

@ -10,17 +10,15 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_gic
# add C++ sources
SRC_CC += spec/cortex_a9/kernel/cpu.cc
SRC_CC += spec/cortex_a9/cpu.cc
SRC_CC += spec/cortex_a9/fpu.cc
SRC_CC += spec/cortex_a9/board.cc
SRC_CC += spec/cortex_a9/timer.cc
SRC_CC += spec/arm/smp/kernel/thread_update_pd.cc
SRC_CC += spec/arm/smp/kernel/cpu.cc
SRC_CC += spec/arm/kernel/cpu_context.cc
SRC_CC += spec/arm_gic/pic.cc
SRC_CC += kernel/vm_thread_off.cc
# add Assembler sources
SRC_S += spec/arm/smp/kernel/crt0.s
# include less specific configuration
include $(BASE_DIR)/../base-hw/lib/mk/spec/smp/core-hw.inc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/core-hw.inc

View File

@ -0,0 +1,5 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/exynos5
SRC_CC += bootstrap/spec/exynos5/platform.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a15/bootstrap-hw.inc

View File

@ -8,7 +8,6 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/exynos5
# add C++ sources
SRC_CC += spec/exynos5/platform_support.cc
SRC_CC += spec/exynos5/cpu.cc
# include less specific configuration

View File

@ -0,0 +1,3 @@
SRC_CC += bootstrap/spec/imx53/board.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/imx53/bootstrap-hw.inc

View File

@ -0,0 +1,3 @@
SRC_CC += bootstrap/spec/imx53/board_trustzone.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/imx53/bootstrap-hw.inc

View File

@ -0,0 +1,8 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a8
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx53
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx
SRC_CC += core/spec/imx53/pic.cc
SRC_CC += bootstrap/spec/imx53/platform.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc

View File

@ -0,0 +1 @@
LIBS += bootstrap-hw-trustzone

View File

@ -12,5 +12,4 @@ SRC_CC += spec/imx53/pic.cc
SRC_CC += platform_services.cc
# include less specific configuration
include $(REP_DIR)/lib/mk/spec/imx53/core-hw-trustzone.inc
include $(REP_DIR)/lib/mk/core-hw-trustzone.inc
include $(REP_DIR)/lib/mk/spec/imx53/core-hw.inc

View File

@ -22,5 +22,4 @@ SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc
SRC_S += spec/arm_v7/trustzone/mode_transition.s
# include less specific configuration
include $(REP_DIR)/lib/mk/spec/imx53/core-hw-trustzone.inc
include $(REP_DIR)/lib/mk/core-hw-trustzone.inc
include $(REP_DIR)/lib/mk/spec/imx53/core-hw.inc

View File

@ -0,0 +1,8 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx6
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx
SRC_CC += bootstrap/spec/imx6/platform.cc
NR_OF_CPUS = 4
include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc

View File

@ -0,0 +1 @@
LIBS += bootstrap-hw-muen_on

View File

@ -0,0 +1,4 @@
SRC_CC += bootstrap/spec/odroid_xu/cpu.cc
SRC_CC += core/spec/arm_gic/pic.cc
include $(REP_DIR)/lib/mk/spec/exynos5/bootstrap-hw.inc

View File

@ -5,13 +5,10 @@
#
# add C++ sources
SRC_CC += spec/cortex_a15/cpu_init.cc
SRC_CC += spec/arm/kernel/cpu_context.cc
SRC_CC += spec/arm_gic/pic.cc
SRC_CC += kernel/vm_thread_off.cc
SRC_CC += platform_services.cc
NR_OF_CPUS = 1
# include less specific configuration
include $(REP_DIR)/lib/mk/spec/exynos5/core-hw.inc

View File

@ -0,0 +1,8 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/panda
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/tl16c750
SRC_CC += bootstrap/spec/panda/platform.cc
NR_OF_CPUS = 2
include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc

View File

@ -0,0 +1,6 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/pbxa9
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/pl011
SRC_CC += bootstrap/spec/pbxa9/platform.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc

View File

@ -0,0 +1,11 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/riscv
SRC_CC += bootstrap/spec/riscv/cpu.cc
SRC_CC += bootstrap/spec/riscv/exception_vector.cc
SRC_CC += bootstrap/spec/riscv/platform.cc
SRC_CC += lib/base/riscv/kernel/interface.cc
SRC_S += bootstrap/spec/riscv/crt0.s
SRC_S += core/spec/riscv/mode_transition.s
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc

View File

@ -9,7 +9,6 @@ SRC_CC += spec/riscv/kernel/cpu_context.cc
SRC_CC += spec/riscv/kernel/thread.cc
SRC_CC += spec/riscv/kernel/pd.cc
SRC_CC += spec/riscv/kernel/cpu.cc
SRC_CC += spec/riscv/kernel/exception_vector.cc
SRC_CC += spec/riscv/platform_support.cc
SRC_CC += spec/riscv/cpu.cc
@ -18,7 +17,5 @@ SRC_S += spec/riscv/mode_transition.s
SRC_S += spec/riscv/kernel/crt0.s
SRC_S += spec/riscv/crt0.s
NR_OF_CPUS = 1
# include less specific configuration
include $(REP_DIR)/lib/mk/core-hw.inc

View File

@ -0,0 +1,10 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/rpi
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_v6
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/pl011
SRC_CC += bootstrap/spec/arm_v6/cpu.cc
SRC_CC += bootstrap/spec/rpi/platform.cc
SRC_CC += core/spec/rpi/pic.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/bootstrap-hw.inc

View File

@ -11,8 +11,8 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/pl011
# add C++ sources
SRC_CC += platform_services.cc
SRC_CC += spec/rpi/platform_support.cc
NR_OF_CPUS = 1
SRC_CC += spec/rpi/timer.cc
SRC_CC += spec/rpi/pic.cc
# include less specific configuration
include $(REP_DIR)/lib/mk/spec/arm_v6/core-hw.inc

View File

@ -0,0 +1 @@
LIBS += bootstrap-hw-trustzone_on

View File

@ -0,0 +1,9 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a8
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx53
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx
SRC_CC += core/spec/imx53/pic.cc
SRC_CC += bootstrap/spec/imx53/platform.cc
SRC_CC += bootstrap/spec/imx53/board_trustzone.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc

View File

@ -0,0 +1,5 @@
SRC_CC += core/spec/x86_64/pic.cc
SRC_CC += bootstrap/spec/x86_64/platform.cc
SRC_S += bootstrap/spec/x86_64/crt0_translation_table.s
include $(BASE_DIR)/../base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc

View File

@ -0,0 +1,9 @@
REQUIRES = muen
INC_DIR += $(REP_DIR)/src/core/include/spec/x86_64/muen
SRC_CC += lib/muen/sinfo.cc
SRC_CC += bootstrap/spec/x86_64/platform_muen.cc
SRC_S += bootstrap/spec/x86_64/crt0_translation_table_muen.s
include $(BASE_DIR)/../base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc

View File

@ -0,0 +1,5 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/x86_64
SRC_S += bootstrap/spec/x86_64/crt0.s
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc

View File

@ -0,0 +1 @@
LIBS = bootstrap-hw-muen

View File

@ -4,12 +4,10 @@
# \date 2015-06-02
#
# add assembly sources
SRC_S += spec/x86_64/kernel/crt0_translation_table.s
# add C++ sources
SRC_CC += kernel/vm_thread_off.cc
SRC_CC += spec/x86_64/pic.cc
SRC_CC += spec/x86_64/timer.cc
SRC_CC += spec/x86_64/kernel/cpu_exception.cc
SRC_CC += spec/x86_64/kernel/thread_exception.cc
SRC_CC += spec/x86_64/platform_support.cc

View File

@ -9,9 +9,6 @@ REQUIRES = muen
# add include paths
INC_DIR += $(REP_DIR)/src/core/include/spec/x86_64/muen
# add assembly sources
SRC_S += spec/x86_64/muen/kernel/crt0_translation_table.s
# add C++ sources
SRC_CC += spec/x86_64/muen/kernel/cpu_exception.cc
SRC_CC += spec/x86_64/muen/kernel/thread_exception.cc

View File

@ -27,7 +27,5 @@ SRC_CC += spec/x86_64/kernel/thread.cc
SRC_CC += spec/x86_64/kernel/thread.cc
SRC_CC += spec/x86_64/platform_support_common.cc
NR_OF_CPUS = 1
# include less specific configuration
include $(BASE_DIR)/../base-hw/lib/mk/core-hw.inc

View File

@ -0,0 +1,5 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/zynq
SRC_CC += bootstrap/spec/zynq/platform.cc
include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc

View File

@ -0,0 +1,4 @@
INC_DIR += $(REP_DIR)/src/core/include/spec/xilinx_uartps_0
INC_DIR += $(REP_DIR)/src/core/include/spec/zynq_qemu
include $(BASE_DIR)/../base-hw/lib/mk/spec/zynq/bootstrap-hw.inc

View File

@ -0,0 +1,24 @@
/*
* \brief Environment dummy implementation needed by cxx library
* \author Stefan Kalkowski
* \date 2016-09-23
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* base includes */
#include <base/env.h>
/* core includes */
#include <assert.h>
Genode::Env_deprecated * Genode::env_deprecated()
{
assert(false);
return nullptr;
}

View File

@ -0,0 +1,13 @@
TARGET = bootstrap
LIBS = bootstrap-hw
BOOTSTRAP_OBJ = bootstrap.o
$(TARGET): $(BOOTSTRAP_OBJ)
$(VERBOSE)true
.PHONY: $(BOOTSTRAP_OBJ)
$(BOOTSTRAP_OBJ):
$(VERBOSE)$(LD) $(LD_MARCH) -u _start --whole-archive -r $(LINK_ITEMS) $(LIBCXX_GCC) -o $@
clean cleanall:
$(VERBOSE)rm -f $(BOOTSTRAP_OBJ)

View File

@ -0,0 +1,142 @@
/*
* \brief Platform interface
* \author Stefan Kalkowski
* \date 2016-10-19
*/
/*
* 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 General Public License version 2.
*/
#ifndef _PLATFORM_H_
#define _PLATFORM_H_
/* Genode includes */
#include <base/allocator_avl.h>
#include <base/internal/elf.h>
#include <util/reconstructible.h>
/* core includes */
#include <bootinfo.h>
#include <board.h>
#include <cpu.h>
#include <pic.h>
#include <rom_fs.h>
using Genode::addr_t;
using Genode::size_t;
using Genode::Bootinfo;
using Genode::Core_mmio;
using Genode::Mapping;
using Genode::Memory_region;
using Genode::Memory_region_array;
using Genode::Rom_module;
class Platform
{
private:
struct Board : Genode::Board
{
Memory_region_array early_ram_regions;
Memory_region_array late_ram_regions;
Core_mmio const core_mmio;
Board();
};
class Ram_allocator : public Genode::Allocator_avl_base
{
private:
using Base = Genode::Allocator_avl_base;
enum { BSZ = Genode::Allocator_avl::slab_block_size() };
Genode::Tslab<Base::Block, BSZ> _slab;
Genode::uint8_t _first_slab[BSZ];
public:
Ram_allocator()
: Genode::Allocator_avl_base(&_slab, sizeof(Base::Block)),
_slab(this, (Genode::Slab_block*)&_first_slab) {}
void * alloc_aligned(size_t size, unsigned align);
bool alloc(size_t size, void **out_addr) override;
void * alloc(size_t size) { return Allocator::alloc(size); }
void add(Memory_region const &);
void remove(Memory_region const &);
template <typename FUNC>
void for_each_free_region(FUNC functor)
{
_block_tree().for_each([&] (Block const & b)
{
if (!b.used())
functor(Genode::Memory_region(b.addr(), b.size()));
});
}
};
struct Pd
{
void * const table_base;
void * const allocator_base;
Bootinfo::Table & table;
Bootinfo::Table_allocator & allocator;
Bootinfo::Mapping_pool mappings;
Pd(Ram_allocator & alloc);
void map(Mapping m);
void map_insert(Mapping m);
};
struct Elf : Genode::Elf_binary
{
Elf(addr_t const addr) : Genode::Elf_binary(addr) { }
template <typename T> void for_each_segment(T functor)
{
Genode::Elf_segment segment;
for (unsigned i = 0; (segment = get_segment(i)).valid(); i++) {
if (segment.flags().skip) continue;
if (segment.mem_size() == 0) continue;
functor(segment);
}
}
};
Board board;
Genode::Cpu cpu;
Genode::Pic pic;
Ram_allocator ram_alloc;
Memory_region const bootstrap_region;
Genode::Constructible<Pd> core_pd;
addr_t core_elf_addr;
Elf core_elf;
addr_t _load_elf();
public:
Platform();
static addr_t mmio_to_virt(addr_t mmio) { return mmio; }
void enable_mmu();
void start_core() __attribute__((noreturn));
};
extern Platform & platform();
#endif /* _PLATFORM_H_ */

View File

@ -0,0 +1,30 @@
/*
* \brief Initialization code for bootstrap
* \author Stefan Kalkowski
* \date 2016-09-22
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* local */
#include <platform.h>
/* base includes */
#include <base/internal/globals.h>
#include <base/internal/unmanaged_singleton.h>
Platform & platform() { return *unmanaged_singleton<Platform>(); }
extern "C" void init() __attribute__ ((noreturn));
extern "C" void init()
{
Genode::init_log();
platform().enable_mmu();
platform().start_core();
}

View File

@ -0,0 +1,32 @@
/*
* \brief Lock dummy implementation
* \author Stefan Kalkowski
* \date 2016-09-23
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/lock.h>
#include <assert.h>
Genode::Cancelable_lock::Cancelable_lock(Genode::Cancelable_lock::State state)
: _state(state), _owner(nullptr) { }
void Genode::Cancelable_lock::unlock()
{
assert(_state == LOCKED);
_state = UNLOCKED;
}
void Genode::Cancelable_lock::lock()
{
assert(_state == UNLOCKED);
_state = LOCKED;
}

View File

@ -0,0 +1,191 @@
/*
* \brief Platform implementation
* \author Stefan Kalkowski
* \date 2016-10-19
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* base-internal includes */
#include <base/internal/crt0.h>
/* core includes */
#include <assert.h>
#include <boot_modules.h>
#include <platform.h>
/*****************************
** Platform::Ram_allocator **
*****************************/
void * Platform::Ram_allocator::alloc_aligned(size_t size, unsigned align)
{
using namespace Genode;
void * ret;
assert(Base::alloc_aligned(round_page(size), &ret,
max(align, get_page_size_log2())).ok());
return ret;
}
bool Platform::Ram_allocator::alloc(size_t size, void **out_addr)
{
*out_addr = alloc_aligned(size, 0);
return true;
}
void Platform::Ram_allocator::add(Memory_region const & region) {
add_range(region.base, region.size); }
void Platform::Ram_allocator::remove(Memory_region const & region) {
remove_range(region.base, region.size); }
/******************
** Platform::Pd **
******************/
Platform::Pd::Pd(Platform::Ram_allocator & alloc)
: table_base(alloc.alloc_aligned(sizeof(Bootinfo::Table),
Bootinfo::Table::ALIGNM_LOG2)),
allocator_base(alloc.alloc_aligned(sizeof(Bootinfo::Table_allocator),
Bootinfo::Table::ALIGNM_LOG2)),
table(*Genode::construct_at<Bootinfo::Table>(table_base)),
allocator(*Genode::construct_at<Bootinfo::Table_allocator>(allocator_base))
{
using namespace Genode;
map_insert(Mapping((addr_t)table_base, (addr_t)table_base,
sizeof(Bootinfo::Table), PAGE_FLAGS_KERN_DATA));
map_insert(Mapping((addr_t)allocator_base, (addr_t)allocator_base,
sizeof(Bootinfo::Table_allocator), PAGE_FLAGS_KERN_DATA));
}
void Platform::Pd::map(Mapping m)
{
try {
table.insert_translation(m.virt(), m.phys(), m.size(), m.flags(),
allocator.alloc());
} catch(Genode::Allocator::Out_of_memory) {
Genode::error("translation table needs to much RAM");
} catch (...) {
Genode::error("invalid mapping ", m);
}
}
void Platform::Pd::map_insert(Mapping m)
{
mappings.add(m);
map(m);
}
/**************
** Platform **
**************/
addr_t Platform::_load_elf()
{
using namespace Genode;
addr_t start = ~0UL;
addr_t end = 0;
auto lambda = [&] (Genode::Elf_segment & segment) {
void * phys = (void*)(core_elf_addr + segment.file_offset());
start = min(start, (addr_t) phys);
size_t const size = round_page(segment.mem_size());
if (segment.flags().w) {
unsigned align_log2;
for (align_log2 = 0; align_log2 < 8*sizeof(addr_t); align_log2++)
if ((addr_t)(1 << align_log2) & (addr_t)phys) break;
void * const dst = ram_alloc.alloc_aligned(segment.mem_size(),
align_log2);
memcpy(dst, phys, segment.file_size());
if (size > segment.file_size())
memset((void *)((addr_t)dst + segment.file_size()),
0, size - segment.file_size());
phys = dst;
}
//FIXME: set read-only, privileged and global accordingly
Page_flags flags{RW, segment.flags().x ? EXEC : NO_EXEC,
USER, NO_GLOBAL, RAM, CACHED};
Mapping m((addr_t)phys, (addr_t)segment.start(), size, flags);
core_pd->map_insert(m);
end = max(end, (addr_t)segment.start() + size);
};
core_elf.for_each_segment(lambda);
return end;
}
void Platform::start_core()
{
typedef void (* Entry)();
Entry __attribute__((noreturn)) const entry
= reinterpret_cast<Entry>(core_elf.entry());
entry();
}
static constexpr Genode::Boot_modules_header & header() {
return *((Genode::Boot_modules_header*) &_boot_modules_headers_begin); }
Platform::Platform()
: bootstrap_region((addr_t)&_prog_img_beg,
((addr_t)&_prog_img_end - (addr_t)&_prog_img_beg)),
core_pd(ram_alloc),
core_elf_addr(header().base),
core_elf(core_elf_addr)
{
using namespace Genode;
/* prepare the ram allocator */
board.early_ram_regions.for_each([this] (Memory_region const & region) {
ram_alloc.add(region); });
ram_alloc.remove(bootstrap_region);
/* now we can use the ram allocator for core's pd */
core_pd.construct(ram_alloc);
/* temporarily map all bootstrap memory 1:1 for transition to core */
// FIXME do not insert as mapping for core
core_pd->map_insert(Mapping(bootstrap_region.base, bootstrap_region.base,
bootstrap_region.size, PAGE_FLAGS_KERN_TEXT));
/* map memory-mapped I/O for core */
board.core_mmio.for_each_mapping([&] (Mapping const & m) {
core_pd->map_insert(m); });
/* load ELF */
addr_t const elf_end = _load_elf();
/* setup boot info page */
void * bi_base = ram_alloc.alloc(sizeof(Bootinfo));
core_pd->map_insert(Mapping((addr_t)bi_base, elf_end, sizeof(Bootinfo),
PAGE_FLAGS_KERN_TEXT));
Bootinfo & bootinfo =
*construct_at<Bootinfo>(bi_base, &core_pd->table, &core_pd->allocator,
core_pd->mappings, board.core_mmio);
/* add all left RAM to bootinfo */
ram_alloc.for_each_free_region([&] (Memory_region const & r) {
bootinfo.ram_regions.add(r); });
board.late_ram_regions.for_each([&] (Memory_region const & r) {
bootinfo.ram_regions.add(r); });
}

View File

@ -0,0 +1,60 @@
/*
* \brief Startup code for bootstrap
* \author Stefan Kalkowski
* \date 2016-09-22
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
.include "macros.s"
.set STACK_SIZE, 4 * 16 * 1024
.section ".text.crt0"
.global _start
_start:
/* zero-fill BSS segment */
adr r0, _bss_local_start
adr r1, _bss_local_end
ldr r0, [r0]
ldr r1, [r1]
mov r2, #0
1:
cmp r1, r0
ble 2f
str r2, [r0]
add r0, r0, #4
b 1b
2:
.global _start_setup_stack
_start_setup_stack:
/* setup multiprocessor-aware kernel stack-pointer */
adr r0, _start_stack
adr r1, _start_stack_size
ldr r1, [r1]
_init_kernel_sp r0, r1
b init
_bss_local_start:
.long _bss_start
_bss_local_end:
.long _bss_end
_start_stack_size:
.long STACK_SIZE
.align 3
_start_stack:
.rept NR_OF_CPUS
.space STACK_SIZE
.endr

View File

@ -0,0 +1,23 @@
/*
* \brief CPU driver for core
* \author Norman Feske
* \author Martin stein
* \author Stefan Kalkowski
* \date 2012-08-30
*/
/*
* Copyright (C) 2012-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <cpu.h>
void Genode::Arm::clean_invalidate_data_cache() {
asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); }
void Genode::Cpu::translation_added(Genode::addr_t const addr,
Genode::size_t const size) { }

View File

@ -13,8 +13,7 @@
/* core includes */
#include <cpu.h>
namespace Kernel { void prepare_hypervisor(void); }
#include <translation_table.h>
static unsigned char hyp_mode_stack[1024];
@ -61,6 +60,25 @@ static inline void prepare_nonsecure_world()
}
static inline void prepare_hypervisor(Genode::Translation_table & table)
{
using Genode::Cpu;
/* set hypervisor exception vector */
Cpu::hyp_exception_entry_at((void*)0xfff00000); /* FIXME */
/* set hypervisor's translation table */
Cpu::Httbr::translation_table((Genode::addr_t)&table);
/* prepare MMU usage by hypervisor code */
Cpu::Htcr::write(Cpu::Ttbcr::init_virt_kernel());
Cpu::Hcptr::write(Cpu::Hcptr::init());
Cpu::Hmair0::write(Cpu::Mair0::init_virt_kernel());
Cpu::Vtcr::write(Cpu::Vtcr::init());
Cpu::Hsctlr::write(Cpu::Sctlr::init_value());
}
static inline void switch_to_supervisor_mode()
{
using Psr = Genode::Cpu::Psr;
@ -82,9 +100,9 @@ static inline void switch_to_supervisor_mode()
}
void Genode::Cpu::init()
void Genode::Cpu::init(Genode::Translation_table & table)
{
prepare_nonsecure_world();
Kernel::prepare_hypervisor();
prepare_hypervisor(table);
switch_to_supervisor_mode();
}

View File

@ -0,0 +1,169 @@
/*
* \brief Cpu class implementation specific to Cortex A9 SMP
* \author Stefan Kalkowski
* \date 2015-12-09
*/
/*
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/log.h>
/* core includes */
#include <kernel/lock.h>
#include <platform.h>
//using namespace Kernel;
/* entrypoint for non-boot CPUs */
extern "C" void * _start_setup_stack;
/**
* SMP-safe simple counter
*/
class Cpu_counter
{
private:
Kernel::Lock _lock;
volatile int _value = 0;
public:
void inc()
{
Kernel::Lock::Guard guard(_lock);
Genode::memory_barrier();
_value++;
}
void wait_for(int const v) {
while (_value < v) ; }
};
struct Scu : Genode::Mmio
{
struct Cr : Register<0x0, 32>
{
struct Enable : Bitfield<0, 1> { };
};
struct Dcr : Register<0x30, 32>
{
struct Bit_0 : Bitfield<0, 1> { };
};
struct Iassr : Register<0xc, 32>
{
struct Cpu0_way : Bitfield<0, 4> { };
struct Cpu1_way : Bitfield<4, 4> { };
struct Cpu2_way : Bitfield<8, 4> { };
struct Cpu3_way : Bitfield<12, 4> { };
};
Scu(Genode::addr_t mmio) : Genode::Mmio(mmio) { }
void invalidate()
{
Iassr::access_t iassr = 0;
for (Iassr::access_t way = 0; way <= Iassr::Cpu0_way::mask();
way++) {
Iassr::Cpu0_way::set(iassr, way);
Iassr::Cpu1_way::set(iassr, way);
Iassr::Cpu2_way::set(iassr, way);
Iassr::Cpu3_way::set(iassr, way);
write<Iassr>(iassr);
}
}
void enable(bool err_arm_764369)
{
if (err_arm_764369) write<Dcr::Bit_0>(1);
write<Cr::Enable>(1);
}
};
/*
* The initialization of Cortex A9 multicore systems implies a sophisticated
* algorithm in early revisions of this cpu.
*
* See ARM's Cortex-A9 MPCore TRM r2p0 in section 5.3.5 for more details
*/
void Platform::enable_mmu()
{
using Genode::Cpu;
static volatile bool primary_cpu = true;
static Cpu_counter data_cache_invalidated;
static Cpu_counter data_cache_enabled;
static Cpu_counter smp_coherency_enabled;
bool primary = primary_cpu;
if (primary) primary_cpu = false;
Cpu::Sctlr::init();
Cpu::Psr::write(Cpu::Psr::init_kernel());
/* locally initialize interrupt controller */
pic.init_cpu_local();
cpu.invalidate_inner_data_cache();
data_cache_invalidated.inc();
/* primary cpu wakes up all others */
if (primary && NR_OF_CPUS > 1) {
board.wake_up_all_cpus(&_start_setup_stack);
/* send an IPI to all other cpus */
pic.send_ipi();
}
/* wait for other cores' data cache invalidation */
data_cache_invalidated.wait_for(NR_OF_CPUS);
if (primary) {
Scu scu(Board::SCU_MMIO_BASE);
scu.invalidate();
Board::L2_cache l2_cache(Board::PL310_MMIO_BASE);
l2_cache.disable();
l2_cache.invalidate();
scu.enable(board.errata(Platform::Board::ARM_764369));
}
/* secondary cpus wait for the primary's cache activation */
if (!primary) data_cache_enabled.wait_for(1);
cpu.enable_mmu_and_caches((Genode::addr_t)core_pd->table_base);
data_cache_enabled.inc();
cpu.clean_invalidate_inner_data_cache();
/* wait for other cores' data cache activation */
data_cache_enabled.wait_for(NR_OF_CPUS);
if (primary) {
Board::L2_cache l2_cache(board.core_mmio.virt_addr(Board::PL310_MMIO_BASE));
l2_cache.enable();
}
/* secondary cpus wait for the primary's coherency activation */
if (!primary) smp_coherency_enabled.wait_for(1);
Cpu::Actlr::enable_smp(board);
smp_coherency_enabled.inc();
/*
* strangely, some older versions (imx6) seem to not work cache coherent
* until SMP bit is set, so write back the variable here.
*/
cpu.clean_invalidate_inner_data_cache();
/* wait for other cores' coherency activation */
smp_coherency_enabled.wait_for(NR_OF_CPUS);
}

View File

@ -0,0 +1,48 @@
/*
* \brief Parts of platform that are specific to Arndale
* \author Martin Stein
* \date 2012-04-27
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <platform.h>
/* entrypoint for non-boot CPUs */
extern "C" void * _start_setup_stack;
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE }),
core_mmio(Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE },
Memory_region { IRQ_CONTROLLER_VT_CTRL_BASE, IRQ_CONTROLLER_VT_CTRL_SIZE },
Memory_region { MCT_MMIO_BASE, MCT_MMIO_SIZE },
Memory_region { UART_2_MMIO_BASE, UART_2_MMIO_SIZE }) { }
void Platform::enable_mmu()
{
using Genode::Cpu;
static volatile bool primary_cpu = true;
pic.init_cpu_local();
cpu.init(*reinterpret_cast<Genode::Translation_table*>(core_pd->table_base));
Cpu::Sctlr::init();
Cpu::Psr::write(Cpu::Psr::init_kernel());
cpu.invalidate_inner_data_cache();
/* primary cpu wakes up all others */
if (primary_cpu && NR_OF_CPUS > 1) {
primary_cpu = false;
board.wake_up_all_cpus(&_start_setup_stack);
}
cpu.enable_mmu_and_caches((Genode::addr_t)core_pd->table_base);
}

View File

@ -0,0 +1,25 @@
/*
* \brief Specific bootstrap implementations
* \author Stefan Kalkowski
* \date 2017-01-27
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <platform.h>
#include <board.h>
using Genode::Memory_region;
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM0_BASE, RAM0_SIZE },
Memory_region { RAM1_BASE, RAM1_SIZE }),
core_mmio(Memory_region { UART_1_MMIO_BASE, UART_1_MMIO_SIZE },
Memory_region { EPIT_1_MMIO_BASE, EPIT_1_MMIO_SIZE },
Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }) {
init(); }

View File

@ -0,0 +1,27 @@
/*
* \brief Specific core implementations
* \author Stefan Kalkowski
* \date 2017-01-27
*/
/*
* Copyright (C) 2017 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.
*/
/* core includes */
#include <platform.h>
#include <drivers/trustzone.h>
using Genode::Memory_region;
Platform::Board::Board()
: early_ram_regions(Memory_region { Trustzone::SECURE_RAM_BASE,
Trustzone::SECURE_RAM_SIZE }),
core_mmio(Memory_region { UART_1_MMIO_BASE, UART_1_MMIO_SIZE },
Memory_region { EPIT_1_MMIO_BASE, EPIT_1_MMIO_SIZE },
Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE },
Memory_region { CSU_BASE, CSU_SIZE }) {
init(); }

View File

@ -0,0 +1,28 @@
/*
* \brief Specific i.MX53 bootstrap implementations
* \author Stefan Kalkowski
* \date 2012-10-24
*/
/*
* Copyright (C) 2012-2017 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.
*/
/* core includes */
#include <platform.h>
#include <cpu.h>
void Platform::enable_mmu()
{
Genode::Cpu::Sctlr::init();
cpu.enable_mmu_and_caches((addr_t)core_pd->table_base);
}
void Genode::Cpu::translation_added(Genode::addr_t const addr,
Genode::size_t const size) { }

View File

@ -0,0 +1,44 @@
/*
* \brief Specific bootstrap implementations
* \author Stefan Kalkowski
* \author Josef Soentgen
* \author Martin Stein
* \date 2014-02-25
*/
/*
* Copyright (C) 2014-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <platform.h>
#include <cpu.h>
using namespace Genode;
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM0_BASE, RAM0_SIZE }),
core_mmio(Memory_region { UART_1_MMIO_BASE,
UART_1_MMIO_SIZE },
Memory_region { CORTEX_A9_PRIVATE_MEM_BASE,
CORTEX_A9_PRIVATE_MEM_SIZE },
Memory_region { PL310_MMIO_BASE,
PL310_MMIO_SIZE }) { init(); }
bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err)
{
switch (err) {
case Cortex_a9::Board::ARM_754322:
case Cortex_a9::Board::ARM_764369:
case Cortex_a9::Board::ARM_775420:
case Cortex_a9::Board::PL310_588369:
case Cortex_a9::Board::PL310_727915:
case Cortex_a9::Board::PL310_769419:
return true;
};
return false;
}

View File

@ -13,4 +13,4 @@
#include <cpu.h>
void Genode::Cpu::init() {}
void Genode::Cpu::init(Genode::Translation_table&) {}

View File

@ -0,0 +1,51 @@
/*
* \brief Parts of platform that are specific to Pandaboard
* \author Stefan Kalkowski
* \date 2017-01-30
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <platform.h>
#include <cortex_a9_wugen.h>
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE }),
core_mmio(Memory_region { CORTEX_A9_PRIVATE_MEM_BASE,
CORTEX_A9_PRIVATE_MEM_SIZE },
Memory_region { TL16C750_3_MMIO_BASE,
TL16C750_MMIO_SIZE },
Memory_region { PL310_MMIO_BASE,
PL310_MMIO_SIZE }) { }
void Cortex_a9::Board::wake_up_all_cpus(void * const ip)
{
Genode::Cortex_a9_wugen wugen;
wugen.init_cpu_1(ip);
asm volatile("dsb\n"
"sev\n");
}
bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err)
{
switch (err) {
case Cortex_a9::Board::PL310_588369:
case Cortex_a9::Board::PL310_727915: return true;
default: ;
};
return false;
}
void Genode::Cpu::Actlr::enable_smp(Genode::Board & board)
{
Board::Secure_monitor monitor;
monitor.call(Board::Secure_monitor::CPU_ACTLR_SMP_BIT_RAISE, 0);
}

View File

@ -0,0 +1,52 @@
/*
* \brief Pbxa9 specific platform implementation
* \author Stefan Kalkowski
* \date 2016-10-20
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* bootstrap includes */
#include <platform.h>
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE },
Memory_region { RAM_1_BASE, RAM_1_SIZE }),
core_mmio(Memory_region { Board::CORTEX_A9_PRIVATE_MEM_BASE,
Board::CORTEX_A9_PRIVATE_MEM_SIZE },
Memory_region { Board::PL011_0_MMIO_BASE,
Board::PL011_0_MMIO_SIZE },
Memory_region { Board::PL310_MMIO_BASE,
Board::PL310_MMIO_SIZE }) { }
bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) {
return false; }
void Cortex_a9::Board::wake_up_all_cpus(void * const ip)
{
/**
* set the entrypoint for the other CPUs via the flags register
* of the system control registers. ARMs boot monitor code will
* read out this register and jump to it after the cpu received
* an interrupt
*/
struct System_control : Genode::Mmio
{
struct Flagsset : Register<0x30, 32> { };
struct Flagsclr : Register<0x34, 32> { };
System_control(void * const ip)
: Mmio(SYSTEM_CONTROL_MMIO_BASE)
{
write<Flagsclr>(~0UL);
write<Flagsset>(reinterpret_cast<Flagsset::access_t>(ip));
}
} sc(ip);
}

View File

@ -0,0 +1,19 @@
/*
* \brief CPU core implementation
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2016-02-10
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <cpu.h>
void Genode::Cpu::translation_added(addr_t const addr, size_t const size) {
Genode::Cpu::sfence(); }

View File

@ -0,0 +1,51 @@
/**
* \brief Kernel startup code
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2015-06-010
*/
/*
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
.set STACK_SIZE, 64 * 1024
.section ".text.crt0"
.global _start
_start:
j _start_next_page
/* leave first page empty for mode-transition page located at 0x100 */
.space 4096
_start_next_page:
/* clear the bss segment */
la a0, _bss_start
la a1, _bss_end
1:
sd x0, (a0)
addi a0, a0, 8
bne a0, a1, 1b
la sp, _stack_area_start
la a0, STACK_SIZE
ld a0, (a0)
add sp, sp, a0
/* save kernel stack pointer in mscratch */
csrw mscratch, sp
jal setup_riscv_exception_vector
jal init
1: j 1b
.align 3
_stack_area_start:
.space STACK_SIZE

View File

@ -0,0 +1,59 @@
/*
* \brief Platform implementations specific for RISC-V
* \author Stefan Kalkowski
* \author Sebastian Sumpf
* \date 2016-11-23
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <platform.h>
Platform::Board::Board()
: early_ram_regions(Genode::Memory_region { 0, 128 * 1024 * 1024 } ) {}
struct Mstatus : Genode::Register<64>
{
enum {
USER = 0,
SUPERVISOR = 1,
Sv39 = 9,
};
struct Ie : Bitfield<0, 1> { };
struct Priv : Bitfield<1, 2> { };
struct Ie1 : Bitfield<3, 1> { };
struct Priv1 : Bitfield<4, 2> { };
struct Fs : Bitfield<12, 2> { enum { INITIAL = 1 }; };
struct Vm : Bitfield<17, 5> { };
};
void Platform::enable_mmu()
{
using Genode::Cpu;
/* read status register */
Mstatus::access_t mstatus = 0;
Mstatus::Vm::set(mstatus, Mstatus::Sv39); /* enable Sv39 paging */
Mstatus::Fs::set(mstatus, Mstatus::Fs::INITIAL); /* enable FPU */
Mstatus::Ie1::set(mstatus, 1); /* user mode interrupt */
Mstatus::Priv1::set(mstatus, Mstatus::USER); /* set user mode */
Mstatus::Ie::set(mstatus, 0); /* disable interrupts */
Mstatus::Priv::set(mstatus, Mstatus::SUPERVISOR); /* set supervisor mode */
asm volatile ("csrw sasid, %0\n" /* address space id */
"csrw sptbr, %1\n" /* set page table */
"csrw mstatus, %2\n" /* change mode */
:
: "r" (0/*core_pd.asid*/),
"r" (core_pd->table_base),
"r" (mstatus)
: "memory");
}

View File

@ -0,0 +1,46 @@
/*
* \brief Platform implementations specific for base-hw and Raspberry Pi
* \author Norman Feske
* \author Stefan Kalkowski
* \date 2013-04-05
*/
/*
* Copyright (C) 2013-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <platform.h>
using Genode::Memory_region;
/**
* Leave out the first page (being 0x0) from bootstraps RAM allocator,
* some code does not feel happy with addresses being zero
*/
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM_0_BASE + 0x1000,
RAM_0_SIZE - 0x1000 }),
late_ram_regions(Memory_region { RAM_0_BASE, 0x1000 }),
core_mmio(Memory_region { PL011_0_MMIO_BASE,
PL011_0_MMIO_SIZE },
Memory_region { SYSTEM_TIMER_MMIO_BASE,
SYSTEM_TIMER_MMIO_SIZE },
Memory_region { IRQ_CONTROLLER_BASE,
IRQ_CONTROLLER_SIZE },
Memory_region { USB_DWC_OTG_BASE,
USB_DWC_OTG_SIZE }) {}
void Platform::enable_mmu()
{
Genode::Cpu::Sctlr::init();
Genode::Cpu::Psr::write(Genode::Cpu::Psr::init_kernel());
/* check for mapping restrictions */
assert(!Genode::Cpu::restricted_page_mappings());
cpu.enable_mmu_and_caches((addr_t)core_pd->table_base);
}

View File

@ -0,0 +1,118 @@
/*
* \brief Startup code for kernel
* \author Adrian-Ken Rueegsegger
* \author Martin Stein
* \author Reto Buerki
* \author Stefan Kalkowski
* \date 2015-02-06
*/
/*
* Copyright (C) 2011-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
.include "macros.s"
.section ".text.crt0"
/* magic multi-boot header to make GRUB happy */
.long 0x1badb002
.long 0x0
.long 0xe4524ffe
/**********************************
** Startup code for primary CPU **
**********************************/
.code32
.global _start
_start:
/**
* zero-fill BSS segment
*/
leal _bss_start, %edi
leal _bss_end, %ecx
sub %edi, %ecx
shr $2, %ecx
xor %eax, %eax
rep stosl
/* Enable PAE (prerequisite for IA-32e mode) */
movl %cr4, %eax
btsl $5, %eax
movl %eax, %cr4
/* Load initial pagetables */
leal _kernel_pml4, %eax
mov %eax, %cr3
/* Enable IA-32e mode and execute-disable */
movl $0xc0000080, %ecx
rdmsr
btsl $8, %eax
btsl $11, %eax
wrmsr
/* Enable paging, write protection and caching */
movl %cr0, %eax
btsl $16, %eax
btrl $29, %eax
btrl $30, %eax
btsl $31, %eax
movl %eax, %cr0
/* Set up GDT */
lgdt _mt_gdt_ptr
/* Indirect long jump to 64-bit code */
ljmp $8, $_start64
.code64
_start64:
/*
* Set up kernel segment selectors
*/
mov $0x10, %eax
mov %eax, %ss
mov %eax, %ds
mov %eax, %es
mov %eax, %fs
mov %eax, %gs
/*
* Install initial temporary environment that is replaced later by the
* environment that init_main_thread creates.
*/
leaq _stack_high@GOTPCREL(%rip),%rax
movq (%rax), %rsp
movq __initial_bx@GOTPCREL(%rip),%rax
movq %rbx, (%rax)
/* kernel-initialization */
call init
/* catch erroneous return of the kernel initialization */
1: jmp 1b
_define_gdt 0
/*********************************
** .bss (non-initialized data) **
*********************************/
.bss
/* stack of the temporary initial environment */
.p2align 8
.space 32 * 1024
_stack_high:
.globl __initial_bx
__initial_bx:
.space 8

View File

@ -2,11 +2,12 @@
* \brief Initial pagetables for x86_64
* \author Adrian-Ken Rueegsegger
* \author Reto Buerki
* \author Stefan Kalkowski
* \date 2015-04-22
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@ -17,10 +18,10 @@
.data
/********************************************
** Identity mapping from 2MiB to 1GiB **
** Identity mapping from 4KiB to 1GiB **
** plus mappings for LAPIC, I/O APIC MMIO **
** Page 0 containing the Bios Data Area **
** gets mapped to 2MB - 4K readonly. **
** gets mapped to 2MiB - 4KiB readonly. **
********************************************/
/* PML4 */
@ -57,5 +58,10 @@
.p2align MIN_PAGE_SIZE_LOG2
_kernel_pt_bda:
.fill 511, 8, 0x0
.fill 1, 8, 0x0
.set entry, 0x118f
.rept 510
.quad entry
.set entry, entry + 0x1000
.endr
.quad 0x000001

View File

@ -0,0 +1,75 @@
/*
* \brief Platform implementations specific for x86_64
* \author Reto Buerki
* \author Stefan Kalkowski
* \date 2015-05-04
*/
/*
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <bios_data_area.h>
#include <cpu.h>
#include <platform.h>
#include <multiboot.h>
using namespace Genode;
/* contains physical pointer to multiboot */
extern "C" Genode::addr_t __initial_bx;
Platform::Board::Board()
: core_mmio(Memory_region { 0, 0x1000 },
Memory_region { Board::MMIO_LAPIC_BASE,
Board::MMIO_LAPIC_SIZE },
Memory_region { Board::MMIO_IOAPIC_BASE,
Board::MMIO_IOAPIC_SIZE },
Memory_region { __initial_bx & ~0xFFFUL,
get_page_size() })
{
using Mmap = Multiboot_info::Mmap;
static constexpr size_t initial_map_max = 1024 * 1024 * 1024;
for (unsigned i = 0; true; i++) {
Mmap v = Multiboot_info(__initial_bx).phys_ram(i);
if (!v.base) break;
Mmap::Addr::access_t base = v.read<Mmap::Addr>();
Mmap::Length::access_t size = v.read<Mmap::Length>();
/*
* Exclude first physical page, so that it will become part of the
* MMIO allocator. The framebuffer requests this page as MMIO.
*/
if (base == 0 && size >= get_page_size()) {
base = get_page_size();
size -= get_page_size();
}
if (base >= initial_map_max) {
late_ram_regions.add(Memory_region { base, size });
continue;
}
if (base + size <= initial_map_max) {
early_ram_regions.add(Memory_region { base, size });
continue;
}
size_t low_size = initial_map_max - base;
early_ram_regions.add(Memory_region { base, low_size });
late_ram_regions.add(Memory_region { initial_map_max, size - low_size });
}
}
void Platform::enable_mmu() {
Cpu::Cr3::write(Cpu::Cr3::init((addr_t)core_pd->table_base)); }
addr_t Bios_data_area::_mmio_base_virt() { return 0x1ff000; }

View File

@ -0,0 +1,39 @@
/*
* \brief Platform implementations specific for x86_64
* \author Reto Buerki
* \author Stefan Kalkowski
* \date 2015-05-04
*/
/*
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <cpu.h>
#include <platform.h>
#include <muen/sinfo.h>
using namespace Genode;
Platform::Board::Board()
: core_mmio(Memory_region { Sinfo::PHYSICAL_BASE_ADDR, Sinfo::SIZE },
Memory_region { TIMER_BASE_ADDR, TIMER_SIZE },
Memory_region { TIMER_PREEMPT_BASE_ADDR, TIMER_PREEMPT_SIZE })
{
struct Sinfo::Memregion_info region;
Sinfo sinfo(Sinfo::PHYSICAL_BASE_ADDR);
if (!sinfo.get_memregion_info("ram", &region))
error("Unable to retrieve base-hw ram region");
else
early_ram_regions.add(Memory_region { region.address, region.size });
}
void Platform::enable_mmu() {
Cpu::Cr3::write(Cpu::Cr3::init((addr_t)core_pd->table_base)); }

View File

@ -0,0 +1,32 @@
/*
* \brief Platform implementations specific for base-hw and Zynq
* \author Johannes Schlatow
* \author Stefan Kalkowski
* \date 2014-12-15
*/
/*
* Copyright (C) 2014-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <platform.h>
Platform::Board::Board()
: early_ram_regions(Memory_region { RAM_0_BASE + 0x1000,
RAM_0_SIZE - 0x1000 }),
late_ram_regions(Memory_region { RAM_0_BASE, 0x1000 }),
core_mmio(Memory_region { CORTEX_A9_PRIVATE_MEM_BASE,
CORTEX_A9_PRIVATE_MEM_SIZE },
Memory_region { KERNEL_UART_BASE,
KERNEL_UART_SIZE },
Memory_region { PL310_MMIO_BASE,
PL310_MMIO_SIZE }) { }
bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) {
return false; }

View File

@ -0,0 +1,28 @@
/*
* \brief Thread implementation needed by cxx library
* \author Stefan Kalkowski
* \date 2016-10-19
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* base includes */
#include <base/thread.h>
/* local includes */
#include <assert.h>
Genode::Thread * Genode::Thread::myself()
{
assert(false);
return nullptr;
}
Genode::Thread::Name Genode::Thread::name() const { return "bootstrap"; }

View File

@ -12,40 +12,16 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/log.h>
/* base-internal includes */
#include <base/internal/output.h>
#include <base/internal/raw_write_string.h>
#include <base/internal/unmanaged_singleton.h>
#include <core_log.h>
#include <serial.h>
#include <kernel/log.h>
static void out_char(char const c)
{
using Genode::Serial;
enum {
ASCII_LINE_FEED = 10,
ASCII_CARRIAGE_RETURN = 13,
BAUD_RATE = 115200
};
Serial & serial = *unmanaged_singleton<Serial>(BAUD_RATE);
if (c == ASCII_LINE_FEED) serial.put_char(ASCII_CARRIAGE_RETURN);
serial.put_char(c);
}
void Genode::Core_log::out(char const c) { out_char(c); }
void Kernel::log(char const c) { out_char(c); }
void Genode::Core_log::out(char const c) { Kernel::log(c); }
void Genode::raw_write_string(char const *str) {
while (char c = *str++) out_char(c); }
while (char c = *str++) Kernel::log(c); }

View File

@ -59,9 +59,9 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
/* map the dataspace's physical pages to corresponding virtual addresses */
unsigned num_pages = page_rounded_size >> get_page_size_log2();
Page_flags const flags = Page_flags::apply_mapping(ds->writable(),
ds->cacheability(),
ds->io_mem());
Page_flags const flags { ds->writable() ? RW : RO, NO_EXEC, USER,
NO_GLOBAL, ds->io_mem() ? DEVICE : RAM,
ds->cacheability() };
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages, flags))
return nullptr;

View File

@ -0,0 +1,44 @@
/*
* \brief Boot information
* \author Stefan Kalkowski
* \date 2016-10-26
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _BOOTINFO_H_
#define _BOOTINFO_H_
#include <core_mmio.h>
#include <translation_table.h>
#include <translation_table_allocator_tpl.h>
namespace Genode { struct Bootinfo; }
struct Genode::Bootinfo
{
using Table = Translation_table;
static constexpr size_t COUNT = Table::CORE_TRANS_TABLE_COUNT;
using Table_allocator = Translation_table_allocator_tpl<COUNT>;
using Mapping_pool = Array<Mapping, 32>;
Table * const table;
Table_allocator * const table_allocator;
Mapping_pool const elf_mappings;
Core_mmio const core_mmio;
Memory_region_array ram_regions;
Bootinfo(Table * const table,
Table_allocator * const table_alloc,
Mapping_pool const elf_mappings,
Core_mmio const core_mmio)
: table(table), table_allocator(table_alloc),
elf_mappings(elf_mappings), core_mmio(core_mmio) {}
};
#endif /* _BOOTINFO_H_ */

View File

@ -0,0 +1,57 @@
/*
* \brief Representation of core's MMIO space
* \author Stefan Kalkowski
* \date 2016-11-24
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CORE_MMIO_H_
#define _CORE_MMIO_H_
#include <mapping.h>
#include <memory_region.h>
#include <util.h>
namespace Genode { struct Core_mmio; }
struct Genode::Core_mmio : Genode::Memory_region_array
{
using Memory_region_array::Memory_region_array;
struct Not_found {};
template <typename FUNC>
void for_each_mapping(FUNC f) const
{
addr_t virt_base = 0xf0000000UL; /* FIXME */
auto lambda = [&] (Memory_region const & r) {
f(Mapping { r.base, virt_base, r.size, PAGE_FLAGS_KERN_IO });
virt_base += r.size + get_page_size();
};
for_each(lambda);
}
addr_t virt_addr(addr_t phys_addr) const
{
/*
* Sadly this method is used quite early in the kernel
* where no exceptions can be used
*/
addr_t ret = 0;
for_each_mapping([&] (Mapping const & m)
{
if (phys_addr >= m.phys() && phys_addr < (m.phys()+m.size()))
ret = m.virt() + (phys_addr-m.phys());
});
return ret;
}
};
#endif /* _CORE_MMIO_H_ */

View File

@ -61,7 +61,7 @@ namespace Kernel
Cpu_pool * cpu_pool();
}
class Kernel::Cpu_context : Genode::Cpu::Context
class Kernel::Cpu_context : public Genode::Cpu::Context
{
private:
@ -292,7 +292,7 @@ class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout
* \param core_pd core's pd object
* \param board object encapsulating board specifics
*/
void init(Pic &pic, Kernel::Pd &core_pd, Genode::Board & board);
void init(Pic &pic/*, Kernel::Pd &core_pd, Genode::Board & board*/);
/**
* Raise the IPI of the CPU

View File

@ -36,7 +36,7 @@ namespace Kernel
* control provides a simple interface to access the code from within
* the kernel.
*/
class Mode_transition_control;
struct Mode_transition_control;
/**
* Return the system wide mode-transition control
@ -49,86 +49,40 @@ namespace Kernel
class Pd;
}
class Kernel::Mode_transition_control
struct Kernel::Mode_transition_control
{
friend class Pd;
/**
* Map the mode transition page to a virtual address space
*
* \param tt translation buffer of the address space
* \param alloc translation table allocator used for the mapping
*/
void map(Genode::Translation_table * tt,
Genode::Translation_table_allocator * alloc);
private:
/**
* Continue execution of client context
*
* \param context targeted CPU context
* \param cpu kernel name of targeted CPU
* \param entry_raw raw pointer to assembly entry-code
* \param context_ptr_base base address of client-context pointer region
*/
void switch_to(Cpu::Context * const context,
unsigned const cpu,
addr_t const entry_raw,
addr_t const context_ptr_base);
/*
* set the table allocator to the current minimum of bits-of-one-mword
* this is a limitation of the Bit_allocator used within this allocator.
* actually only one page-mapping is needed by the MTC allocator
*/
typedef Genode::Translation_table_allocator_tpl<64> Allocator;
typedef Genode::Translation_table Table;
Allocator _alloc;
Table _table;
Cpu_context _master;
/**
* Return size of the mode transition
*/
static size_t _size();
/**
* Return size of master-context space in the mode transition
*/
static size_t _master_context_size();
/**
* Return virtual address of the user entry-code
*/
static addr_t _virt_user_entry();
public:
enum {
SIZE = Cpu::mtc_size,
VIRT_BASE = Cpu::exception_entry,
ALIGN_LOG2 = Genode::Translation_table::ALIGNM_LOG2,
ALIGN = 1 << ALIGN_LOG2,
};
/**
* Constructor
*
* \param c CPU context for kernel mode entry
*/
Mode_transition_control();
/**
* Map the mode transition page to a virtual address space
*
* \param tt translation buffer of the address space
* \param alloc translation table allocator used for the mapping
*/
void map(Genode::Translation_table * tt,
Genode::Translation_table_allocator * alloc);
/**
* Continue execution of client context
*
* \param context targeted CPU context
* \param cpu kernel name of targeted CPU
* \param entry_raw raw pointer to assembly entry-code
* \param context_ptr_base base address of client-context pointer region
*/
void switch_to(Cpu::Context * const context,
unsigned const cpu,
addr_t const entry_raw,
addr_t const context_ptr_base);
/**
* Continue execution of user context
*
* \param context targeted CPU context
* \param cpu kernel name of targeted CPU
*/
void switch_to_user(Cpu::Context * const context,
unsigned const cpu);
} __attribute__((aligned(Mode_transition_control::ALIGN)));
/**
* Continue execution of user context
*
* \param context targeted CPU context
* \param cpu kernel name of targeted CPU
*/
void switch_to_user(Cpu::Context * const context,
unsigned const cpu);
};
class Kernel::Pd : public Cpu::Pd,

View File

@ -30,8 +30,7 @@ namespace Genode {
* \return true on success
*/
bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages,
Page_flags flags = { true, true, false, false,
false, CACHED });
Page_flags flags = PAGE_FLAGS_KERN_DATA);
/**
* Unmap pages from core's address space

View File

@ -14,39 +14,50 @@
#ifndef _MAPPING_H_
#define _MAPPING_H_
#include <base/output.h>
#include <memory_region.h>
#include <page_flags.h>
namespace Genode { struct Mapping; }
namespace Genode { class Mapping; }
struct Genode::Mapping
class Genode::Mapping
{
addr_t phys = 0;
addr_t virt = 0;
size_t size = 0;
Page_flags flags;
private:
Mapping() {}
Memory_region _phys { 0, 0 };
addr_t _virt = 0;
Page_flags _flags { RO, NO_EXEC, KERN, NO_GLOBAL, RAM, CACHED };
Mapping(addr_t virt, addr_t phys, Cache_attribute cacheable,
bool io, unsigned size_log2, bool writeable)
: phys(phys), virt(virt), size(1 << size_log2),
flags{ writeable, true, false, false, io, cacheable } {}
public:
Mapping(addr_t phys, addr_t virt, size_t size, Page_flags flags)
: phys(phys), virt(virt), size(size), flags(flags) {}
Mapping() {}
void print(Output & out) const
{
Genode::print(out, "phys=", (void*)phys, " => virt=", (void*) virt,
" (size=", Hex(size, Hex::PREFIX, Hex::PAD),
" page-flags: ", flags, ")");
}
Mapping(addr_t phys, addr_t virt, size_t size, Page_flags flags)
: _phys(phys, size), _virt(virt), _flags(flags) {}
/**
* Dummy implementation used by generic region_map code
*/
void prepare_map_operation() {}
void print(Output & out) const
{
Genode::print(out, "physical region(", _phys,
") => virtual address=", (void*) _virt,
" with page-flags: ", _flags, ")");
}
addr_t phys() const { return _phys.base; }
addr_t virt() const { return _virt; }
size_t size() const { return _phys.size; }
Page_flags flags() const { return _flags; }
/***********************************************
** Interface used by generic region_map code **
***********************************************/
Mapping(addr_t virt, addr_t phys, Cache_attribute cacheable,
bool io, unsigned size_log2, bool writeable)
: _phys(phys, 1 << size_log2), _virt(virt),
_flags { writeable ? RW : RO, EXEC, USER, NO_GLOBAL,
io ? DEVICE : RAM, cacheable } {}
void prepare_map_operation() const {}
};
#endif /* _MAPPING_H_ */

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
* Copyright (C) 2014-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@ -17,48 +17,55 @@
#include <base/cache.h>
#include <base/output.h>
namespace Genode { struct Page_flags; }
namespace Genode {
enum Writeable { RO, RW };
enum Executeable { NO_EXEC, EXEC };
enum Privileged { USER, KERN };
enum Global { NO_GLOBAL, GLOBAL };
enum Type { RAM, DEVICE };
struct Page_flags;
}
struct Genode::Page_flags
{
bool writeable;
bool executable;
bool privileged;
bool global;
bool device;
Writeable writeable;
Executeable executable;
Privileged privileged;
Global global;
Type type;
Cache_attribute cacheable;
/**
* Create flag POD for Genode pagers
*/
static const Page_flags
apply_mapping(bool const writeable,
Cache_attribute const cacheable,
bool const io_mem) {
return Page_flags { writeable, true, false, false,
io_mem, cacheable }; }
/**
* Create flag POD for the mode transition region
*/
static const Page_flags mode_transition() {
return Page_flags { true, true, true, true, false, CACHED }; }
void print(Output & out) const
{
using Genode::print;
print(out, writeable ? "writeable, " : "readonly, ",
executable ? "exec, " : "noexec, ");
if (privileged) print(out, "privileged, ");
if (global) print(out, "global, ");
if (device) print(out, "iomem, ");
print(out, (writeable == RW) ? "writeable, " : "readonly, ",
(executable ==EXEC) ? "exec, " : "noexec, ");
if (privileged == KERN) print(out, "privileged, ");
if (global == GLOBAL) print(out, "global, ");
if (type == DEVICE) print(out, "iomem, ");
switch (cacheable) {
case UNCACHED: print(out, "uncached"); break;
case CACHED: print(out, "cached"); break;
case WRITE_COMBINED: print(out, "write-combined"); break;
case UNCACHED: print(out, "uncached"); break;
case CACHED: print(out, "cached"); break;
case WRITE_COMBINED: print(out, "write-combined"); break;
};
}
};
namespace Genode {
static constexpr Page_flags PAGE_FLAGS_KERN_IO
{ RW, NO_EXEC, USER, NO_GLOBAL, DEVICE, UNCACHED };
static constexpr Page_flags PAGE_FLAGS_KERN_DATA
{ RW, EXEC, USER, NO_GLOBAL, RAM, CACHED };
static constexpr Page_flags PAGE_FLAGS_KERN_TEXT
{ RW, EXEC, USER, NO_GLOBAL, RAM, CACHED };
static constexpr Page_flags PAGE_FLAGS_KERN_EXCEP
{ RW, EXEC, USER, GLOBAL, RAM, CACHED };
static constexpr Page_flags PAGE_FLAGS_UTCB
{ RW, NO_EXEC, USER, NO_GLOBAL, RAM, CACHED };
}
#endif /* _CORE__INCLUDE__PAGE_FLAGS_H_ */

View File

@ -25,6 +25,7 @@
#include <kernel/core_interface.h>
/* core includes */
#include <bootinfo.h>
#include <translation_table_allocator_tpl.h>
#include <platform_generic.h>
#include <core_region_map.h>
@ -46,6 +47,9 @@ namespace Genode {
Phys_allocator _irq_alloc; /* IRQ allocator */
Rom_fs _rom_fs; /* ROM file system */
static Genode::Bootinfo const & _bootinfo();
static Genode::Memory_region_array const & _core_virt_regions();
/**
* Initialize I/O port allocator
*/
@ -68,9 +72,10 @@ namespace Genode {
public:
Platform();
static addr_t mmio_to_virt(addr_t mmio);
/**
* Return platform IRQ-number for user IRQ-number 'user_irq'
*/
@ -99,23 +104,12 @@ namespace Genode {
static bool get_msi_params(const addr_t mmconf,
addr_t &address, addr_t &data,
unsigned &irq_number);
/**
* Return address of cores translation table allocator
*/
static addr_t core_translation_tables();
/**
* Return size of cores translation table allocator
*/
static constexpr size_t core_translation_tables_size()
{
return round_page(sizeof(Translation_table_allocator_tpl<
Translation_table::CORE_TRANS_TABLE_COUNT>));
}
static addr_t core_phys_addr(addr_t virt);
static Genode::Memory_region_array & ram_regions();
static Memory_region_array & core_ram_regions();
static Genode::Memory_region_array & core_mmio_regions();
static Translation_table * core_translation_table();
static Translation_table_allocator * core_translation_table_allocator();
/********************************

View File

@ -211,29 +211,9 @@ class Genode::Platform_pd : public Hw::Address_space,
};
class Genode::Core_platform_pd : public Genode::Platform_pd
struct Genode::Core_platform_pd : Genode::Platform_pd
{
private:
static inline Translation_table * const _table();
static inline Translation_table_allocator * const _table_alloc();
/**
* Establish initial one-to-one mappings for core/kernel.
* This function avoids to take the core-pd's translation table
* lock in contrast to normal translation insertions to
* circumvent strex/ldrex problems in early bootstrap code
* on some ARM SoCs.
*
* \param start physical/virtual start address of area
* \param size size of area
* \param io_mem true if it should be marked as device memory
*/
void _map(addr_t start, size_t size, bool io_mem);
public:
Core_platform_pd();
Core_platform_pd();
};
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */

View File

@ -169,8 +169,8 @@ class Genode::Arm
{
access_t v = Ba::masked((addr_t)table);
Rgn::set(v, CACHEABLE);
S::set(v, Kernel::board().is_smp() ? 1 : 0);
if (Kernel::board().is_smp()) Irgn::set(v, CACHEABLE);
S::set(v, Board::SMP ? 1 : 0);
if (Board::SMP) Irgn::set(v, CACHEABLE);
else C::set(v, 1);
return v;
}
@ -488,12 +488,27 @@ class Genode::Arm
*/
void clean_invalidate_data_cache();
/**
* Invalidate all branch predictions
*/
static void invalidate_branch_predicts() {
asm volatile ("mcr p15, 0, r0, c7, c5, 6" ::: "r0"); };
/**
* Switch on MMU and caches
*
* \param pd kernel's pd object
* \param table page tables physical address
*/
void enable_mmu_and_caches(Kernel::Pd & pd);
void enable_mmu_and_caches(Genode::addr_t table)
{
invalidate_tlb();
Cidr::write(0);
Dacr::write(Dacr::init_virt_kernel());
Ttbr0::write(Ttbr0::init(table));
Ttbcr::write(0);
Sctlr::enable_mmu_and_caches();
invalidate_branch_predicts();
}
/**
* Invalidate all TLB entries of the address space named 'pid'
@ -504,7 +519,7 @@ class Genode::Arm
/**
* Invalidate all TLB entries
*/
void invalidate_tlb() {
static void invalidate_tlb() {
asm volatile ("mcr p15, 0, %0, c8, c7, 0" :: "r" (0) : ); }
static constexpr addr_t line_size = 1 << Board::CACHE_LINE_SIZE_LOG2;

View File

@ -19,10 +19,7 @@
/* Genode includes */
#include <util/mmio.h>
namespace Arm
{
struct Pl310;
}
namespace Arm { struct Pl310; }
/**
@ -68,7 +65,8 @@ class Arm::Pl310 : public Genode::Mmio
Pl310(Genode::addr_t const base) : Mmio(base) { }
void enable() {}
void enable() {}
void disable() {}
void clean_invalidate()
{

View File

@ -61,15 +61,18 @@ class Genode::Translation
_create(Page_flags const & f, addr_t const pa)
{
typename T::access_t v = T::Pa::masked(pa);
T::S::set(v, Kernel::board().is_smp());
T::S::set(v, Board::SMP);
T::Ng::set(v, !f.global);
T::Xn::set(v, !f.executable);
if (f.device) { T::Tex::set(v, _device_tex()); }
else {
switch (f.cacheable) {
case CACHED: T::Tex::set(v, 5);
case WRITE_COMBINED: T::B::set(v, 1); break;
case UNCACHED: T::Tex::set(v, 1); break; } }
if (f.type == DEVICE) {
T::Tex::set(v, _device_tex());
} else {
switch (f.cacheable) {
case CACHED: T::Tex::set(v, 5);
case WRITE_COMBINED: T::B::set(v, 1); break;
case UNCACHED: T::Tex::set(v, 1); break;
}
}
if (f.writeable) if (f.privileged) T::Ap::set(v, 1);
else T::Ap::set(v, 3);
else if (f.privileged) T::Ap::set(v, 5);

View File

@ -210,17 +210,7 @@ class Genode::Pic
enum { NR_OF_IRQ = Distr::nr_of_irq };
/**
* Constructor
*/
Pic()
: _distr(Board::IRQ_CONTROLLER_DISTR_BASE),
_cpui (Board::IRQ_CONTROLLER_CPU_BASE),
_last_iar(Cpui::Iar::Irq_id::bits(spurious_id)),
_max_irq(_distr.max_irq())
{
_init();
}
Pic();
/**
* Initialize CPU local interface of the controller

View File

@ -119,20 +119,6 @@ class Genode::Arm_v7 : public Arm
asm volatile ("mcr p15, 0, %[v], c10, c2, 0" :: [v]"r"(v) : ); }
};
/**
* Invalidate all branch predictions
*/
static void invalidate_branch_predicts() {
asm volatile ("mcr p15, 0, r0, c7, c5, 6" ::: "r0"); };
/**
* Switch on MMU and caches
*
* \param pd kernel's pd object
*/
void enable_mmu_and_caches(Kernel::Pd& pd);
/**
* Finish all previous data transfers
*/

View File

@ -203,7 +203,9 @@ class Genode::Long_translation_table
static typename Descriptor::access_t create(Page_flags const &f)
{
if (f.device) { return Attribute_index::bits(DEVICE); }
if (f.type == Genode::DEVICE)
return Attribute_index::bits(DEVICE);
switch (f.cacheable) {
case CACHED: return Attribute_index::bits(CACHED);
case WRITE_COMBINED:

View File

@ -16,6 +16,7 @@
#define _CORE__INCLUDE__SPEC__CORTEX_A15__CPU_H_
/* core includes */
#include <translation_table.h>
#include <spec/arm_v7/cpu_support.h>
namespace Genode { class Cpu; }
@ -431,7 +432,22 @@ class Genode::Cpu : public Arm_v7
* Hook function called at the very beginning
* of the local cpu initialization
*/
void init();
void init(Genode::Translation_table&);
/**
* Switch on MMU and caches
*
* \param table physical page table address
*/
void enable_mmu_and_caches(Genode::addr_t table)
{
Cpu::Mair0::write(Cpu::Mair0::init_virt_kernel());
Cpu::Dacr::write(Cpu::Dacr::init_virt_kernel());
Cpu::Ttbr0::write(Cpu::Ttbr0::init(table, 0));
Cpu::Ttbcr::write(Cpu::Ttbcr::init_virt_kernel());
Cpu::Sctlr::enable_mmu_and_caches();
invalidate_branch_predicts();
}
/*************

View File

@ -18,23 +18,15 @@
#include <drivers/board_base.h>
#include <spec/arm/pl310.h>
namespace Cortex_a9
{
/**
* Board driver
*/
class Board;
}
namespace Cortex_a9 { class Board; }
class Cortex_a9::Board : public Genode::Board_base
{
protected:
public:
using L2_cache = Arm::Pl310;
L2_cache _l2_cache;
public:
static constexpr bool SMP = true;
enum Errata {
ARM_754322,
@ -61,14 +53,17 @@ class Cortex_a9::Board : public Genode::Board_base
PRIVATE_TIMER_IRQ = 29,
};
Board() : _l2_cache(Genode::Board_base::PL310_MMIO_BASE) {}
Board();
L2_cache & l2_cache() { return _l2_cache; }
void init() { }
void wake_up_all_cpus(void * const ip);
bool is_smp() { return true; }
bool errata(Errata);
protected:
L2_cache _l2_cache;
};
#endif /* _CORE__INCLUDE__SPEC__CORTEX_A9__BOARD_SUPPORT_H_ */

View File

@ -74,7 +74,7 @@ class Genode::Cortex_a9 : public Arm_v7
static void write(access_t const v) {
asm volatile ("mcr p15, 0, %0, c1, c0, 1" :: "r" (v) : ); }
static void enable_smp()
static void enable_smp(Board&)
{
access_t v = read();
Smp::set(v, 1);

View File

@ -18,54 +18,47 @@
/* local includes */
#include <board.h>
namespace Genode {
class Scu;
}
namespace Genode { struct Scu; }
class Genode::Scu : Genode::Mmio
struct Genode::Scu : Genode::Mmio
{
private:
struct Cr : Register<0x0, 32>
{
struct Enable : Bitfield<0, 1> { };
};
struct Cr : Register<0x0, 32>
{
struct Enable : Bitfield<0, 1> { };
};
struct Dcr : Register<0x30, 32>
{
struct Bit_0 : Bitfield<0, 1> { };
};
struct Dcr : Register<0x30, 32>
{
struct Bit_0 : Bitfield<0, 1> { };
};
struct Iassr : Register<0xc, 32>
{
struct Cpu0_way : Bitfield<0, 4> { };
struct Cpu1_way : Bitfield<4, 4> { };
struct Cpu2_way : Bitfield<8, 4> { };
struct Cpu3_way : Bitfield<12, 4> { };
};
struct Iassr : Register<0xc, 32>
{
struct Cpu0_way : Bitfield<0, 4> { };
struct Cpu1_way : Bitfield<4, 4> { };
struct Cpu2_way : Bitfield<8, 4> { };
struct Cpu3_way : Bitfield<12, 4> { };
};
Scu() : Mmio(Board::SCU_MMIO_BASE) { }
Board &_board;
public:
Scu(Board & board) : Mmio(Board::SCU_MMIO_BASE), _board(board) { }
void invalidate()
{
Iassr::access_t iassr = 0;
for (Iassr::access_t way = 0; way <= Iassr::Cpu0_way::mask();
way++) {
Iassr::Cpu0_way::set(iassr, way);
Iassr::Cpu1_way::set(iassr, way);
Iassr::Cpu2_way::set(iassr, way);
Iassr::Cpu3_way::set(iassr, way);
write<Iassr>(iassr);
}
void invalidate()
{
Iassr::access_t iassr = 0;
for (Iassr::access_t way = 0; way <= Iassr::Cpu0_way::mask();
way++) {
Iassr::Cpu0_way::set(iassr, way);
Iassr::Cpu1_way::set(iassr, way);
Iassr::Cpu2_way::set(iassr, way);
Iassr::Cpu3_way::set(iassr, way);
write<Iassr>(iassr);
}
}
void enable()
{
if (_board.errata(Board::ARM_764369)) write<Dcr::Bit_0>(1);
write<Cr::Enable>(1);
}
void enable(Board & board)
{
if (board.errata(Board::ARM_764369)) write<Dcr::Bit_0>(1);
write<Cr::Enable>(1);
}
};

View File

@ -70,13 +70,7 @@ class Genode::Timer : public Mmio
public:
/**
* Constructor
*/
Timer() : Mmio(Board::PRIVATE_TIMER_MMIO_BASE)
{
write<Control::Timer_enable>(0);
}
Timer();
/**
* Return kernel name of timer interrupt
@ -89,21 +83,7 @@ class Genode::Timer : public Mmio
*
* \param tics delay of timer interrupt
*/
void start_one_shot(time_t const tics, unsigned const)
{
enum { PRESCALER = Board::CORTEX_A9_PRIVATE_TIMER_DIV - 1 };
/* reset timer */
write<Interrupt_status::Event>(1);
Control::access_t control = 0;
Control::Irq_enable::set(control, 1);
Control::Prescaler::set(control, PRESCALER);
write<Control>(control);
/* load timer and start decrementing */
write<Load>(tics);
write<Control::Timer_enable>(1);
}
void start_one_shot(time_t const tics, unsigned const);
time_t tics_to_us(time_t const tics) const {
return (tics / TICS_PER_MS) * 1000; }
@ -119,6 +99,6 @@ class Genode::Timer : public Mmio
time_t max_value() { return (Load::access_t)~0; }
};
namespace Kernel { class Timer : public Genode::Timer { }; }
namespace Kernel { using Genode::Timer; }
#endif /* _CORE__INCLUDE__SPEC__CORTEX_A9__TIMER_H_ */

View File

@ -36,7 +36,7 @@ namespace Genode
"sev\n");
}
static bool is_smp() { return true; }
static constexpr bool SMP = true;
};
}

View File

@ -17,6 +17,7 @@
/* core includes */
#include <board.h>
#include <platform.h>
/* Genode includes */
#include <drivers/uart_base.h>
@ -37,7 +38,7 @@ namespace Genode
*/
Serial(unsigned const baud_rate)
:
Exynos_uart_base(Board::UART_2_MMIO_BASE,
Exynos_uart_base(Platform::mmio_to_virt(Board::UART_2_MMIO_BASE),
Board::UART_2_CLOCK, baud_rate)
{ }
};

View File

@ -19,6 +19,7 @@
/* core include */
#include <board.h>
#include <platform.h>
/* Genode includes */
#include <util/mmio.h>
@ -207,7 +208,7 @@ class Genode::Timer : public Mmio
*/
Timer()
:
Mmio(Board::MCT_MMIO_BASE),
Mmio(Platform::mmio_to_virt(Board::MCT_MMIO_BASE)),
_tics_per_ms(_calc_tics_per_ms(Board::MCT_CLOCK))
{
Mct_cfg::access_t mct_cfg = 0;

Some files were not shown because too many files have changed in this diff Show More