genode/repos/ports-foc/src/lib/l4lx/l4x_pagefault.cc

123 lines
2.6 KiB
C++

#include <env.h>
#include <rm.h>
#include <vcpu.h>
#include <linux.h>
namespace Fiasco {
#include <genode/net.h>
#include <l4/sys/irq.h>
#include <l4/util/util.h>
#include <l4/sys/linkage.h>
}
static bool ballooning = false;
static Genode::Lock balloon_lock;
namespace {
class Signal_thread : public Genode::Thread<8192>
{
private:
Fiasco::l4_cap_idx_t _cap;
Genode::Lock *_sync;
protected:
void entry()
{
using namespace Fiasco;
using namespace Genode;
Signal_receiver receiver;
Signal_context rx;
Signal_context_capability cap(receiver.manage(&rx));
Genode::env()->parent()->yield_sigh(cap);
_sync->unlock();
while (true) {
receiver.wait_for_signal();
Genode::env()->parent()->yield_request();
{
Genode::Lock::Guard guard(balloon_lock);
ballooning = true;
if (l4_error(l4_irq_trigger(_cap)) != -1)
PWRN("IRQ net trigger failed\n");
}
}
}
public:
Signal_thread(Fiasco::l4_cap_idx_t cap, Genode::Lock *sync)
: Genode::Thread<8192>("net-signal-thread"), _cap(cap), _sync(sync) {
start(); }
};
}
extern "C" {
L4_CV int l4x_forward_pf(Fiasco::l4_umword_t addr,
Fiasco::l4_umword_t pc, int extra_write)
{
using namespace Fiasco;
Genode::size_t size = L4_PAGESIZE;
Genode::addr_t ds_start_addr = addr;
L4lx::Region *r = L4lx::Env::env()->rm()->find_region(&ds_start_addr, &size);
L4lx::Dataspace *ds = r ? r->ds() : 0;
while (ds) {
try {
ds->map(addr - r->addr(), !ballooning);
break;
} catch(Genode::Rm_session::Attach_failed) {
PWRN("Attach of chunk dataspace of failed");
return 0;
}
}
if (!extra_write)
l4_touch_ro((void*)l4_trunc_page(addr), L4_LOG2_PAGESIZE);
else
l4_touch_rw((void*)l4_trunc_page(addr), L4_LOG2_PAGESIZE);
return 1;
}
Fiasco::l4_cap_idx_t genode_balloon_irq_cap()
{
Linux::Irq_guard guard;
static Genode::Native_capability cap = L4lx::vcpu_connection()->alloc_irq();
static Genode::Lock lock(Genode::Lock::LOCKED);
static Signal_thread th(cap.dst(), &lock);
lock.lock();
return cap.dst();
}
bool genode_balloon_free_chunk(unsigned long addr)
{
Linux::Irq_guard guard;
Genode::addr_t ds_start_addr = addr;
Genode::size_t size = L4_PAGESIZE;
L4lx::Region *r = L4lx::Env::env()->rm()->find_region(&ds_start_addr, &size);
L4lx::Dataspace *ds = r ? r->ds() : 0;
return ds ? ds->free(addr - r->addr()) : false;
}
void genode_balloon_free_done()
{
Linux::Irq_guard ig;
Genode::Lock::Guard guard(balloon_lock);
ballooning = false;
Genode::env()->parent()->yield_response();
}
}