/*
* \brief Linux region-map test
* \author Christian Helmuth
* \date 2013-09-06
*/
/*
* Copyright (C) 2006-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include
#include
#include
#include
#include
#include
using namespace Genode;
static void blob() __attribute__((used));
static void blob()
{
asm volatile (
".balign 4096, -1\n"
"blob_beg:\n"
".space 16*4096, -2\n"
"blob_end:\n"
".global blob_beg\n"
".global blob_end\n"
: : : );
}
extern unsigned long blob_beg;
extern unsigned long blob_end;
struct Main
{
Heap heap;
Main(Env &env);
};
Main::Main(Env &env) : heap(env.ram(), env.rm())
{
/* activate for early printf in Rm_session_mmap::attach() etc. */
if (0) Thread::trace("FOO");
/* induce initial heap expansion to remove RM noise */
if (1) {
heap.try_alloc(0x100000).with_result(
[&] (void *ptr) { heap.free(ptr, 0); },
[&] (Allocator::Alloc_error) { });
}
addr_t beg((addr_t)&blob_beg);
addr_t end(align_addr((addr_t)&blob_end, 12));
size_t size(end - beg);
log("blob region region ", Hex_range(beg, size), " size=", size);
/* RAM dataspace attachment overlapping binary */
log("before RAM dataspace attach");
env.rm().attach(env.ram().alloc(size), {
.size = { }, .offset = { },
.use_at = true, .at = beg,
.executable = { }, .writeable = true
}).with_result(
[&] (Region_map::Range) {
error("after RAM dataspace attach -- ERROR");
env.parent().exit(-1); },
[&] (Region_map::Attach_error e) {
if (e == Region_map::Attach_error::REGION_CONFLICT)
log("OK caught Region_conflict exception"); }
);
/* empty managed dataspace overlapping binary */
{
Rm_connection rm_connection(env);
Region_map_client rm(rm_connection.create(size));
log("before sub-RM dataspace attach");
env.rm().attach(rm.dataspace(), {
.size = { }, .offset = { },
.use_at = true, .at = beg,
.executable = { }, .writeable = true
}).with_result(
[&] (Region_map::Range) {
error("after sub-RM dataspace attach -- ERROR");
env.parent().exit(-1); },
[&] (Region_map::Attach_error e) {
if (e == Region_map::Attach_error::REGION_CONFLICT)
log("OK caught Region_conflict exception"); }
);
}
/* sparsely populated managed dataspace in free VM area */
{
Rm_connection rm_connection(env);
Region_map_client rm(rm_connection.create(0x100000));
rm.attach(env.ram().alloc(0x1000), {
.size = { }, .offset = { },
.use_at = true, .at = 0x1000,
.executable = { }, .writeable = true
});
log("before populated sub-RM dataspace attach");
char * const addr = env.rm().attach(rm.dataspace(), {
.size = { }, .offset = { },
.use_at = { }, .at = { },
.executable = { }, .writeable = true
}).convert(
[&] (Region_map::Range r) { return (char *)r.start + 0x1000; },
[&] (Region_map::Attach_error) { return nullptr; }
);
log("after populated sub-RM dataspace attach / before touch");
char const val = *addr;
*addr = 0x55;
log("after touch (", val, "/", *addr, ")");
}
env.parent().exit(0);
}
void Component::construct(Env &env) { static Main main(env); }