2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief OKL4 platform interface implementation
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2009-03-31
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2009-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <base/allocator_avl.h>
|
|
|
|
#include <base/sleep.h>
|
|
|
|
#include <util/misc_math.h>
|
|
|
|
|
2016-01-22 14:31:58 +01:00
|
|
|
/* base-internal includes */
|
|
|
|
#include <base/internal/crt0.h>
|
2016-03-03 17:57:29 +01:00
|
|
|
#include <base/internal/stack_area.h>
|
2016-06-13 13:53:58 +02:00
|
|
|
#include <base/internal/native_utcb.h>
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/internal/globals.h>
|
2016-01-22 14:31:58 +01:00
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/* core includes */
|
2016-09-15 16:08:33 +02:00
|
|
|
#include <boot_modules.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
#include <core_parent.h>
|
|
|
|
#include <platform.h>
|
|
|
|
#include <platform_thread.h>
|
|
|
|
#include <platform_pd.h>
|
|
|
|
#include <map_local.h>
|
|
|
|
|
|
|
|
/* OKL4 includes */
|
|
|
|
namespace Okl4 {
|
|
|
|
#include <l4/ipc.h>
|
|
|
|
#include <l4/schedule.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************
|
|
|
|
** Support for core memory management **
|
|
|
|
****************************************/
|
|
|
|
|
2015-09-17 14:16:59 +02:00
|
|
|
bool Mapped_mem_allocator::_map_local(addr_t virt_addr, addr_t phys_addr,
|
|
|
|
unsigned size) {
|
2014-03-10 15:24:53 +01:00
|
|
|
return map_local(phys_addr, virt_addr, size / get_page_size()); }
|
|
|
|
|
|
|
|
|
2016-07-15 11:05:09 +02:00
|
|
|
bool Mapped_mem_allocator::_unmap_local(addr_t virt_addr, addr_t phys_addr,
|
|
|
|
unsigned size) {
|
2014-03-10 15:24:53 +01:00
|
|
|
return unmap_local(virt_addr, size / get_page_size()); }
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
** Boot-info parser **
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
int Platform::bi_init_mem(Okl4::uintptr_t virt_base, Okl4::uintptr_t virt_end,
|
|
|
|
Okl4::uintptr_t phys_base, Okl4::uintptr_t phys_end,
|
|
|
|
const Okl4::bi_user_data_t *data)
|
|
|
|
{
|
|
|
|
Platform *p = (Platform *)data->user_data;
|
|
|
|
p->_core_mem_alloc.phys_alloc()->add_range(phys_base, phys_end - phys_base + 1);
|
|
|
|
p->_core_mem_alloc.virt_alloc()->add_range(virt_base, virt_end - virt_base + 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Platform::bi_add_virt_mem(Okl4::bi_name_t pool, Okl4::uintptr_t base,
|
|
|
|
Okl4::uintptr_t end, const Okl4::bi_user_data_t *data)
|
|
|
|
{
|
|
|
|
/* prevent first page from being added to core memory */
|
|
|
|
if (base < get_page_size() || end < get_page_size())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Platform *p = (Platform *)data->user_data;
|
|
|
|
p->_core_mem_alloc.virt_alloc()->add_range(base, end - base + 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Platform::bi_add_phys_mem(Okl4::bi_name_t pool, Okl4::uintptr_t base,
|
|
|
|
Okl4::uintptr_t end, const Okl4::bi_user_data_t *data)
|
|
|
|
{
|
|
|
|
if (pool == 2) {
|
|
|
|
Platform *p = (Platform *)data->user_data;
|
|
|
|
p->_core_mem_alloc.phys_alloc()->add_range(base, end - base + 1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 16:08:33 +02:00
|
|
|
void Platform::_setup_rom()
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
2016-09-15 16:08:33 +02:00
|
|
|
/* add boot modules to ROM FS */
|
|
|
|
Boot_modules_header * header = &_boot_modules_headers_begin;
|
|
|
|
for (; header < &_boot_modules_headers_end; header++) {
|
|
|
|
Rom_module * rom = new (core_mem_alloc())
|
|
|
|
Rom_module(header->base, header->size, (const char*)header->name);
|
|
|
|
_rom_fs.insert(rom);
|
2011-12-22 16:19:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-10 15:24:53 +01:00
|
|
|
static char init_slab_block_rom[get_page_size()];
|
|
|
|
static char init_slab_block_thread[get_page_size()];
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
Platform::Platform() :
|
|
|
|
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
|
2014-03-10 15:24:53 +01:00
|
|
|
_irq_alloc(core_mem_alloc()),
|
|
|
|
_rom_slab(core_mem_alloc(), (Slab_block *)&init_slab_block_rom),
|
|
|
|
_thread_slab(core_mem_alloc(), (Slab_block *)&init_slab_block_thread)
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We must be single-threaded at this stage and so this is safe.
|
|
|
|
*/
|
|
|
|
static bool initialized = 0;
|
|
|
|
if (initialized) panic("Platform constructed twice!");
|
|
|
|
initialized = true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine address of boot-info structure. On startup, the OKL4 kernel
|
|
|
|
* provides this address in roottask's UTCB message register 1.
|
|
|
|
*/
|
|
|
|
Okl4::L4_Word_t boot_info_addr;
|
|
|
|
Okl4::L4_StoreMR(1, &boot_info_addr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Request base address for UTCB locations
|
|
|
|
*/
|
|
|
|
_utcb_base = (addr_t)Okl4::utcb_base_get();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Define our own thread ID
|
|
|
|
*/
|
|
|
|
Okl4::__L4_TCR_Set_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF, Okl4::L4_rootserver.raw);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* By default, the first roottask thread is executed at maxiumum priority.
|
|
|
|
* To make preemptive scheduler work as expected, we set the priority of
|
|
|
|
* ourself to the default priority of all other threads, which is 100 on
|
|
|
|
* OKL4.
|
|
|
|
*/
|
|
|
|
L4_Set_Priority(Okl4::L4_Myself(), Platform_thread::DEFAULT_PRIORITY);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Invoke boot-info parser for determining the memory configuration and
|
|
|
|
* the location of the boot modules.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize callback function for parsing the boot-info
|
|
|
|
*
|
|
|
|
* The supplied callback functions differ slightly from the interface
|
|
|
|
* used by the boot-info library in that they do not have a return
|
|
|
|
* type.
|
|
|
|
*/
|
|
|
|
static Okl4::bi_callbacks_t callbacks;
|
|
|
|
callbacks.init_mem = Platform::bi_init_mem;
|
|
|
|
callbacks.add_virt_mem = Platform::bi_add_virt_mem;
|
|
|
|
callbacks.add_phys_mem = Platform::bi_add_phys_mem;
|
|
|
|
|
|
|
|
Okl4::bootinfo_parse((void *)boot_info_addr, &callbacks, this);
|
|
|
|
|
|
|
|
/* initialize interrupt allocator */
|
|
|
|
_irq_alloc.add_range(0, 0x10);
|
|
|
|
|
|
|
|
/* I/O memory could be the whole user address space */
|
|
|
|
_io_mem_alloc.add_range(0, ~0);
|
|
|
|
|
|
|
|
/* I/O port allocator (only meaningful for x86) */
|
|
|
|
_io_port_alloc.add_range(0, 0x10000);
|
|
|
|
|
2016-09-15 16:08:33 +02:00
|
|
|
_setup_rom();
|
|
|
|
|
2016-01-23 14:42:55 +01:00
|
|
|
/* preserve stack area in core's virtual address space */
|
2016-03-03 17:57:29 +01:00
|
|
|
_core_mem_alloc.virt_alloc()->remove_range(stack_area_virtual_base(),
|
|
|
|
stack_area_virtual_size());
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
_vm_start = 0x1000;
|
|
|
|
_vm_size = 0xb0000000 - 0x1000;
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
init_log();
|
|
|
|
|
|
|
|
log(":phys_alloc: "); (*_core_mem_alloc.phys_alloc())()->dump_addr_tree();
|
|
|
|
log(":virt_alloc: "); (*_core_mem_alloc.virt_alloc())()->dump_addr_tree();
|
|
|
|
log(":io_mem: "); _io_mem_alloc()->dump_addr_tree();
|
|
|
|
log(":io_port: "); _io_port_alloc()->dump_addr_tree();
|
|
|
|
log(":irq: "); _irq_alloc()->dump_addr_tree();
|
|
|
|
log(":rom_fs: "); _rom_fs.print_fs();
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
/* setup task object for core task */
|
|
|
|
_core_pd = new(core_mem_alloc()) Platform_pd(true);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We setup the thread object for thread0 in core task using a special
|
|
|
|
* interface that allows us to specify the thread ID. For core this creates
|
|
|
|
* the situation that task_id == thread_id of first task. But since we do
|
|
|
|
* not destroy this task, it should be no problem.
|
|
|
|
*/
|
|
|
|
Platform_thread *core_thread =
|
2014-10-16 11:15:46 +02:00
|
|
|
new(&_thread_slab) Platform_thread(0, "core.main");
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
core_thread->set_l4_thread_id(Okl4::L4_rootserver);
|
|
|
|
|
|
|
|
_core_pd->bind_thread(core_thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************
|
|
|
|
** Generic platform interface **
|
|
|
|
********************************/
|
|
|
|
|
|
|
|
void Platform::wait_for_exit()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* On OKL4, core never exits. So let us sleep forever.
|
|
|
|
*/
|
|
|
|
sleep_forever();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Core_parent::exit(int exit_value) { }
|