genode/repos/base-sel4/src/core/include/untyped_memory.h

123 lines
3.3 KiB
C++

/*
* \brief Utilities for dealing with untyped memory
* \author Norman Feske
* \date 2015-05-06
*/
/*
* Copyright (C) 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.
*/
#ifndef _CORE__INCLUDE__UNTYPED_MEMORY_H_
#define _CORE__INCLUDE__UNTYPED_MEMORY_H_
/* Genode includes */
#include <base/allocator.h>
/* core includes */
#include <util.h>
#include <cap_sel_alloc.h>
/* seL4 includes */
#include <sel4/sel4.h>
namespace Genode { struct Untyped_memory; }
struct Genode::Untyped_memory
{
class Phys_alloc_failed : Exception { };
static inline addr_t alloc_pages(Range_allocator &phys_alloc, size_t num_pages)
{
void *out_ptr = nullptr;
Range_allocator::Alloc_return alloc_ret =
phys_alloc.alloc_aligned(num_pages*get_page_size(), &out_ptr,
get_page_size_log2());
if (alloc_ret.is_error()) {
PERR("%s: allocation of untyped memory failed", __FUNCTION__);
throw Phys_alloc_failed();
}
return (addr_t)out_ptr;
}
static inline addr_t alloc_page(Range_allocator &phys_alloc)
{
return alloc_pages(phys_alloc, 1);
}
/**
* Local utility solely used by 'untyped_sel' and 'frame_sel'
*/
static inline Cap_sel _core_local_sel(Core_cspace::Top_cnode_idx top_idx,
addr_t phys_addr)
{
unsigned const upper_bits = top_idx << Core_cspace::NUM_PHYS_SEL_LOG2;
unsigned const lower_bits = phys_addr >> get_page_size_log2();
return Cap_sel(upper_bits | lower_bits);
}
/**
* Return core-local selector for untyped page at given physical address
*/
static inline Cap_sel untyped_sel(addr_t phys_addr)
{
return _core_local_sel(Core_cspace::TOP_CNODE_UNTYPED_IDX, phys_addr);
}
/**
* Return core-local selector for 4K page frame at given physical address
*/
static inline Cap_sel frame_sel(addr_t phys_addr)
{
return _core_local_sel(Core_cspace::TOP_CNODE_PHYS_IDX, phys_addr);
}
/**
* Create page frames from untyped memory
*/
static inline void convert_to_page_frames(addr_t phys_addr,
size_t num_pages)
{
for (size_t i = 0; i < num_pages; i++, phys_addr += get_page_size()) {
seL4_Untyped const service = untyped_sel(phys_addr).value();
int const type = seL4_IA32_4K;
int const size_bits = 0;
seL4_CNode const root = Core_cspace::TOP_CNODE_SEL;
int const node_index = Core_cspace::TOP_CNODE_PHYS_IDX;
int const node_depth = Core_cspace::NUM_TOP_SEL_LOG2;
int const node_offset = phys_addr >> get_page_size_log2();
int const num_objects = 1;
int const ret = seL4_Untyped_Retype(service,
type,
size_bits,
root,
node_index,
node_depth,
node_offset,
num_objects);
if (ret != 0) {
PERR("%s: seL4_Untyped_RetypeAtOffset (IA32_4K) returned %d",
__FUNCTION__, ret);
return;
}
}
}
};
#endif /* _CORE__INCLUDE__UNTYPED_MEMORY_H_ */