mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-16 06:08:16 +00:00
Imported Genode release 11.11
This commit is contained in:
committed by
Christian Helmuth
parent
6bcc9aef0e
commit
da4e1feaa5
175
base-codezero/src/base/ipc/ipc.cc
Normal file
175
base-codezero/src/base/ipc/ipc.cc
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* \brief Codezero implementation of the IPC API
|
||||
* \author Norman Feske
|
||||
* \date 2009-10-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2011 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.
|
||||
*/
|
||||
|
||||
/* Codezero includes */
|
||||
#include <codezero/syscalls.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/ipc.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/blocking.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Codezero;
|
||||
|
||||
enum { verbose_ipc = false };
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
void Ipc_ostream::_send()
|
||||
{
|
||||
if (verbose_ipc)
|
||||
PDBG("thread %d sends IPC to %d, write_offset=%d",
|
||||
thread_myself(), _dst.tid().tid, _write_offset);
|
||||
|
||||
umword_t snd_size = min(_write_offset, (unsigned)L4_IPC_EXTENDED_MAX_SIZE);
|
||||
|
||||
*(umword_t *)_snd_msg->addr() = _dst.local_name();
|
||||
|
||||
int ret = l4_send_extended(_dst.tid().tid, L4_IPC_TAG_SYNC_EXTENDED,
|
||||
snd_size, _snd_msg->addr());
|
||||
if (ret < 0)
|
||||
PERR("l4_send_extended (to thread %d) returned ret=%d",
|
||||
_dst.tid().tid, ret);
|
||||
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller((char *)snd_msg->addr(), snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
void Ipc_istream::_wait()
|
||||
{
|
||||
umword_t *rcv_buf = (umword_t *)_rcv_msg->addr();
|
||||
umword_t rcv_size = min(_rcv_msg->size(), (unsigned)L4_IPC_EXTENDED_MAX_SIZE);
|
||||
|
||||
if (verbose_ipc)
|
||||
PDBG("thread %d waits for IPC from %d, rcv_buf at %p, rcv_size=%d",
|
||||
tid().tid, _rcv_cs, rcv_buf, (int)rcv_size);
|
||||
|
||||
int ret = l4_receive_extended(_rcv_cs, rcv_size, rcv_buf);
|
||||
if (ret < 0)
|
||||
PERR("l4_receive_extended (from any) returned ret=%d", ret);
|
||||
|
||||
if (verbose_ipc)
|
||||
PDBG("thread %d received IPC from %d",
|
||||
tid().tid, l4_get_sender());
|
||||
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller((char *)rcv_msg->addr(), rcv_msg->size()),
|
||||
Native_capability(thread_myself(), 0),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_rcv_cs = L4_ANYTHREAD;
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
#warning l4_sendrecv_extended is not yet implemented in l4lib/arch/syslib.h
|
||||
_send();
|
||||
_rcv_cs = _dst.tid().tid;
|
||||
_wait();
|
||||
_rcv_cs = L4_ANYTHREAD;
|
||||
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
{ }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_server **
|
||||
****************/
|
||||
|
||||
void Ipc_server::_prepare_next_reply_wait()
|
||||
{
|
||||
/* now we have a request to reply */
|
||||
_reply_needed = true;
|
||||
|
||||
/* leave space for return value at the beginning of the msgbuf */
|
||||
_write_offset = 2*sizeof(umword_t);
|
||||
|
||||
/* receive buffer offset */
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try { Ipc_istream::_wait(); } catch (Blocking_canceled) { }
|
||||
|
||||
/* define destination of next reply */
|
||||
_dst = Native_capability(l4_get_sender(), badge());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
{
|
||||
try { _send(); } catch (Ipc_error) { }
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
{
|
||||
if (_reply_needed)
|
||||
_reply();
|
||||
|
||||
_wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg),
|
||||
_reply_needed(false)
|
||||
{ }
|
175
base-codezero/src/base/ipc/pager.cc
Normal file
175
base-codezero/src/base/ipc/pager.cc
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* \brief Pager support for Codezero
|
||||
* \author Norman Feske
|
||||
* \date 2010-02-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2011 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/ipc_pager.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* Codezero includes */
|
||||
#include <codezero/syscalls.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Codezero;
|
||||
|
||||
enum { verbose_page_faults = false };
|
||||
|
||||
|
||||
/************************
|
||||
** Page-fault utility **
|
||||
************************/
|
||||
|
||||
class Fault
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type { READ, WRITE, EXEC, UNKNOWN };
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Translate Codezero page-fault information to generic fault type
|
||||
*
|
||||
* \param sr status
|
||||
* \param pte page-table entry
|
||||
*/
|
||||
static Type _fault_type(umword_t sr, umword_t pte)
|
||||
{
|
||||
if (is_prefetch_abort(sr))
|
||||
return EXEC;
|
||||
|
||||
if ((pte & PTE_PROT_MASK) == (__MAP_USR_RO & PTE_PROT_MASK))
|
||||
return WRITE;
|
||||
|
||||
return READ;
|
||||
}
|
||||
|
||||
Type _type;
|
||||
umword_t _addr;
|
||||
umword_t _ip;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param kdata Codezero-specific page-fault information
|
||||
*/
|
||||
Fault(struct fault_kdata const &kdata)
|
||||
:
|
||||
_type(_fault_type(kdata.fsr, kdata.pte)),
|
||||
_addr(_type == EXEC ? kdata.faulty_pc : kdata.far),
|
||||
_ip(kdata.faulty_pc)
|
||||
{ }
|
||||
|
||||
Type type() const { return _type; }
|
||||
umword_t addr() const { return _addr; }
|
||||
umword_t ip() const { return _ip; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Print page-fault information in a human-readable form
|
||||
*/
|
||||
inline void print_page_fault(Fault &fault, int from)
|
||||
{
|
||||
printf("page (%s%s%s) fault from %d at pf_addr=%lx, pf_ip=%lx\n",
|
||||
fault.type() == Fault::READ ? "r" : "-",
|
||||
fault.type() == Fault::WRITE ? "w" : "-",
|
||||
fault.type() == Fault::EXEC ? "x" : "-",
|
||||
from, fault.addr(), fault.ip());
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** IPC pager **
|
||||
***************/
|
||||
|
||||
void Ipc_pager::wait_for_fault()
|
||||
{
|
||||
for (;;) {
|
||||
int ret = l4_receive(L4_ANYTHREAD);
|
||||
|
||||
if (ret < 0) {
|
||||
PERR("pager: l4_received returned ret=%d", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
umword_t tag = l4_get_tag();
|
||||
int faulter_tid = l4_get_sender();
|
||||
|
||||
if (tag != L4_IPC_TAG_PFAULT) {
|
||||
PWRN("got an unexpected IPC from %d", faulter_tid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy fault information from message registers */
|
||||
struct fault_kdata fault_kdata;
|
||||
for (unsigned i = 0; i < sizeof(fault_kdata_t)/sizeof(umword_t); i++)
|
||||
((umword_t *)&fault_kdata)[i] = read_mr(MR_UNUSED_START + i);
|
||||
|
||||
Fault fault(fault_kdata);
|
||||
|
||||
if (verbose_page_faults)
|
||||
print_page_fault(fault, faulter_tid);
|
||||
|
||||
/* determine corresponding page in our own address space */
|
||||
_pf_addr = fault.addr();
|
||||
_pf_write = fault.type() == Fault::WRITE;
|
||||
_pf_ip = fault.ip();
|
||||
_last = faulter_tid;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ipc_pager::reply_and_wait_for_fault()
|
||||
{
|
||||
/* install mapping */
|
||||
umword_t flags = _reply_mapping.writeable() ? MAP_USR_RW
|
||||
: MAP_USR_RO;
|
||||
|
||||
/*
|
||||
* XXX: remove heuristics for mapping device registers.
|
||||
*/
|
||||
if (_reply_mapping.from_phys() == 0x10120000 /* LCD */
|
||||
|| _reply_mapping.from_phys() == 0x10006000 /* keyboard */
|
||||
|| _reply_mapping.from_phys() == 0x10007000) /* mouse */
|
||||
flags = MAP_USR_IO;
|
||||
|
||||
int ret = l4_map((void *)_reply_mapping.from_phys(),
|
||||
(void *)_reply_mapping.to_virt(),
|
||||
_reply_mapping.num_pages(), flags, _last.tid);
|
||||
|
||||
/* wake up faulter if mapping succeeded */
|
||||
if (ret < 0)
|
||||
PERR("l4_map returned %d, putting thread %d to sleep", ret, _last.tid);
|
||||
else
|
||||
acknowledge_wakeup();
|
||||
|
||||
/* wait for next page fault */
|
||||
wait_for_fault();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_pager::acknowledge_wakeup()
|
||||
{
|
||||
enum { SUCCESS = 0 };
|
||||
l4_set_sender(_last.tid);
|
||||
l4_ipc_return(SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
Ipc_pager::Ipc_pager() : Native_capability(thread_myself(), 0) { }
|
||||
|
Reference in New Issue
Block a user