From 1e7eb4512eda563517854c2a182f29d6d2747b2c Mon Sep 17 00:00:00 2001
From: Martin Stein <martin.stein@genode-labs.com>
Date: Thu, 17 Oct 2013 16:57:41 +0200
Subject: [PATCH] hw: manage UTCB through use-case specific structs

ref #874
---
 base-hw/include/base/native_types.h | 38 +++++++++++++----------------
 base-hw/src/base/ipc.cc             | 16 ++++++------
 base-hw/src/base/pager.cc           | 14 +++++------
 base-hw/src/core/kernel/thread.cc   | 20 +++++++--------
 4 files changed, 42 insertions(+), 46 deletions(-)

diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h
index cbdf482eb0..5ec565502b 100644
--- a/base-hw/include/base/native_types.h
+++ b/base-hw/include/base/native_types.h
@@ -90,43 +90,39 @@ namespace Genode
 	 */
 	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
 		 */
-		void * base() { return payload; }
+		void * base() { return data; }
 
 		/**
 		 * 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
 		 */
-		addr_t top()  { return (addr_t)payload + 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; }
+		addr_t top()  { return (addr_t)data + size(); }
 
 		/**
 		 * 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
diff --git a/base-hw/src/base/ipc.cc b/base-hw/src/base/ipc.cc
index 06d66f7df6..46c56a6a6e 100644
--- a/base-hw/src/base/ipc.cc
+++ b/base-hw/src/base/ipc.cc
@@ -43,12 +43,12 @@ enum
 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();
+	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_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();
 	enum { NAME_SIZE = sizeof(local_name) };
 	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";
-		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;
-	void * const utcb_msg = (void *)((addr_t)utcb->ipc_msg_base() + 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);
+	utcb->ipc_msg.size = ipc_msg_size;
 }
 
 
@@ -175,7 +175,7 @@ void Ipc_server::_wait()
 void Ipc_server::_reply()
 {
 	Native_utcb * const utcb = Thread_base::myself()->utcb();
-	utcb->ipc_msg_size(_write_offset);
+	utcb->ipc_msg.size = _write_offset;
 	Kernel::reply(0);
 }
 
diff --git a/base-hw/src/base/pager.cc b/base-hw/src/base/pager.cc
index 1d31b71061..c99157a614 100644
--- a/base-hw/src/base/pager.cc
+++ b/base-hw/src/base/pager.cc
@@ -97,14 +97,14 @@ void Ipc_pager::wait_for_first_fault()
 {
 	while (Kernel::wait_for_request()) { PERR("failed to receive fault"); }
 	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()
 {
 	Native_utcb * const utcb = Thread_base::myself()->utcb();
-	utcb->ipc_msg_size(0);
+	utcb->ipc_msg.size = 0;
 	int err = Kernel::reply(1);
 	if (err) {
 		PERR("failed to receive fault");
@@ -112,7 +112,7 @@ void Ipc_pager::wait_for_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 */
 			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())
 			{
 				/* 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 */
 			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;
 
 			/* resume faulter, send ack to RM and get the next message */
 			Kernel::resume_thread(msg->pager_object->badge());
-			utcb->ipc_msg_size(0);
+			utcb->ipc_msg.size = 0;
 			if (Kernel::reply(1)) {
 				PERR("failed to receive fault");
 				while (Kernel::wait_for_request()) {
 					PERR("failed to receive fault");
 				}
 			}
-			s = utcb->ipc_msg_size();
+			s = utcb->ipc_msg.size;
 			continue; }
 
 		default: {
diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc
index 3a2d6124e5..579f36cef7 100644
--- a/base-hw/src/core/kernel/thread.cc
+++ b/base-hw/src/core/kernel/thread.cc
@@ -90,7 +90,7 @@ void Thread::_received_ipc_request(size_t const s)
 {
 	switch (_state) {
 	case SCHEDULED:
-		_phys_utcb->ipc_msg_size(s);
+		_phys_utcb->ipc_msg.size = s;
 		user_arg_0(0);
 		return;
 	default:
@@ -121,7 +121,7 @@ void Thread::_await_ipc_succeeded(size_t const s)
 {
 	switch (_state) {
 	case AWAITS_IPC:
-		_phys_utcb->ipc_msg_size(s);
+		_phys_utcb->ipc_msg.size = s;
 		user_arg_0(0);
 		_schedule();
 		return;
@@ -604,8 +604,8 @@ void Thread::_syscall_get_thread()
  */
 void Thread::_syscall_wait_for_request()
 {
-	void * const buf_base = _phys_utcb->ipc_msg_base();
-	size_t const buf_size = _phys_utcb->max_ipc_msg_size();
+	void * const buf_base = _phys_utcb->ipc_msg.data;
+	size_t const buf_size = _phys_utcb->ipc_msg_max_size();
 	Ipc_node::await_request(buf_base, buf_size);
 }
 
@@ -622,8 +622,8 @@ void Thread::_syscall_request_and_wait()
 		return;
 	}
 	Ipc_node::send_request_await_reply(
-		dst, _phys_utcb->ipc_msg_base(), _phys_utcb->ipc_msg_size(),
-		_phys_utcb->ipc_msg_base(), _phys_utcb->max_ipc_msg_size());
+		dst, _phys_utcb->ipc_msg.data, _phys_utcb->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()
 {
 	bool const await_request = user_arg_1();
-	void * const msg_base = _phys_utcb->ipc_msg_base();
-	size_t const msg_size = _phys_utcb->ipc_msg_size();
+	void * const msg_base = _phys_utcb->ipc_msg.data;
+	size_t const msg_size = _phys_utcb->ipc_msg.size;
 	Ipc_node::send_reply(msg_base, msg_size);
 
 	if (await_request) {
-		void * const buf_base = _phys_utcb->ipc_msg_base();
-		size_t const buf_size = _phys_utcb->max_ipc_msg_size();
+		void * const buf_base = _phys_utcb->ipc_msg.data;
+		size_t const buf_size = _phys_utcb->ipc_msg_max_size();
 		Ipc_node::await_request(buf_base, buf_size);
 	} else { user_arg_0(0); }
 }