diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h index 2fcb3d701..07725bf4b 100644 --- a/base-hw/include/base/native_types.h +++ b/base-hw/include/base/native_types.h @@ -18,6 +18,10 @@ #include #include #include +#include + +/* base-hw includes */ +#include namespace Genode { @@ -49,12 +53,11 @@ namespace Genode /** * Message that is communicated between user threads + * + * \param MAX_SIZE maximum size the object is allowed to take */ - struct Ipc_msg - { - size_t size; - uint8_t data[]; - }; + template + struct Ipc_msg; /** * Message that is communicated from a thread creator to the new thread @@ -115,6 +118,115 @@ namespace Genode struct Native_pd_args { }; } +template +class Genode::Ipc_msg +{ + private: + + size_t _data_size; + uint8_t _data[]; + + /** + * Return size of payload-preceding meta data + */ + size_t _header_size() const { return (addr_t)_data - (addr_t)this; } + + /** + * Return maximum payload size + */ + size_t _max_data_size() const { return MAX_SIZE - _header_size(); } + + /** + * Return size of header and current payload + */ + size_t _size() const { return _header_size() + _data_size; } + + public: + + /** + * Get information about current await-request operation + * + * \return buf_base base of receive buffer + * \return buf_size size of receive buffer + */ + void info_about_await_request(void * & buf_base, size_t & buf_size) + { + buf_base = this; + buf_size = MAX_SIZE; + } + + /** + * Get information about current send-request operation + * + * \return msg_base base of complete send-message data + * \return msg_size size of complete send-message data + * \return buf_base base of receive buffer + * \return buf_size size of receive buffer + */ + void info_about_send_request(void * & msg_base, size_t & msg_size, + void * & buf_base, size_t & buf_size) + { + msg_base = this; + msg_size = _size(); + buf_base = this; + buf_size = MAX_SIZE; + } + + /** + * Get information about current send-reply operation + * + * \return msg_base base of complete send-message data + * \return msg_size size of complete send-message data + */ + void info_about_send_reply(void * & msg_base, size_t & msg_size) + { + msg_base = this; + msg_size = _size(); + } + + /** + * Install message that shall be send + * + * \param data base of payload + * \param raw_data_size size of payload without preceding name + * \param name local name that shall precede raw payload + */ + void prepare_send(void * const data, size_t raw_data_size, + unsigned const name) + { + /* limit data size */ + enum { NAME_SIZE = sizeof(name) }; + size_t const data_size = raw_data_size + NAME_SIZE; + if (data_size > _max_data_size()) { + kernel_log() << __func__ << ": oversized message outgoing\n"; + raw_data_size = _max_data_size() - NAME_SIZE; + } + /* copy data */ + *(unsigned *)_data = name; + void * const raw_data_dst = (void *)((addr_t)_data + NAME_SIZE); + void * const raw_data_src = (void *)((addr_t)data + NAME_SIZE); + memcpy(raw_data_dst, raw_data_src, raw_data_size); + _data_size = data_size; + } + + /** + * Read out message that was received + * + * \param buf_base base of read buffer + * \param buf_size size of read buffer + */ + void finish_receive(void * const buf_base, size_t const buf_size) + { + /* limit data size */ + if (_data_size > buf_size) { + kernel_log() << __func__ << ": oversized message incoming\n"; + _data_size = buf_size; + } + /* copy data */ + memcpy(buf_base, _data, _data_size); + } +}; + class Genode::Startup_msg { private: @@ -140,40 +252,17 @@ class Genode::Startup_msg struct Genode::Native_utcb { + enum { SIZE = 1 << MIN_MAPPING_SIZE_LOG2 }; + union { - uint8_t data[1 << MIN_MAPPING_SIZE_LOG2]; - Ipc_msg ipc_msg; - Startup_msg startup_msg; + uint8_t data[SIZE]; + Ipc_msg ipc_msg; + Startup_msg startup_msg; }; - void call_await_request_msg(void * & buf_base, size_t & buf_size) - { - buf_base = base(); - buf_size = size(); - } + size_t size() const { return SIZE; } - void call_send_request_msg(void * & msg_base, size_t & msg_size, - void * & buf_base, size_t & buf_size) - { - msg_base = ipc_msg_base(); - msg_size = ipc_msg_size(); - buf_base = base(); - buf_size = size(); - } - - void call_send_reply_msg(void * & msg_base, size_t & msg_size) - { - msg_base = ipc_msg_base(); - msg_size = ipc_msg_size(); - } - - size_t size() { return sizeof(data) / sizeof(data[0]); } - void * base() { return &data; } - addr_t top() { return (addr_t)base() + size(); } - void * ipc_msg_base() { return &ipc_msg; } - size_t ipc_msg_size() { return ipc_msg_header_size() + ipc_msg.size; } - size_t ipc_msg_max_size() { return top() - (addr_t)&ipc_msg; } - size_t ipc_msg_header_size() { return (addr_t)ipc_msg.data - (addr_t)&ipc_msg; } + void * base() const { return (void *)data; } }; #endif /* _BASE__NATIVE_TYPES_H_ */ diff --git a/base-hw/src/base/ipc.cc b/base-hw/src/base/ipc.cc index fbf9a7785..985a2dbe9 100644 --- a/base-hw/src/base/ipc.cc +++ b/base-hw/src/base/ipc.cc @@ -35,46 +35,6 @@ enum }; -/*************** - ** Utilities ** - ***************/ - -/** - * Copy message from the callers UTCB to message buffer - */ -static void utcb_to_msgbuf(Msgbuf_base * const msgbuf) -{ - Native_utcb * const utcb = Thread_base::myself()->utcb(); - size_t msg_size = utcb->ipc_msg.size; - if (msg_size > msgbuf->size()) { - kernel_log() << "oversized IPC message\n"; - msg_size = msgbuf->size(); - } - memcpy(msgbuf->buf, utcb->ipc_msg.data, msg_size); -} - - -/** - * Copy message from message buffer to the callers UTCB - */ -static void msgbuf_to_utcb(Msgbuf_base * const msg_buf, size_t msg_size, - unsigned const local_name) -{ - Native_utcb * const utcb = Thread_base::myself()->utcb(); - enum { NAME_SIZE = sizeof(local_name) }; - size_t const ipc_msg_size = msg_size + NAME_SIZE; - if (ipc_msg_size > utcb->ipc_msg_max_size()) { - kernel_log() << "oversized IPC message\n"; - msg_size = utcb->ipc_msg_max_size() - NAME_SIZE; - } - *(unsigned *)utcb->ipc_msg.data = local_name; - 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); - memcpy(utcb_msg, buf_msg, msg_size); - utcb->ipc_msg.size = ipc_msg_size; -} - - /***************** ** Ipc_ostream ** *****************/ @@ -118,12 +78,13 @@ void Ipc_client::_call() { /* send request and receive corresponding reply */ unsigned const local_name = Ipc_ostream::_dst.local_name(); - msgbuf_to_utcb(_snd_msg, _write_offset, local_name); + Native_utcb * const utcb = Thread_base::myself()->utcb(); + utcb->ipc_msg.prepare_send(_snd_msg->buf, _write_offset, local_name); if (Kernel::send_request_msg(Ipc_ostream::_dst.dst())) { PERR("failed to receive reply"); throw Blocking_canceled(); } - utcb_to_msgbuf(_rcv_msg); + utcb->ipc_msg.finish_receive(_rcv_msg->buf, _rcv_msg->size()); /* reset unmarshaller */ _write_offset = _read_offset = RPC_OBJECT_ID_SIZE; @@ -167,7 +128,8 @@ void Ipc_server::_wait() PERR("failed to receive request"); throw Blocking_canceled(); } - utcb_to_msgbuf(_rcv_msg); + Native_utcb * const utcb = Thread_base::myself()->utcb(); + utcb->ipc_msg.finish_receive(_rcv_msg->buf, _rcv_msg->size()); /* update server state */ _prepare_next_reply_wait(); @@ -176,8 +138,9 @@ void Ipc_server::_wait() void Ipc_server::_reply() { + unsigned const local_name = Ipc_ostream::_dst.local_name(); Native_utcb * const utcb = Thread_base::myself()->utcb(); - utcb->ipc_msg.size = _write_offset; + utcb->ipc_msg.prepare_send(_snd_msg->buf, _write_offset, local_name); Kernel::send_reply_msg(0); } @@ -191,12 +154,13 @@ void Ipc_server::_reply_wait() } /* send reply and receive next request */ unsigned const local_name = Ipc_ostream::_dst.local_name(); - msgbuf_to_utcb(_snd_msg, _write_offset, local_name); + Native_utcb * const utcb = Thread_base::myself()->utcb(); + utcb->ipc_msg.prepare_send(_snd_msg->buf, _write_offset, local_name); if (Kernel::send_reply_msg(1)) { PERR("failed to receive request"); throw Blocking_canceled(); } - utcb_to_msgbuf(_rcv_msg); + utcb->ipc_msg.finish_receive(_rcv_msg->buf, _rcv_msg->size()); /* update server state */ _prepare_next_reply_wait(); diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc index 7849a9428..c601ef702 100644 --- a/base-hw/src/core/kernel/thread.cc +++ b/base-hw/src/core/kernel/thread.cc @@ -456,7 +456,7 @@ void Thread::_call_await_request_msg() { void * buf_base; size_t buf_size; - _utcb_phys->call_await_request_msg(buf_base, buf_size); + _utcb_phys->ipc_msg.info_about_await_request(buf_base, buf_size); Ipc_node::await_request(buf_base, buf_size); } @@ -473,8 +473,8 @@ void Thread::_call_send_request_msg() size_t msg_size; void * buf_base; size_t buf_size; - _utcb_phys->call_send_request_msg(msg_base, msg_size, - buf_base, buf_size); + _utcb_phys->ipc_msg.info_about_send_request(msg_base, msg_size, + buf_base, buf_size); Ipc_node::send_request_await_reply(dst, msg_base, msg_size, buf_base, buf_size); } @@ -484,7 +484,7 @@ void Thread::_call_send_reply_msg() { void * msg_base; size_t msg_size; - _utcb_phys->call_send_reply_msg(msg_base, msg_size); + _utcb_phys->ipc_msg.info_about_send_reply(msg_base, msg_size); Ipc_node::send_reply(msg_base, msg_size); bool const await_request_msg = user_arg_1(); if (await_request_msg) { _call_await_request_msg(); }