hw: manage UTCB through use-case specific structs

ref #874
This commit is contained in:
Martin Stein 2013-10-17 16:57:41 +02:00 committed by Norman Feske
parent 96bbca6191
commit 1e7eb4512e
4 changed files with 42 additions and 46 deletions

View File

@ -90,43 +90,39 @@ namespace Genode
*/ */
struct Native_utcb struct Native_utcb
{ {
/* UTCB payload */ /**
char payload[1<<MIN_MAPPING_SIZE_LOG2]; * Structure of an IPC message held by the UTCB
*/
struct Ipc_msg
{
size_t size;
uint8_t data[];
};
union {
uint8_t data[1 << MIN_MAPPING_SIZE_LOG2];
Ipc_msg ipc_msg;
};
/** /**
* Get the base of the UTCB region * Get the base of the UTCB region
*/ */
void * base() { return payload; } void * base() { return data; }
/** /**
* Get the size of the UTCB region * Get the size of the UTCB region
*/ */
size_t size() { return sizeof(payload); } size_t size() { return sizeof(data) / sizeof(data[0]); }
/** /**
* Get the top of the UTCB region * Get the top of the UTCB region
*/ */
addr_t top() { return (addr_t)payload + size(); } addr_t top() { return (addr_t)data + size(); }
/**
* Get the base of an IPC message that is held by the UTCB
*/
void * ipc_msg_base() { return (void *)((addr_t)base() + sizeof(size_t)); }
/**
* Get the size of an IPC message that is held by the UTCB
*/
size_t ipc_msg_size() { return *(size_t *)base(); }
/**
* Set the size of the IPC message that is held by the UTCB
*/
void ipc_msg_size(size_t const s) { *(size_t *)base() = s; }
/** /**
* Maximum size of an IPC message that can be held by the UTCB * Maximum size of an IPC message that can be held by the UTCB
*/ */
size_t max_ipc_msg_size() { return top() - (addr_t)ipc_msg_base(); } size_t ipc_msg_max_size() { return top() - (addr_t)ipc_msg.data; }
}; };
struct Cap_dst_policy struct Cap_dst_policy

View File

@ -43,12 +43,12 @@ enum
static void utcb_to_msgbuf(Msgbuf_base * const msgbuf) static void utcb_to_msgbuf(Msgbuf_base * const msgbuf)
{ {
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
size_t msg_size = utcb->ipc_msg_size(); size_t msg_size = utcb->ipc_msg.size;
if (msg_size > msgbuf->size()) { if (msg_size > msgbuf->size()) {
kernel_log() << "oversized IPC message\n"; kernel_log() << "oversized IPC message\n";
msg_size = msgbuf->size(); msg_size = msgbuf->size();
} }
memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size); memcpy(msgbuf->buf, utcb->ipc_msg.data, msg_size);
} }
@ -61,15 +61,15 @@ static void msgbuf_to_utcb(Msgbuf_base * const msg_buf, size_t msg_size,
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
enum { NAME_SIZE = sizeof(local_name) }; enum { NAME_SIZE = sizeof(local_name) };
size_t const ipc_msg_size = msg_size + NAME_SIZE; size_t const ipc_msg_size = msg_size + NAME_SIZE;
if (ipc_msg_size > utcb->max_ipc_msg_size()) { if (ipc_msg_size > utcb->ipc_msg_max_size()) {
kernel_log() << "oversized IPC message\n"; kernel_log() << "oversized IPC message\n";
msg_size = utcb->max_ipc_msg_size() - NAME_SIZE; msg_size = utcb->ipc_msg_max_size() - NAME_SIZE;
} }
*(unsigned *)utcb->ipc_msg_base() = local_name; *(unsigned *)utcb->ipc_msg.data = local_name;
void * const utcb_msg = (void *)((addr_t)utcb->ipc_msg_base() + NAME_SIZE); void * const utcb_msg = (void *)((addr_t)utcb->ipc_msg.data + NAME_SIZE);
void * const buf_msg = (void *)((addr_t)msg_buf->buf + NAME_SIZE); void * const buf_msg = (void *)((addr_t)msg_buf->buf + NAME_SIZE);
memcpy(utcb_msg, buf_msg, msg_size); memcpy(utcb_msg, buf_msg, msg_size);
utcb->ipc_msg_size(ipc_msg_size); utcb->ipc_msg.size = ipc_msg_size;
} }
@ -175,7 +175,7 @@ void Ipc_server::_wait()
void Ipc_server::_reply() void Ipc_server::_reply()
{ {
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
utcb->ipc_msg_size(_write_offset); utcb->ipc_msg.size = _write_offset;
Kernel::reply(0); Kernel::reply(0);
} }

View File

