2012-05-30 20:13:09 +02:00
|
|
|
/*
|
|
|
|
* \brief Platform implementation specific for hw
|
|
|
|
* \author Martin Stein
|
2014-04-28 21:31:57 +02:00
|
|
|
* \author Stefan Kalkowski
|
2012-05-30 20:13:09 +02:00
|
|
|
* \date 2011-12-21
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2011-2017 Genode Labs GmbH
|
2012-05-30 20:13:09 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2012-05-30 20:13:09 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
2016-06-16 15:55:36 +02:00
|
|
|
#include <base/log.h>
|
2012-05-30 20:13:09 +02:00
|
|
|
|
|
|
|
/* core includes */
|
2016-09-15 16:08:33 +02:00
|
|
|
#include <boot_modules.h>
|
2017-02-21 13:46:59 +01:00
|
|
|
#include <hw/memory_region.h>
|
2014-04-28 21:31:57 +02:00
|
|
|
#include <map_local.h>
|
2012-05-30 20:13:09 +02:00
|
|
|
#include <platform.h>
|
2014-04-28 21:31:57 +02:00
|
|
|
#include <platform_pd.h>
|
2017-02-21 13:46:59 +01:00
|
|
|
#include <hw/page_flags.h>
|
|
|
|
#include <hw/util.h>
|
2014-04-28 21:31:57 +02:00
|
|
|
#include <pic.h>
|
|
|
|
#include <kernel/kernel.h>
|
|
|
|
#include <translation_table.h>
|
2017-03-23 03:06:53 +01:00
|
|
|
#include <kernel/cpu.h>
|
2012-05-30 20:13:09 +02:00
|
|
|
|
2016-03-03 17:57:29 +01:00
|
|
|
/* base-internal includes */
|
2016-10-06 20:07:16 +02:00
|
|
|
#include <base/internal/crt0.h>
|
2016-03-03 17:57:29 +01:00
|
|
|
#include <base/internal/stack_area.h>
|
|
|
|
|
2012-05-30 20:13:09 +02:00
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
|
|
|
|
/**************
|
|
|
|
** Platform **
|
|
|
|
**************/
|
|
|
|
|
2017-02-21 13:46:59 +01:00
|
|
|
Hw::Boot_info const & Platform::_boot_info() {
|
|
|
|
return *reinterpret_cast<Hw::Boot_info*>(round_page((addr_t)&_prog_img_end)); }
|
2015-06-25 15:53:39 +02:00
|
|
|
|
2016-11-07 18:00:24 +01:00
|
|
|
addr_t Platform::mmio_to_virt(addr_t mmio) {
|
2017-02-21 13:46:59 +01:00
|
|
|
return _boot_info().mmio_space.virt_addr(mmio); }
|
2015-06-25 15:53:39 +02:00
|
|
|
|
2017-02-21 13:46:59 +01:00
|
|
|
Hw::Page_table & Platform::core_page_table() {
|
|
|
|
return *(Hw::Page_table*)_boot_info().table; }
|
2012-05-30 20:13:09 +02:00
|
|
|
|
2017-02-21 13:46:59 +01:00
|
|
|
Hw::Page_table::Allocator & Platform::core_page_table_allocator()
|
|
|
|
{
|
|
|
|
using Allocator = Hw::Page_table::Allocator;
|
|
|
|
using Array = Allocator::Array<Hw::Page_table::CORE_TRANS_TABLE_COUNT>;
|
|
|
|
return unmanaged_singleton<Array>(*((Array*)_boot_info().table_allocator))->alloc();
|
|
|
|
}
|
2016-10-06 20:07:16 +02:00
|
|
|
|
|
|
|
void Platform::_init_io_mem_alloc()
|
|
|
|
{
|
|
|
|
/* add entire adress space minus the RAM memory regions */
|
|
|
|
_io_mem_alloc.add_range(0, ~0x0UL);
|
2017-02-21 13:46:59 +01:00
|
|
|
_boot_info().ram_regions.for_each([this] (Hw::Memory_region const &r) {
|
2016-10-06 20:07:16 +02:00
|
|
|
_io_mem_alloc.remove_range(r.base, r.size); });
|
|
|
|
};
|
2014-04-28 21:31:57 +02:00
|
|
|
|
2012-05-30 20:13:09 +02:00
|
|
|
|
2017-02-21 13:46:59 +01:00
|
|
|
Hw::Memory_region_array const & Platform::_core_virt_regions()
|
2016-11-07 18:00:24 +01:00
|
|
|
{
|
2017-02-21 13:46:59 +01:00
|
|
|
return *unmanaged_singleton<Hw::Memory_region_array>(
|
|
|
|
Hw::Memory_region(stack_area_virtual_base(), stack_area_virtual_size()));
|
2016-11-07 18:00:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addr_t Platform::core_phys_addr(addr_t virt)
|
|
|
|
{
|
|
|
|
addr_t ret = 0;
|
2017-02-21 13:46:59 +01:00
|
|
|
_boot_info().elf_mappings.for_each([&] (Hw::Mapping const & m)
|
2016-11-07 18:00:24 +01:00
|
|
|
{
|
|
|
|
if (virt >= m.virt() && virt < (m.virt() + m.size()))
|
|
|
|
ret = (virt - m.virt()) + m.phys();
|
|
|
|
});
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-23 02:30:24 +01:00
|
|
|
Platform::Platform()
|
|
|
|
:
|
2014-04-28 21:31:57 +02:00
|
|
|
_io_mem_alloc(core_mem_alloc()),
|
2015-03-18 23:40:58 +01:00
|
|
|
_io_port_alloc(core_mem_alloc()),
|
2016-10-06 20:07:16 +02:00
|
|
|
_irq_alloc(core_mem_alloc())
|
2012-05-30 20:13:09 +02:00
|
|
|
{
|
2017-03-23 03:06:53 +01:00
|
|
|
struct Kernel_resource : Exception { };
|
|
|
|
|
2016-10-06 20:07:16 +02:00
|
|
|
_core_mem_alloc.virt_alloc()->add_range(VIRT_ADDR_SPACE_START,
|
|
|
|
VIRT_ADDR_SPACE_SIZE);
|
2017-02-21 13:46:59 +01:00
|
|
|
_core_virt_regions().for_each([this] (Hw::Memory_region const & r) {
|
2016-11-07 18:00:24 +01:00
|
|
|
_core_mem_alloc.virt_alloc()->remove_range(r.base, r.size); });
|
2017-02-21 13:46:59 +01:00
|
|
|
_boot_info().elf_mappings.for_each([this] (Hw::Mapping const & m) {
|
2016-11-07 18:00:24 +01:00
|
|
|
_core_mem_alloc.virt_alloc()->remove_range(m.virt(), m.size()); });
|
2017-02-21 13:46:59 +01:00
|
|
|
_boot_info().ram_regions.for_each([this] (Hw::Memory_region const & region) {
|
2016-10-06 20:07:16 +02:00
|
|
|
_core_mem_alloc.phys_alloc()->add_range(region.base, region.size); });
|
|
|
|
|
2015-03-18 23:40:58 +01:00
|
|
|
_init_io_port_alloc();
|
|
|
|
|
2015-04-03 17:22:16 +02:00
|
|
|
/* make all non-kernel interrupts available to the interrupt allocator */
|
|
|
|
for (unsigned i = 0; i < Kernel::Pic::NR_OF_IRQ; i++) {
|
2017-03-23 03:06:53 +01:00
|
|
|
bool kernel_resource = false;
|
|
|
|
Kernel::cpu_pool()->for_each_cpu([&] (Kernel::Cpu const &cpu) {
|
|
|
|
if (i == cpu.timer_interrupt_id()) {
|
|
|
|
kernel_resource = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (i == Pic::IPI) {
|
|
|
|
kernel_resource = true;
|
|
|
|
}
|
|
|
|
if (kernel_resource) {
|
2015-04-03 17:22:16 +02:00
|
|
|
continue;
|
2017-03-23 03:06:53 +01:00
|
|
|
}
|
2014-04-04 17:36:05 +02:00
|
|
|
_irq_alloc.add_range(i, 1);
|
2015-04-03 17:22:16 +02:00
|
|
|
}
|
2013-04-08 19:05:44 +02:00
|
|
|
|
2015-04-28 14:56:00 +02:00
|
|
|
_init_io_mem_alloc();
|
2017-08-17 16:20:56 +02:00
|
|
|
_init_rom_modules();
|
2015-07-02 16:25:51 +02:00
|
|
|
_init_additional();
|
|
|
|
|
2012-05-30 20:13:09 +02:00
|
|
|
/* print ressource summary */
|
2016-11-02 10:39:13 +01:00
|
|
|
log(":virt_alloc: ", *_core_mem_alloc.virt_alloc());
|
|
|
|
log(":phys_alloc: ", *_core_mem_alloc.phys_alloc());
|
|
|
|
log(":io_mem_alloc: ", _io_mem_alloc);
|
|
|
|
log(":io_port_alloc: ", _io_port_alloc);
|
|
|
|
log(":irq_alloc: ", _irq_alloc);
|
2016-11-02 13:29:50 +01:00
|
|
|
log(":rom_fs: ", _rom_fs);
|
2012-05-30 20:13:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-28 21:31:57 +02:00
|
|
|
/****************************************
|
|
|
|
** Support for core memory management **
|
|
|
|
****************************************/
|
|
|
|
|
2014-07-08 15:46:53 +02:00
|
|
|
bool Genode::map_local(addr_t from_phys, addr_t to_virt, size_t num_pages,
|
|
|
|
Page_flags flags)
|
2014-04-28 21:31:57 +02:00
|
|
|
{
|
2015-04-28 14:07:51 +02:00
|
|
|
Platform_pd * pd = Kernel::core_pd()->platform_pd();
|
|
|
|
return pd->insert_translation(to_virt, from_phys,
|
|
|
|
num_pages * get_page_size(), flags);
|
2014-04-28 21:31:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Genode::unmap_local(addr_t virt_addr, size_t num_pages)
|
|
|
|
{
|
2015-04-28 14:07:51 +02:00
|
|
|
Platform_pd * pd = Kernel::core_pd()->platform_pd();
|
|
|
|
pd->flush(virt_addr, num_pages * get_page_size());
|
|
|
|
return true;
|
2014-04-28 21:31:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-17 14:16:59 +02:00
|
|
|
bool Mapped_mem_allocator::_map_local(addr_t virt_addr, addr_t phys_addr,
|
|
|
|
unsigned size) {
|
2015-06-16 10:59:26 +02:00
|
|
|
return ::map_local(phys_addr, virt_addr, size / get_page_size()); }
|
2014-04-28 21:31:57 +02:00
|
|
|
|
|
|
|
|
2016-07-15 11:05:09 +02:00
|
|
|
bool Mapped_mem_allocator::_unmap_local(addr_t virt_addr, addr_t phys_addr,
|
|
|
|
unsigned size) {
|
2015-06-16 10:59:26 +02:00
|
|
|
return ::unmap_local(virt_addr, size / get_page_size()); }
|