nova: platform test to stress SMP revoke/delegate

Issue #2100
This commit is contained in:
Alexander Boettcher 2016-09-02 10:40:08 +02:00 committed by Christian Helmuth
parent 4be8c2daa4
commit 66e9ca12b5
2 changed files with 154 additions and 2 deletions

View File

@ -35,7 +35,7 @@ install_config $config
build_boot_image "core init test-platform"
append qemu_args "-nographic -m 128"
append qemu_args "-nographic -m 128 -smp 2"
run_genode_until {Test finished} 150

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
* Copyright (C) 2015-2016 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.
@ -25,7 +25,9 @@
#include <os/config.h>
#include <trace/timestamp.h>
#include <nova/native_thread.h>
#include <nova_native_pd/client.h>
#include "server.h"
@ -412,6 +414,154 @@ void test_server_oom(Genode::Env &env)
ep.dissolve(&component);
}
class Pager : private Genode::Thread {
private:
Native_capability _call_to_map;
Ram_dataspace_capability _ds;
static addr_t _ds_mem;
void entry() { }
static void page_fault()
{
Thread * myself = Thread::myself();
Nova::Utcb * utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
if (utcb->msg_words() != 1) {
Genode::error("unexpected");
while (1) { }
}
Genode::addr_t map_from = utcb->msg[0];
// Genode::error("pager: got map request ", Genode::Hex(map_from));
utcb->set_msg_word(0);
utcb->mtd = 0;
Nova::Mem_crd crd_map(map_from >> 12, 0, Nova::Rights(true, true, true));
bool res = utcb->append_item(crd_map, 0);
(void)res;
Nova::reply(myself->stack_top());
}
public:
Pager(Genode::Env &env, Location location)
:
Thread(env, "pager", 0x1000, location, Weight(), env.cpu()),
_ds(env.ram().alloc (4096))
{
_ds_mem = env.rm().attach(_ds);
touch_read(reinterpret_cast<unsigned char *>(_ds_mem));
/* request creation of a 'local' EC */
Thread::native_thread().ec_sel = Native_thread::INVALID_INDEX - 1;
Thread::start();
Genode::warning("pager: created");
Native_capability thread_cap =
Capability_space::import(Thread::native_thread().ec_sel);
Genode::Nova_native_pd_client native_pd(env.pd().native_pd());
Nova::Mtd mtd (Nova::Mtd::QUAL | Nova::Mtd::EIP | Nova::Mtd::ESP);
Genode::addr_t entry = reinterpret_cast<Genode::addr_t>(page_fault);
_call_to_map = native_pd.alloc_rpc_cap(thread_cap, entry,
mtd.value());
}
Native_capability call_to_map() { return _call_to_map; }
addr_t mem_st() { return _ds_mem; }
};
addr_t Pager::_ds_mem;
class Cause_mapping : public Genode::Thread {
private:
Native_capability _call_to_map;
Rm_connection _rm;
Region_map_client _sub_rm;
addr_t _mem_nd;
addr_t _mem_st;
Nova::Rights const _mapping_rwx = {true, true, true};
public:
unsigned volatile called = 0;
Cause_mapping(Genode::Env &env, Native_capability call_to_map,
Genode::addr_t mem_st, Location location)
:
Thread(env, "mapper", 0x1000, location, Weight(), env.cpu()),
_call_to_map(call_to_map),
_rm(env),
_sub_rm(_rm.create(0x2000)),
_mem_nd(env.rm().attach(_sub_rm.dataspace())),
_mem_st(mem_st)
{ }
void entry() {
log("mapper: hello");
Nova::Utcb * nova_utcb = reinterpret_cast<Nova::Utcb *>(utcb());
while (true) {
called ++;
// log("mapper: request mapping ", Hex(_mem_nd), " ", called);
Nova::Crd old = nova_utcb->crd_rcv;
// touch_read((unsigned char *)_mem_st);
nova_utcb->msg[0] = _mem_st;
nova_utcb->set_msg_word(1);
nova_utcb->crd_rcv = Nova::Mem_crd(_mem_nd >> 12, 0,
_mapping_rwx);
Nova::call(_call_to_map.local_name());
//touch_read((unsigned char *)_mem_nd);
nova_utcb->msg[0] = _mem_nd;
nova_utcb->set_msg_word(1);
nova_utcb->crd_rcv = Nova::Mem_crd((_mem_nd + 0x1000) >> 12, 0,
_mapping_rwx);
Nova::call(_call_to_map.local_name());
// touch_read((unsigned char *)_mem_nd + 0x1000);
nova_utcb->crd_rcv = old;
}
}
void revoke_remote()
{
Nova::revoke(Nova::Mem_crd(_mem_nd >> 12, 0, _mapping_rwx), true);
}
};
void test_delegate_revoke_smp(Genode::Env &env)
{
Affinity::Space cpus = env.cpu().affinity_space();
Genode::log("detected ", cpus.width(), "x", cpus.height(), " "
"CPU", cpus.total() > 1 ? "s." : ".");
Pager pager(env, cpus.location_of_index(1));
Cause_mapping mapper(env, pager.call_to_map(), pager.mem_st(),
cpus.location_of_index(1));
mapper.start();
for (unsigned i = 0; i < 2000; i++) {
mapper.revoke_remote();
if (i % 1000 == 0)
Genode::log("main ", i, " ", mapper.called);
}
}
class Greedy : public Genode::Thread {
private:
@ -557,6 +707,8 @@ Main::Main(Env &env) : env(env)
check(res, "pt_ctrl %2u", i);
}
test_delegate_revoke_smp(env);
/* test PAT kernel feature */
test_pat(env);