@ -97,14 +97,14 @@ void Ipc_pager::wait_for_first_fault()
{ {
while (Kernel::wait_for_request()) { PERR("failed to receive fault"); } while (Kernel::wait_for_request()) { PERR("failed to receive fault"); }
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
_wait_for_fault(utcb->ipc_msg_size()); _wait_for_fault(utcb->ipc_msg.size);
} }
void Ipc_pager::wait_for_fault() void Ipc_pager::wait_for_fault()
{ {
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
utcb->ipc_msg_size(0); utcb->ipc_msg.size = 0;
int err = Kernel::reply(1); int err = Kernel::reply(1);
if (err) { if (err) {
PERR("failed to receive fault"); PERR("failed to receive fault");
@ -112,7 +112,7 @@ void Ipc_pager::wait_for_fault()
PERR("failed to receive fault"); PERR("failed to receive fault");
} }
} }
_wait_for_fault(utcb->ipc_msg_size()); _wait_for_fault(utcb->ipc_msg.size);
} }
@ -129,7 +129,7 @@ void Ipc_pager::_wait_for_fault(size_t s)
/* message is a pagefault */ /* message is a pagefault */
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
Pagefault * const pf = (Pagefault *)utcb->ipc_msg_base(); Pagefault * const pf = (Pagefault *)utcb->ipc_msg.data;
if (pf->valid()) if (pf->valid())
{ {
/* give our caller the chance to handle the fault */ /* give our caller the chance to handle the fault */
@ -147,19 +147,19 @@ void Ipc_pager::_wait_for_fault(size_t s)
/* message is a release request from a RM session */ /* message is a release request from a RM session */
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
void * const msg_base = utcb->ipc_msg_base(); void * const msg_base = utcb->ipc_msg.data;
Pagefault_resolved * const msg = (Pagefault_resolved *)msg_base; Pagefault_resolved * const msg = (Pagefault_resolved *)msg_base;
/* resume faulter, send ack to RM and get the next message */ /* resume faulter, send ack to RM and get the next message */
Kernel::resume_thread(msg->pager_object->badge()); Kernel::resume_thread(msg->pager_object->badge());
utcb->ipc_msg_size(0); utcb->ipc_msg.size = 0;
if (Kernel::reply(1)) { if (Kernel::reply(1)) {
PERR("failed to receive fault"); PERR("failed to receive fault");
while (Kernel::wait_for_request()) { while (Kernel::wait_for_request()) {
PERR("failed to receive fault"); PERR("failed to receive fault");
} }
} }
s = utcb->ipc_msg_size(); s = utcb->ipc_msg.size;
continue; } continue; }
default: { default: {

View File

@ -90,7 +90,7 @@ void Thread::_received_ipc_request(size_t const s)
{ {
switch (_state) { switch (_state) {
case SCHEDULED: case SCHEDULED:
_phys_utcb->ipc_msg_size(s); _phys_utcb->ipc_msg.size = s;
user_arg_0(0); user_arg_0(0);
return; return;
default: default:
@ -121,7 +121,7 @@ void Thread::_await_ipc_succeeded(size_t const s)
{ {
switch (_state) { switch (_state) {
case AWAITS_IPC: case AWAITS_IPC:
_phys_utcb->ipc_msg_size(s); _phys_utcb->ipc_msg.size = s;
user_arg_0(0); user_arg_0(0);
_schedule(); _schedule();
return; return;
@ -604,8 +604,8 @@ void Thread::_syscall_get_thread()
*/ */
void Thread::_syscall_wait_for_request() void Thread::_syscall_wait_for_request()
{ {
void * const buf_base = _phys_utcb->ipc_msg_base(); void * const buf_base = _phys_utcb->ipc_msg.data;
size_t const buf_size = _phys_utcb->max_ipc_msg_size(); size_t const buf_size = _phys_utcb->ipc_msg_max_size();
Ipc_node::await_request(buf_base, buf_size); Ipc_node::await_request(buf_base, buf_size);
} }
@ -622,8 +622,8 @@ void Thread::_syscall_request_and_wait()
return; return;
} }
Ipc_node::send_request_await_reply( Ipc_node::send_request_await_reply(
dst, _phys_utcb->ipc_msg_base(), _phys_utcb->ipc_msg_size(), dst, _phys_utcb->ipc_msg.data, _phys_utcb->ipc_msg.size,
_phys_utcb->ipc_msg_base(), _phys_utcb->max_ipc_msg_size()); _phys_utcb->ipc_msg.data, _phys_utcb->ipc_msg_max_size());
} }
@ -633,13 +633,13 @@ void Thread::_syscall_request_and_wait()
void Thread::_syscall_reply() void Thread::_syscall_reply()
{ {
bool const await_request = user_arg_1(); bool const await_request = user_arg_1();
void * const msg_base = _phys_utcb->ipc_msg_base(); void * const msg_base = _phys_utcb->ipc_msg.data;
size_t const msg_size = _phys_utcb->ipc_msg_size(); size_t const msg_size = _phys_utcb->ipc_msg.size;
Ipc_node::send_reply(msg_base, msg_size); Ipc_node::send_reply(msg_base, msg_size);
if (await_request) { if (await_request) {
void * const buf_base = _phys_utcb->ipc_msg_base(); void * const buf_base = _phys_utcb->ipc_msg.data;
size_t const buf_size = _phys_utcb->max_ipc_msg_size(); size_t const buf_size = _phys_utcb->ipc_msg_max_size();
Ipc_node::await_request(buf_base, buf_size); Ipc_node::await_request(buf_base, buf_size);
} else { user_arg_0(0); } } else { user_arg_0(0); }
} }