123 lines
3.3 KiB
C++
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_ */
|