285 lines
56 KiB
HTML
285 lines
56 KiB
HTML
<!-- HTML header for doxygen 1.9.1-->
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||
<meta name="generator" content="Doxygen 1.15.0"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||
<title>L4Re Operating System Framework: L4 Inter-Process Communication (IPC)</title>
|
||
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
||
<script type="text/javascript" src="jquery.js"></script>
|
||
<script type="text/javascript" src="dynsections.js"></script>
|
||
<link href="navtree.css" rel="stylesheet" type="text/css"/>
|
||
<script type="text/javascript" src="navtreedata.js"></script>
|
||
<script type="text/javascript" src="navtree.js"></script>
|
||
<script type="text/javascript" src="cookie.js"></script>
|
||
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||
<script type="text/javascript" src="search/searchdata.js"></script>
|
||
<script type="text/javascript" src="search/search.js"></script>
|
||
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||
<link href="doxygen-awesome.css" rel="stylesheet" type="text/css"/>
|
||
<link href="l4re-awesome.css" rel="stylesheet" type="text/css"/>
|
||
</head>
|
||
<body>
|
||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||
<div id="titlearea">
|
||
<table cellspacing="0" cellpadding="0">
|
||
<tbody>
|
||
<tr style="height: 56px;">
|
||
<td id="projectlogo"><img alt="Logo" src="L4Re_rgb_logo_quer_hg_h55.png"/></td>
|
||
<td id="projectalign" style="padding-left: 0.5em;">
|
||
<div id="projectname">L4Re Operating System Framework
|
||
</div>
|
||
<div id="projectbrief">Interface and Usage Documentation</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- end header part -->
|
||
<!-- Generated by Doxygen 1.15.0 -->
|
||
<script type="text/javascript">
|
||
var searchBox = new SearchBox("searchBox", "search/",'.html');
|
||
</script>
|
||
<script type="text/javascript">
|
||
$(function() { codefold.init(); });
|
||
</script>
|
||
<script type="text/javascript" src="menudata.js"></script>
|
||
<script type="text/javascript" src="menu.js"></script>
|
||
<script type="text/javascript">
|
||
$(function() {
|
||
initMenu('',true,false,'search.php','Search',true);
|
||
$(function() { init_search(); });
|
||
});
|
||
</script>
|
||
<div id="main-nav"></div>
|
||
</div><!-- top -->
|
||
<div id="side-nav" class="ui-resizable side-nav-resizable">
|
||
<div id="nav-tree">
|
||
<div id="nav-tree-contents">
|
||
<div id="nav-sync" class="sync"></div>
|
||
</div>
|
||
</div>
|
||
<div id="splitbar" style="-moz-user-select:none;"
|
||
class="ui-resizable-handle">
|
||
</div>
|
||
</div>
|
||
<script type="text/javascript">
|
||
$(function(){initNavTree('l4re_concepts_ipc.html','',''); });
|
||
</script>
|
||
<div id="container">
|
||
<div id="doc-content">
|
||
<!-- window showing the filter options -->
|
||
<div id="MSearchSelectWindow"
|
||
onmouseover="return searchBox.OnSearchSelectShow()"
|
||
onmouseout="return searchBox.OnSearchSelectHide()"
|
||
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||
</div>
|
||
|
||
<!-- iframe showing the search results (closed by default) -->
|
||
<div id="MSearchResultsWindow">
|
||
<div id="MSearchResults">
|
||
<div class="SRPage">
|
||
<div id="SRIndex">
|
||
<div id="SRResults"></div>
|
||
<div class="SRStatus" id="Loading">Loading...</div>
|
||
<div class="SRStatus" id="Searching">Searching...</div>
|
||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div><div class="header">
|
||
<div class="headertitle"><div class="title">L4 Inter-Process Communication (IPC) </div></div>
|
||
</div><!--header-->
|
||
<div class="contents">
|
||
<div class="textblock"><p>Inter-process communication (IPC) is the fundamental communication mechanism in the <a class="el" href="namespaceL4Re.html" title="L4Re C++ Interfaces.">L4Re</a> Microkernel.</p>
|
||
<p>Basically IPC invokes a subroutine in a different context using input and output parameters. It is used to communicate between userland threads and, as a special case, to communicate between a userland thread and a kernel object. IPC provides the only (non-debugging) way of doing system calls.</p>
|
||
<h1 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_mechanism"></a>
|
||
IPC mechanism</h1>
|
||
<p>When using this API, an IPC operation can be conducted using the <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> function (or one of its related <a class="el" href="group__l4__ipc__api.html">helpers</a>). In general it causes a method to be invoked on the called kernel object. An IPC operation consists of a send and receive phase, but either of them can be skipped, that is, an IPC operation can consist of only either a send or a receive phase. IPC is always synchronous and blocking and can be given a timeout. Timeouts can be specified separately for each phase. Invoking the IPC syscall without any phase is deprecated.</p>
|
||
<p>On the lowest abstraction level, IPC operations need the following arguments:</p><ul>
|
||
<li><a class="el" href="#l4re_concepts_descr_flags">flags</a> describing the IPC mode,</li>
|
||
<li>the <a class="el" href="#l4re_concepts_descr_capidx">capability selector</a> of the communication partner,</li>
|
||
<li>a <a class="el" href="#l4re_concepts_descr_label">label</a>,</li>
|
||
<li>a <a class="el" href="#l4re_concepts_descr_msgtag">message tag</a>, and</li>
|
||
<li>a pair of <a class="el" href="#l4re_concepts_descr_timeouts">timeout</a> values.</li>
|
||
</ul>
|
||
<p>During an IPC operation the kernel accesses the UTCB of the current thread to read parameters which are not passed as direct arguments.</p>
|
||
<p>As result of an IPC operation the kernel returns a message tag and a label and the kernel also changes UTCB content. For the detailed call signature, refer to <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a>. Furthermore, depending on the IPC parameters, the kernel might have transferred the FPU state and capabilities (memory, I/O ports, and/or object capabilities) from the sender to the receiving thread.</p>
|
||
<p>The transition between the IPC send phase and the IPC receive phase is atomic, that is, as soon as the send phase has finished, the thread receive phase starts. A relative receive timeout does not start before the send phase has finished (see also below) and a thread which received an IPC call from another thread can assume that the other thread is ready to receive the reply message and the replying thread can therefore reply with a timeout of zero, see <a class="el" href="#l4re_concepts_descr_timeouts">IPC Timeouts</a>.</p>
|
||
<p>For performance optimization and under certain conditions, the kernel may perform a context switch from the IPC sender to the IPC receiver without consulting the scheduler after the send phase finished. For instance, a client performing an IPC call to a server has to wait for the server anyway. Hence, after the client request was sent to the server, the kernel switches directly to the server thread. This behavior can be disabled by setting the <a class="el" href="group__l4__msgtag__api.html#gga16589e963a73c13aefd2760ce418e053ad220e1ca078f0ea69c8368cb3401d941" title="Enable schedule in IPC flag.">L4_MSGTAG_SCHEDULE</a> flag in the sender message tag (see below).</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_flags"></a>
|
||
IPC Flags</h2>
|
||
<p>The <em>flags</em> defined in <a class="el" href="group__l4__ipc__api.html#gaecfdf101783a02772b67b94793f3a915" title="Capability selector flags.">l4_syscall_flags_t</a> are used by the invoking thread to define the intended IPC operation. The variants of <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> (see <a class="el" href="group__l4__ipc__api.html">Object Invocation</a>) use the flags</p><ul>
|
||
<li>to request the IPC phases (send-only IPC, receive-only IPC, IPC with send and receive phase), and</li>
|
||
<li>to decide, if the reply capability (see <a class="el" href="#l4re_concepts_descr_capidx">below</a>) should be used instead of the capability of a dedicated kernel object as target for the send phase (<em>reply</em>), and</li>
|
||
<li>to decide, if receiving should wait for an incoming message from any possible sender (<em>open wait</em>) instead of a message from a dedicated sender (<em>closed wait</em>).</li>
|
||
</ul>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_capidx"></a>
|
||
Partner capability selector</h2>
|
||
<p>The <em>partner capability selector</em> defines a kernel object as partner of the IPC operation. Some kernel objects forward IPC to a userland thread.</p>
|
||
<p>Basically an object capability is represented by <a class="el" href="group__l4__cap__api.html#ga1445e923ce73029130d569d6e69a4dd8" title="Capability selector type.">l4_cap_idx_t</a> where the bits starting from <a class="el" href="group__l4__cap__api.html#ggafee0421c2fe0e5cfc59f17f16ea10879ac13ad59620aeba353454514a42950a85" title="Capability index shift.">L4_CAP_SHIFT</a> are used as index into the local capability table of the current address space.</p>
|
||
<p>Specifying <a class="el" href="group__l4__cap__api.html#ggafee0421c2fe0e5cfc59f17f16ea10879aff9320ed307e76cebfca6c2871136102" title="Invalid capability selector.">L4_INVALID_CAP</a> as target for an IPC operation is equivalent to specifying a thread capability of the current thread with full permissions. As a result, the userland thread either communicates with its corresponding kernel thread object (if <a class="el" href="group__l4__msgtag__api.html#gga9ac8443c5696208bb0539dd659ea1c92a924bae5fb10fe4a7ad46e959a7fa87d3" title="Protocol for messages to a thread object.">L4_PROTO_THREAD</a> is specified as protocol value, see the description of the message tag <a class="el" href="#l4re_concepts_descr_msgtag">below</a>) or the IPC target is the current userland thread. In the latter case, no IPC will be performed and the send phase and the receive phase will block until the corresponding timeout has expired, see <a class="el" href="#l4re_concepts_descr_timeouts">below</a>.</p>
|
||
<p>A special partner is defined by the <em>reply capability</em>. Since it would be impractical (and a security flaw) to always pass an explicit object capability to reply to for each IPC, the kernel generates an implicit one that can be used for just that purpose if the IPC contains an <b>open wait</b> phase. The reply capability is valid after a receive phase and points to the kernel object that sent the IPC just received. It can be used only once. The reply capability is selected by setting the <a class="el" href="group__l4__ipc__api.html#ggaecfdf101783a02772b67b94793f3a915a21d07c1e159b0e4b2bd824ac052e4508" title="Reply flag.">L4_SYSF_REPLY</a> flag, see <a class="el" href="#l4re_concepts_descr_flags">above</a>.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_label"></a>
|
||
IPC Label</h2>
|
||
<p>The IPC label is a machine word which is transferred unchanged from the IPC sender to the IPC receiver when directly sending to a userland thread. However, the primary purpose of the label is to create a relationship between an <a class="el" href="classL4_1_1Rcv__endpoint.html" title="Interface for kernel objects that allow to receive IPC from them.">L4::Rcv_endpoint</a> (<a class="el" href="classL4_1_1Ipc__gate.html" title="The C++ IPC gate interface, see IPC-Gate API for the C interface.">L4::Ipc_gate</a> or <a class="el" href="classL4_1_1Irq.html" title="C++ Irq interface, see IRQs for the C interface.">L4::Irq</a>) and the bound thread.</p>
|
||
<p>During <a class="el" href="classL4_1_1Rcv__endpoint.html#a44d288dd670226f6845b5bd8c973b15e" title="Bind the IPC receive endpoint to a thread.">L4::Rcv_endpoint::bind_thread()</a>, a label is specified. If the thread receives an IPC message through the endpoint, that label is delivered to the receiving thread as output parameter of <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> instead of the label specified during the corresponding IPC send operation (see the detailed description of <a class="el" href="classL4_1_1Ipc__gate.html" title="The C++ IPC gate interface, see IPC-Gate API for the C interface.">L4::Ipc_gate</a> for more details on the label with IPC gates). The label is usually used by the receiving thread to invoke the object which is responsible for handling the IPC request of the corresponding endpoint. This mechanism is used by the <a class="el" href="structL4_1_1Epiface.html" title="Base class for interface implementations.">L4::Epiface</a> mechanism for server loops.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_msgtag"></a>
|
||
IPC Message Tag</h2>
|
||
<p>The <em>message tag</em> (<a class="el" href="structl4__msgtag__t.html" title="Message tag data structure.">l4_msgtag_t</a>) describes the payload of the IPC and can also be used to enable certain features. It contains:</p><ul>
|
||
<li>a <em>protocol value</em> (cf. <a class="el" href="structl4__msgtag__t.html#a002076380a3f6e4f29a1f6b50ce2bde2" title="Get the protocol value.">l4_msgtag_t::label()</a>, also called the tag's <em>label</em>),</li>
|
||
<li>the number of items in <a class="el" href="#l4re_concepts_descr_mrs">UTCB message registers</a> to transfer (cg. <a class="el" href="structl4__msgtag__t.html#a98577ea730d9abcd938b89d5c7adb18c" title="Get the number of untyped words.">l4_msgtag_t::words()</a> and <a class="el" href="structl4__msgtag__t.html#ad014e4a9f4509b068ddda678f6f8d568" title="Get the number of typed items.">l4_msgtag_t::items()</a>), and</li>
|
||
<li>flags (cf. <a class="el" href="structl4__msgtag__t.html#af6b9564a9a16427cec0e81a4628996b8" title="Get the flags value.">l4_msgtag_t::flags()</a> and <a class="el" href="group__l4__msgtag__api.html#ga16589e963a73c13aefd2760ce418e053" title="Flags for message tags.">L4_msgtag_flags</a>, may be 0).</li>
|
||
</ul>
|
||
<p>The information from the message tag is required by the kernel to transfer the message. The IPC system call returns a message tag as result of the IPC operation. On success, a copy of the message tag specified by the sender is returned if there is a receive phase. Without receive phase, a successful IPC syscall returns the message tag specified as input parameter.</p>
|
||
<p>Failures during IPC are signalled using the <a class="el" href="group__l4__msgtag__api.html#gga16589e963a73c13aefd2760ce418e053aad1669664171cc979970b1e2300bd463" title="Error indicator flag.">L4_MSGTAG_ERROR</a> flag in the message tag. If this bit is set by the kernel, the content of the returned message tag apart from that bit is undefined and the kernel wrote the actual error code into the <a class="el" href="structl4__thread__regs__t.html#a5938a98c49f9b75e46046b36e6f65e89" title="System call error code (see l4_ipc_tcr_error_t).">l4_thread_regs_t::error</a> register of the UTCB (see also <a class="el" href="#l4re_concepts_descr_tcrs">IPC Thread Control Registers</a>). When an IPC error occurs after the rendezvous of the IPC partners, both partners observe the same error information. If, for instance, the IPC was aborted using <a class="el" href="classL4_1_1Thread.html#aacd56bbf983577cfc591f21fd511d3b6" title="Exchange basic thread registers.">L4::Thread::ex_regs()</a>, the sender gets an <a class="el" href="group__l4__ipc__err__api.html#gga896e67446a2348545f520c46a775c3c3abd31d60b580f81f79455eec7c182689b" title="Send operation canceled.">L4_IPC_SECANCELED</a> error while the receiver gets an <a class="el" href="group__l4__ipc__err__api.html#gga896e67446a2348545f520c46a775c3c3a1e8c9ffe50b84ac34aec53e4dc25eb71" title="Receive operation canceled.">L4_IPC_RECANCELED</a> error. The function <a class="el" href="namespaceL4Re.html#ae21329b88c6ffc4917048e8d9564ea99" title="Test a message tag for IPC errors.">L4Re::chkipc()</a> can be used to verify that an IPC operation finished successfully: It throws an error if the IPC failed.</p>
|
||
<p>The <em>protocol value</em> is usually used to distinguish between different protocols of the same interface. Certain protocol IDs are pre-defined when talking to kernel objects, see <a class="el" href="group__l4__msgtag__api.html#ga9ac8443c5696208bb0539dd659ea1c92" title="Message tag for IPC operations.">L4_msgtag_protocol</a>. From IPC point of view, the protocol value is just payload that is transferred from sender to receiver and hence doesn't have a dedicated meaning.</p>
|
||
<p>By convention, during IPC calls, the protocol value is used for return values, where negative values signify errors. See the <a class="el" href="l4_cxx_ipc_iface.html#l4_cxx_ipc_iface_return_types">section</a> about L4 RPC return types for further information. The function <a class="el" href="namespaceL4Re.html#a3f17984019f06676a7e3eecb41bbb0bb" title="Generate C++ exception on error.">L4Re::chksys()</a> can be used to verify that an RPC call using IPC was successful: It throws an error if the IPC failed or if the returned protocol value is negative.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_timeouts"></a>
|
||
IPC Timeouts</h2>
|
||
<p>As written above, IPC <em>timeouts</em> are specified separately for the send phase (IPC send timeout) and the receive phase (IPC receive timeout). The timeout of one phase is encapsulated by <a class="el" href="structl4__timeout__s.html" title="Basic timeout specification.">l4_timeout_s</a>. Both timeouts are combined into a single <a class="el" href="unionl4__timeout__t.html" title="Timeout pair.">l4_timeout_t</a> parameter. Timeouts are either relative to the current time of the invoking thread or absolute. In the latter case, the absolute time of the deadline of the respective phase is written into a UTCB buffer register (see <a class="el" href="group__l4__timeout__api.html#gab3eeabba0542c7723fbd5628c6e4d6c3" title="Set an absolute timeout.">l4_timeout_abs()</a>). The relative timeout of the receive phase starts immediately after the send phase has finished.</p>
|
||
<p>Two specific timeout values are sufficient for most IPC operations:</p><ul>
|
||
<li><a class="el" href="group__l4__timeout__api.html#ga10233285bd94a308b93087f765c83218" title="never timeout">L4_IPC_TIMEOUT_NEVER</a> is used if the IPC partner might not yet be ready. Usually a client trusting a server will perform an IPC call with an infinite timeout for both phases. The send phase will take some time if the IPC receiver is currently not ready. The receive phase will take some time as the server needs time to serve the request. Also, a server will usually wait with an infinite receive timeout for the next request (see below for a possible exception).</li>
|
||
<li><a class="el" href="group__l4__timeout__api.html#ga1fd51d98ee92362453e7bc266fa8b455" title="Timeout constants.">L4_IPC_TIMEOUT_0</a> is used when it is either certain that the IPC receiver is currently ready or if the IPC sender doesn't want to wait if the IPC receiver is not ready. The former case applies to a thread which was called with an IPC call, for example a server got a client request. The reply to the IPC call should use a timeout of zero to ensure that a client doesn't block a server (server could not deliver the result of the request). See also <a class="el" href="structL4_1_1Ipc__svr_1_1Default__timeout.html" title="Mix in for LOOP_HOOKS to use a 0 send and a infinite receive timeout.">L4::Ipc_svr::Default_timeout</a>. Another case is an IPC send operation for waking up another thread from an IPC receive operation. If the other thread is not ready to receive, then it might be already woken up and it does not make sense to wait any longer. Also triggering an IRQ is usually done with a send timeout of 0, see <a class="el" href="structL4_1_1Triggerable.html#a7109ca8b4aeac0169639f973c91a3a6b" title="Trigger the object.">L4::Triggerable::trigger()</a>.</li>
|
||
</ul>
|
||
<p>In certain cases it also makes sense to specify an IPC timeout different from "never" or "zero":</p><ul>
|
||
<li>A server might leave the server loop after some time to perform idle work (see <a class="el" href="classL4_1_1Ipc__svr_1_1Server__iface.html#a7bd56bcdfd81c0be0654492e3016d7eb" title="Add a timeout to the server internal timeout queue.">L4::Ipc_svr::Server_iface::add_timeout()</a>).</li>
|
||
<li>A thread does not want to wait for an infinite time if the partner is not ready. This could be also some safety measure.</li>
|
||
<li>A thread wants to block for a certain amount of time without consuming CPU time. The <a class="el" href="group__l4__ipc__api.html#gac3b4a3b13e77b799dc154c57a04cdd9b" title="Sleep for an amount of time.">l4_ipc_sleep()</a> function specifies the <a class="el" href="group__l4__cap__api.html#ggafee0421c2fe0e5cfc59f17f16ea10879aff9320ed307e76cebfca6c2871136102" title="Invalid capability selector.">L4_INVALID_CAP</a> as target for an IPC receive operation and specifies the intended relative waiting period as IPC timeout. Waiting for an absolute timeout would be possible with similar code.</li>
|
||
</ul>
|
||
<dl class="section note"><dt>Note</dt><dd>The kernel IPC path is optimized for the two special cases using <a class="el" href="group__l4__timeout__api.html#ga10233285bd94a308b93087f765c83218" title="never timeout">L4_IPC_TIMEOUT_NEVER</a> and <a class="el" href="group__l4__timeout__api.html#ga1fd51d98ee92362453e7bc266fa8b455" title="Timeout constants.">L4_IPC_TIMEOUT_0</a>. Specifying a different timeout causes more maintenance effort for the kernel.</dd>
|
||
<dd>
|
||
Special care is required if a finite timeout for the receive phase of an IPC call is specified: The IPC receive operation could abort before the partner was able to send the reply message. Under certain circumstances the partner may still have the temporary reply capability to the calling thread and may use this capability to reply to the caller at a later, unexpected time specifying an arbitrary IPC label. This case is relevant for servers which call another, possibly untrusted, server while serving a client request.</dd></dl>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_utcb"></a>
|
||
User-level Thread Control Block</h2>
|
||
<p>The <a class="el" href="group__l4__utcb__api.html">UTCB</a> is located on a power-of-2-sized and power-of-2-aligned memory area shared between userland and the kernel (<a class="el" href="classL4_1_1Task.html#a9e741ff1d27ca776c65abaff1de2f139" title="Add kernel-user memory.">L4::Task::add_ku_mem()</a>). The UTCB is bound to a thread during the <a class="el" href="classL4_1_1Thread.html#a4252cd0ad4bdfa00cdc61b5fd2317aef" title="Commit the given thread-attributes object.">L4::Thread::control()</a> operation with the <a class="el" href="classL4_1_1Thread_1_1Attr.html" title="Thread attributes used for control().">L4::Thread::Attr</a> parameters set up using <a class="el" href="classL4_1_1Thread_1_1Attr.html#a858c0a51f7b147c4b2ba21d4a97afdbb" title="Bind the thread to a task.">L4::Thread::Attr::bind()</a>. The UTCB is used for IPC-related data exchange and is set up before invoking <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a>. To access certain parts of the UTCB, the corresponding functions have to be used (there is no data type L4_utcb or similar). The UTCB consists of:</p><ul>
|
||
<li>the <a class="el" href="#l4re_concepts_descr_mrs">message registers</a> <span class="tt">MR[0]</span>, <span class="tt">MR[1]</span>, ..., <span class="tt">MR[n-1]</span> with n = <a class="el" href="group__l4__utcb__api__x86.html#ggac03d87ea12ff53e0a7037eb3f9408af8abc15992493ad991b1854c23002fbbe16" title="Total number of message register (MRs) available.">L4_UTCB_GENERIC_DATA_SIZE</a> (access using <a class="el" href="group__l4__utcb__api.html#ga090bdcc433d5ce568b22ec9ab4f3357b" title="Get the message-register block of a UTCB.">l4_utcb_mr()</a>),</li>
|
||
<li>the <a class="el" href="#l4re_concepts_descr_bdr">buffer descriptor register</a> <span class="tt">BDR</span> (access using <a class="el" href="group__l4__utcb__api.html#gae35044c9bae188ccffb2fd90781c60a5" title="Get the buffer-register block of a UTCB.">l4_utcb_br()</a>, see <a class="el" href="structl4__buf__regs__t.html#a852ae37fbb64d4a2f71cbd4c0ba905d1" title="Buffer descriptor.">l4_buf_regs_t::bdr</a>),</li>
|
||
<li>the <a class="el" href="#l4re_concepts_descr_brs">buffer registers</a> <span class="tt">BR[0]</span>, <span class="tt">BR[1]</span>, ..., <span class="tt">BR[m-1]</span> with m = <a class="el" href="group__l4__utcb__api__x86.html#ggac03d87ea12ff53e0a7037eb3f9408af8ad311749a2178cbc16f654fd48fb4930d" title="Total number of buffer registers (BRs) available.">L4_UTCB_GENERIC_BUFFERS_SIZE</a> (access using <a class="el" href="group__l4__utcb__api.html#gae35044c9bae188ccffb2fd90781c60a5" title="Get the buffer-register block of a UTCB.">l4_utcb_br()</a>),</li>
|
||
<li>the <a class="el" href="#l4re_concepts_descr_tcrs">thread control registers</a> (access using <a class="el" href="group__l4__utcb__api.html#ga78ce6eec1d9b19af0f87119c6ac72716" title="Get the thread-control-register block of a UTCB.">l4_utcb_tcr()</a>, includes the IPC error code), and</li>
|
||
<li>in case of an exception IPC, the register state of the thread which triggered the exception (access using <a class="el" href="group__l4__utcb__exc__api.html#ga3d957c3c28e526804e2c1a2e183df88f" title="Get the message-register block of a UTCB (for an exception IPC).">l4_utcb_exc()</a>).</li>
|
||
</ul>
|
||
<p>IPC to a kernel object requires the setup of the UTCB of the corresponding userlevel thread. IPC between userlevel threads requires the setup of UTCBs of both partners.</p>
|
||
<p>The kernel changes only the following UTCB content:</p><ul>
|
||
<li>The message registers of the UTCB of the receiver of an IPC, and</li>
|
||
<li>the IPC error field of the thread invoking <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> if there was an error during IPC.</li>
|
||
</ul>
|
||
<h3 class="doxsection"><a class="anchor" id="l4re_concepts_descr_mrs"></a>
|
||
IPC Message registers</h3>
|
||
<p>The <em>message registers</em> contain <em>untyped items</em> and <em>typed items</em>. The sender's typed items are interpreted by the kernel in conjunction with the receiver's <em>receive items</em>. Each typed send item occupies two message registers. The untyped items, on the other hand, are free to be used by the communication partners to exchange data: The content of all message registers used for untyped items (<a class="el" href="structl4__msgtag__t.html#a98577ea730d9abcd938b89d5c7adb18c" title="Get the number of untyped words.">l4_msgtag_t::words()</a>) is copied from the UTCB of the IPC sender to the UTCB of the IPC receiver.</p>
|
||
<p>A typed send item consists of a <em>flexpage</em> (see <a class="el" href="group__l4__fpage__api.html#ga8d185d1e2ec513f1b3e8a5634469b756" title="Create a memory flexpage.">l4_fpage()</a>, <a class="el" href="group__l4__fpage__api.html#ga3eaf59757a63812044e2b3a1cdf09d54" title="Create a kernel-object flexpage.">l4_obj_fpage()</a>, and <a class="el" href="group__l4__fpage__api.html#gab918a25f8a923b7a68158e737d4801a8" title="Create an IO-port flexpage.">l4_iofpage()</a>) of the to be transferred capabilities (<em>flexpage word</em>) and a <em>message word</em>. There are two types of send items: <em>map items</em> and <em>void items</em>. For a void item, the message word is all zero. For a map item, the message word contains:</p><ul>
|
||
<li>the <em>compound bit</em> allowing to use the same receive buffer for the subsequent typed send item (scatter-gather behavior, see <a class="el" href="group__l4__msgitem__api.html#gga94ecfe2908867c4ed0c13a7a97337f6aac4ea7fecbdc440401bde677de3df051d" title="Denote that the following item shall be put into the same receive item as this one.">L4_ITEM_CONT</a> of <a class="el" href="group__l4__msgitem__api.html#ga94ecfe2908867c4ed0c13a7a97337f6a" title="Constants for message items.">l4_msg_item_consts_t</a>),</li>
|
||
<li>the <em>type bit</em> defining this typed send item as a <em>map item</em>,</li>
|
||
<li>the <em>grant flag</em> for delegating the access to the flexpage from the sender to the receiver and atomically removing the rights from the sender (see <a class="el" href="group__l4__msgitem__api.html#ga94ecfe2908867c4ed0c13a7a97337f6a" title="Constants for message items.">l4_msg_item_consts_t</a>),</li>
|
||
<li><em>attributes</em> with semantics depending on the item type; for memory mappings, they contain cacheability information (see <a class="el" href="group__l4__msgitem__api.html#ga547729eef68ea9c0e085c34a66e133fa" title="Cacheability options for memory send items.">l4_fpage_cacheability_opt_t</a>); for objects, they contain additional rights (see <a class="el" href="group__l4__msgitem__api.html#gad142e99a533af52d358f9940fa00966a" title="Attributes and additional permissions for object send items.">L4_obj_fpage_ctl</a>),</li>
|
||
<li>the <em>send base</em> (also called <em>hot spot</em>) defining what is actually mapped when send and receive flexpages have a different size.</li>
|
||
</ul>
|
||
<p>A typed send item can be created using <a class="el" href="group__l4__ipc__api.html#gad2fef5fd3d173495d89c122883e909d6" title="Add a flexpage to be sent to the UTCB.">l4_sndfpage_add()</a>. This function sets the compound bit unconditionally. Alternatively, the functions <a class="el" href="group__l4__msgitem__api.html#ga1ce1321fd25614e9af43a35819540ba7" title="Create the first word for a map item that is a send item for the memory space.">l4_map_control()</a> and <a class="el" href="group__l4__msgitem__api.html#ga6c9056957ac92e458eaabcbf3223ce6f" title="Create the first word for a map item that is a send item for the object space.">l4_map_obj_control()</a> can be used to set up the message word of a map item for a memory flexpage respective for objects.</p>
|
||
<p>See <a class="el" href="#l4re_concepts_descr_transfer">below</a> for a description how typed items are transferred.</p>
|
||
<h3 class="doxsection"><a class="anchor" id="l4re_concepts_descr_brs"></a>
|
||
IPC Buffer Registers</h3>
|
||
<p>The <em>buffer registers</em> and <em>buffer descriptor register</em> are interpreted by the kernel during the receive phase (if any). <a class="el" href="structBuffer.html" title="Data buffer used to transfer packets.">Buffer</a> registers define <em>receive items</em> which are required to receive typed send items (memory, I/O ports or object capabilities). To specify a receive item, up to three buffer registers are required:</p><ul>
|
||
<li>A <em>small receive item</em> (<a class="el" href="classL4_1_1Ipc_1_1Small__buf.html" title="A receive item for receiving a single object capability.">L4::Ipc::Small_buf</a>) occupying one buffer register is sufficient to receive one object capability.</li>
|
||
<li>A <em>receive item</em> (<a class="el" href="classL4_1_1Ipc_1_1Rcv__fpage.html" title="Non-small receive item.">L4::Ipc::Rcv_fpage</a>) occupying two or three buffer registers (<em>message word</em>, a <em>flexpage</em>, and an optional destination task capability index) is required to receive memory flexpages, I/O ports, or multiple object capabilities.</li>
|
||
</ul>
|
||
<h3 class="doxsection"><a class="anchor" id="l4re_concepts_descr_bdr"></a>
|
||
IPC Buffer Descriptor Register</h3>
|
||
<p>The buffer descriptor register defines indices of buffer registers used to receive dedicated types of send items and also contains a flag:</p><ul>
|
||
<li>5 bits starting at <a class="el" href="group__l4__utcb__br__api.html#gga70354800866c2fd27294d42109045553ad7435ad3e99a1f6aea9fb8175dd3deb1" title="Bit offset for the memory-buffer index.">L4_BDR_MEM_SHIFT</a> define the index of the first receive item used for memory flexpages.</li>
|
||
<li>5 bits starting at <a class="el" href="group__l4__utcb__br__api.html#gga70354800866c2fd27294d42109045553a5bdf4f4b8bb8c0bfb93b2cdece7026da" title="Bit offset for the IO-buffer index.">L4_BDR_IO_SHIFT</a> define the index of the first receive item used for I/O flexpages.</li>
|
||
<li>5 bits starting at <a class="el" href="group__l4__utcb__br__api.html#gga70354800866c2fd27294d42109045553ae681d10aa94dc46e666d42d3a18ebf70" title="Bit offset for the capability-buffer index.">L4_BDR_OBJ_SHIFT</a> define the index of the first receive item used for object flexpages.</li>
|
||
<li>The <a class="el" href="group__l4__utcb__api__x86.html#ggac03d87ea12ff53e0a7037eb3f9408af8aa7fb27ae80eb4f7d3356bfa4ab637648" title="BDR flag to accept reception of FPU state.">L4_UTCB_INHERIT_FPU</a> can be set using <a class="el" href="group__l4__utcb__br__api.html#gacebc13d69883825a309b381a6aabe7b7" title="Enable or disable inheritance of FPU state to receiver.">l4_utcb_inherit_fpu()</a> and allows to receive the FPU state from the IPC sender. This is only relevant if the sender set <a class="el" href="group__l4__msgtag__api.html#gga16589e963a73c13aefd2760ce418e053aea4fd67d2f81b00e6949ddcdc7beb5f9" title="Enable FPU transfer flag for IPC.">L4_MSGTAG_TRANSFER_FPU</a> in the message tag.</li>
|
||
</ul>
|
||
<p>For most use cases, a BDR value of zero is sufficient. In that case, if <span class="tt">BR[0]</span> contains a void item, no capabilities are received. Otherwise, only one type of capabilities (memory, I/O ports or objects) can be received even if there are several receive items. For more complex setups that require receiving different types of capabilities in one receive operation, other BDR values are necessary.</p>
|
||
<p>The BDR of the receiving thread is only used by the kernel if at least one typed item is transferred during the IPC or if <a class="el" href="group__l4__msgtag__api.html#gga16589e963a73c13aefd2760ce418e053aea4fd67d2f81b00e6949ddcdc7beb5f9" title="Enable FPU transfer flag for IPC.">L4_MSGTAG_TRANSFER_FPU</a> is set in the UTCB of the sending thread.</p>
|
||
<h3 class="doxsection"><a class="anchor" id="l4re_concepts_descr_tcrs"></a>
|
||
IPC Thread Control Registers</h3>
|
||
<p>The <a class="el" href="structl4__thread__regs__t.html#a5938a98c49f9b75e46046b36e6f65e89" title="System call error code (see l4_ipc_tcr_error_t).">l4_thread_regs_t::error</a> register contains the IPC error code in case the <a class="el" href="group__l4__msgtag__api.html#gga16589e963a73c13aefd2760ce418e053aad1669664171cc979970b1e2300bd463" title="Error indicator flag.">L4_MSGTAG_ERROR</a> flag is set in the message tag returned by an IPC syscall. Otherwise this register is not touched by the kernel. See <a class="el" href="group__l4__ipc__err__api.html#ga896e67446a2348545f520c46a775c3c3" title="Error codes in the error TCR.">l4_ipc_tcr_error_t</a> for a detailed enumeration of all possible error codes during an IPC operation.</p>
|
||
<p>The <a class="el" href="structl4__thread__regs__t.html#a50e81e415f7d4ca398b320f9e9d507be" title="Kernel free marker.">l4_thread_regs_t::free_marker</a> is set by the kernel to zero immediately before a thread is destroyed. This value indicates that the kernel does not longer use the UTCB and it can be re-used by other threads.</p>
|
||
<p>The other members of <a class="el" href="structl4__thread__regs__t.html" title="Encapsulation of the thread-control-register block of the UTCB.">l4_thread_regs_t</a> are never touched by the kernel.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_descr_transfer"></a>
|
||
Transfer of Typed Send Items</h2>
|
||
<p>The kernel interprets all typed items in the sender UTCB (<a class="el" href="structl4__msgtag__t.html#ad014e4a9f4509b068ddda678f6f8d568" title="Get the number of typed items.">l4_msgtag_t::items()</a>) and performs the following operations while modifying the corresponding typed items in the receiver UTCB:</p><ul>
|
||
<li>If the message item of the sender is void, this item is ignored and the message word of the corresponding typed item in the receiver UTCB is set to zero (making it a void item). The flexpage word of this item is not changed.</li>
|
||
<li>Otherwise, if the type bit of the message item of the sender is not set, the IPC is aborted with <a class="el" href="group__l4__ipc__err__api.html#gga896e67446a2348545f520c46a775c3c3acea5de2618320038175e88cbd1007bf7" title="Sent message truncated.">L4_IPC_SEMSGCUT</a> / <a class="el" href="group__l4__ipc__err__api.html#gga896e67446a2348545f520c46a775c3c3acfe35ea38d9bd5b67200793f96c6d7f2" title="Received message truncated.">L4_IPC_REMSGCUT</a>.</li>
|
||
<li>Otherwise, if there is a receive item corresponding to the flexpage type of the send item available (see <a class="el" href="#l4re_concepts_descr_bdr">IPC Buffer Descriptor Register</a>), information described by the flexpage is transferred to the receiver.</li>
|
||
</ul>
|
||
<p>In the last case, the message word of the typed item in the receiver UTCB is modified to contain the send base, the type and the size of the transferred flexpage, as well as a copy of the compound bit and the type bit of the send item. If the receiver ordered a local ID in the corresponding receive item, the kernel attempts to apply special rules, see <a class="el" href="group__l4__msgitem__api.html#gga94ecfe2908867c4ed0c13a7a97337f6aa9ec3db5390483f9f0cd4a4571b04b5be" title="The receiver requests to receive a local ID instead of a mapping whenever possible.">L4_RCV_ITEM_LOCAL_ID</a>. Otherwise, regular mappings as described by the flexpage of the send item are created in the receiver space.</p>
|
||
<p>A receive item forms a <em>receive window</em> of a specific address and size in the receiver space. Each typed send item that is a map item requires a corresponding receive item. By default, there is a one-to-one mapping (one receive item per typed send item) but it is also possible to use one receive item to receive several typed send items: The compound bit (see <a class="el" href="group__l4__msgitem__api.html#ga94ecfe2908867c4ed0c13a7a97337f6a" title="Constants for message items.">l4_msg_item_consts_t</a>) of a send item defines if the following typed send item shall use the same receive item as the current one for receiving the flexpage. If the compound bit is set, proper values of the send base shall be used to prevent overlapping of addresses in the receiver space.</p>
|
||
<p>The send base is relevant when the size of the receive flexpage differs from the size of the transferred resource. As a typical example, triggering a memory page fault opens a receive window covering the entire memory address space of the faulting thread. The pager will usually reply a memory flexpage smaller than the entire address space of the faulting thread. Hence, the pager has to specify a proper base which is used as offset of the sent object in the receive flexpage in the <em>receiver space</em>. If the sender flexpage is bigger than the receive window, a flexpage of the size of the receive window starting at the send base in the <em>sender space</em> is transferred to the receiver.</p>
|
||
<p>The kernel will stop transmission of typed items before <a class="el" href="structl4__msgtag__t.html#ad014e4a9f4509b068ddda678f6f8d568" title="Get the number of typed items.">l4_msgtag_t::items()</a> is reached either if it finds a void item as receive buffer or if the flexpage type of the send item does not match the flexpage type of the corresponding receive item. Under both conditions, the IPC is aborted with <a class="el" href="group__l4__ipc__err__api.html#gga896e67446a2348545f520c46a775c3c3acea5de2618320038175e88cbd1007bf7" title="Sent message truncated.">L4_IPC_SEMSGCUT</a> / <a class="el" href="group__l4__ipc__err__api.html#gga896e67446a2348545f520c46a775c3c3acfe35ea38d9bd5b67200793f96c6d7f2" title="Received message truncated.">L4_IPC_REMSGCUT</a>.</p>
|
||
<dl class="section note"><dt>Note</dt><dd>The kernel ignores the flexpage access rights of the receive items. The actual rights for a transferred resource in the target address space are defined by the access rights to that resource of the IPC sender address space and the flexpage access rights in the typed send item. Additionally, when transferring object capabilities, the transferred rights also depend on the sender’s rights on the capability invoked for IPC.</dd></dl>
|
||
<p>The kernel does not unmap capabilities in the receive window when there is no capability present at the corresponding index at the sender. Further, the receiver cannot reliably detect at which capability indices it received capabilities in its receive windows. Therefore, before receiving from an untrusted source, all receive windows should be cleared. Otherwise the receiver may erroneously associate a capability in one of its receive windows with his last IPC partner although it was actually received in an earlier IPC.</p>
|
||
<p>However, the kernel indicates if at least one object capability was received or not, see <a class="el" href="classL4_1_1Ipc_1_1Snd__fpage.html#af9b4655a879646d2e79818e71ef28d81" title="(Defined for return items only.) Check if at least one object capability has been mapped for this ite...">L4::Ipc::Snd_fpage::cap_received()</a>.</p>
|
||
<h1 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_examples"></a>
|
||
Examples</h1>
|
||
<p>A number of examples show the interplay of the concepts introduced so far.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_examples_1"></a>
|
||
User Thread to Kernel Object</h2>
|
||
<p>The <a class="el" href="classL4_1_1Scheduler.html" title="C++ interface of the Scheduler kernel object, see Scheduler for the C interface.">L4::Scheduler</a> kernel object has a method <a class="el" href="classL4_1_1Scheduler.html#a0ab0511264542f083786e88ee1edd2e4" title="Query the idle time (in µs) of a CPU.">L4::Scheduler.idle_time()</a>. It takes a set of CPUs to query, represented by two machine words.</p>
|
||
<p>In user space, the function <a class="el" href="classL4_1_1Cap.html" title="C++ interface for capabilities.">L4::Cap<L4::Scheduler></a>->idle_time() is called, which does the following:</p><ul>
|
||
<li>Fill <span class="tt">MR[0]</span> with a constant identifying the method being called (<a class="el" href="group__l4__scheduler__api.html#gga0b5a4009c40728ca0326ae9a603a9c0ba0f92c789b1f2b6c4fbd1339651561398" title="Query idle time for the scheduler.">L4_SCHEDULER_IDLE_TIME_OP</a>).</li>
|
||
<li>Fill <span class="tt">MR[1]</span> and <span class="tt">MR[2]</span> with the two words making up the CPU set.</li>
|
||
<li>Set up the message tag with the protocol value (<a class="el" href="group__l4__msgtag__api.html#gga9ac8443c5696208bb0539dd659ea1c92a268c2ee39d5ca854c5879837ce735997" title="Protocol for messages to a scheduler object.">L4_PROTO_SCHEDULER</a>), the number of untyped and typed items (3 and 0), and some flags.</li>
|
||
<li>Call <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> with the partner capability ID, the tag, the pointer to the filled UTCB, infinite timeouts, and with flags indicating a send and receive phase. (The label does not matter in this case.)</li>
|
||
</ul>
|
||
<p>This function traps into kernel space using standard platform specific mechanisms. The kernel reads the protocol value on the message tag, checks that the partner capability ID refers to a valid object that speaks that protocol, and dispatches the message to the appropriate handler. The handler fills the first 64 bits of the message registers with the computed time value. This will cover <span class="tt">MR[0]</span> on 64-bit architectures and <span class="tt">MR[0]</span> and <span class="tt">MR[1]</span> on 32-bit architectures. It then sets up the return message tag:</p><ul>
|
||
<li>The number of untyped items is 1 or 2.</li>
|
||
<li>The number of typed items is 0.</li>
|
||
<li>The protocol value contains the return value and is set to 0.</li>
|
||
<li>An error would be signalled as a negative protocol value. Under certain conditions (e.g. wrong kernel object capability specified), the error is signalled as IPC error (see <a class="el" href="group__l4__msgtag__api.html#gga16589e963a73c13aefd2760ce418e053aad1669664171cc979970b1e2300bd463" title="Error indicator flag.">L4_MSGTAG_ERROR</a> in the description of the <a class="el" href="#l4re_concepts_descr_msgtag">IPC Message Tag</a>).</li>
|
||
<li>(The return label is as irrelevant in this case as the send label.)</li>
|
||
</ul>
|
||
<p>This reply is received by the receive phase of the original <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> call from userland. Finally the <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> function copies the time value out of the message registers and forwards it with a possible error from the message tag flags to its caller.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_examples_2"></a>
|
||
User Thread to User Thread</h2>
|
||
<p>When the target kernel object is of type <a class="el" href="classL4_1_1Thread.html" title="C++ L4 kernel thread interface, see Thread for the C interface.">L4::Thread</a> (or <a class="el" href="classL4_1_1Ipc__gate.html" title="The C++ IPC gate interface, see IPC-Gate API for the C interface.">L4::Ipc_gate</a>, but we will cover this in the example <a class="el" href="#l4re_concepts_ipc_examples_3">below</a>) and the message tag's protocol value is not <a class="el" href="group__l4__msgtag__api.html#gga9ac8443c5696208bb0539dd659ea1c92a924bae5fb10fe4a7ad46e959a7fa87d3" title="Protocol for messages to a thread object.">L4_PROTO_THREAD</a>, the kernel will forward the IPC message to the userland thread represented by the kernel object. There it can be received by a call to <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a>. The restriction of the protocol number is necessary because one also wants to invoke <a class="el" href="classL4_1_1Thread.html" title="C++ L4 kernel thread interface, see Thread for the C interface.">L4::Thread</a>'s control methods such as <a class="el" href="classL4_1_1Thread.html#a7bb604d3fe94545ad9e44b46600aef46" title="Switch execution to this thread.">L4::Thread.switch_to()</a> or <a class="el" href="classL4_1_1Thread.html#aacd56bbf983577cfc591f21fd511d3b6" title="Exchange basic thread registers.">L4::Thread.ex_regs()</a>. Besides this restriction, the interpretation of all the IPC parameters and the untyped items of the UTCB is up to the communication partners.</p>
|
||
<h3 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_examples_2_1"></a>
|
||
Simple Messages</h3>
|
||
<p>A simple example is a client calling a server to have a computation performed on a value: Similar to IPC from a userland thread to a kernel object, the client writes the value to <span class="tt">MR[0]</span>. It sets up the message tag with some agreed upon protocol value (which, as explained above, must be different from <a class="el" href="group__l4__msgtag__api.html#gga9ac8443c5696208bb0539dd659ea1c92a924bae5fb10fe4a7ad46e959a7fa87d3" title="Protocol for messages to a thread object.">L4_PROTO_THREAD</a>), number of untyped items to 1, typed items to 0, and no flags set. The client may want to pass a label that identifies itself, as many clients can use the server. In this context, the identifier might also be passed via the message registers, but the label is the proper place for this, as it gets a special treatment by the kernel for IPC gates (covered by the example <a class="el" href="#l4re_concepts_ipc_examples_3">below</a>). The client then calls <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> with the tag, label and flags indicating it wants a send phase and a receive phase (as it wants a result back). The target is the capability index referring to a capability for the <a class="el" href="classL4_1_1Thread.html" title="C++ L4 kernel thread interface, see Thread for the C interface.">L4::Thread</a> kernel object of the server.</p>
|
||
<p>To be able to receive an IPC message, the server has set up a UTCB of its own and called <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> with flags indicating it only wants to enter a receive phase and it accepts IPCs from any partner. This is called an <b>open wait</b>. (The alternative would be to specify a capability index referring to a <a class="el" href="classL4_1_1Thread.html" title="C++ L4 kernel thread interface, see Thread for the C interface.">L4::Thread</a> capability to exclusively receive from.)</p>
|
||
<p>Both system calls (the send IPC initiated by the client and the receive IPC initiated by the server) may be seen by the kernel in any order but the IPC will not start before sender and receiver are ready. In that case the kernel will copy the relevant message registers the client specified in the message tag from the client's UTCB to the server's UTCB, in the current example just <span class="tt">MR[0]</span>. It will then switch the client to the receive phase of its call (which cannot yet be executed) and return the server's call with the message tag and label.</p>
|
||
<p>The server inspects the tag for the correct protocol value and number of untyped items passed, inspect the label to decide whether it maybe wants special treatment of this particular client, performs the computation on <span class="tt">MR[0]</span> and writes the result back to <span class="tt">MR[0]</span> (or to more words, depending on what exactly it computes). It sets up the tag in the usual way, but probably needs to pass no label, as the client knows who it is talking to.</p>
|
||
<p>For the reply, the server makes use the reply capability (see <a class="el" href="#l4re_concepts_descr_capidx">above</a>). Since the client sent the last IPC to the server, the reply capability will point to it. So when the server calls <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> with the computed result in the message registers and using the reply capability as target, the kernel knows to forward this to the client's thread. The kernel copies the message registers from the server's UTCB to the client's UTCB, and the client's <a class="el" href="group__l4__ipc__api.html#ga1caa56d45e0453b3002e7f5cfdb0dec7" title="Generic L4 object invocation.">l4_ipc()</a> system call, which is still stuck in the receive phase, is returned with the tag.</p>
|
||
<p>The client looks at the tag and then the message registers for its wanted result and the example is concluded.</p>
|
||
<h3 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_examples_2_2"></a>
|
||
Send Items</h3>
|
||
<p>IPC between userland threads is also used to transfer typed items: Memory, I/O ports, and objects, all represented as flexpages. Typed items and untyped items can be part of the same IPC. As general rule, the sender specifies what he wants to send, the receiver where and how much it wants to receive, and the kernel checks the required permissions before doing the actual transfer. As written before, this mechanism is synchronous and the receiver cannot be transferred items against its will. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__l4__fpage__api.html" title="Flexpage-related API.">Flexpages</a></dd></dl>
|
||
<p>Suppose a client wants a server to have read only access to a page of its memory. The client sets up a flexpage covering the page and with only the <a class="el" href="group__l4__fpage__api.html#gga5d4f4972d58f72b2a33b6c139b5950a8a555326b01b4fe72916157bdc90307691" title="Read-only flexpage.">L4_FPAGE_RO</a> right set. The server sets up a flexpage of a memory region where it will receive the mapping. This may be larger than one page, suppose for our case four pages, in which case the exact position of the mapping will be resolved by the send base provided by the sender. The client combines the hot spot and some flags into a machine word and writes it to <span class="tt">MR[0]</span> (see also <a class="el" href="group__l4__msgitem__api.html#ga1ce1321fd25614e9af43a35819540ba7" title="Create the first word for a map item that is a send item for the memory space.">l4_map_control()</a>). At <span class="tt">MR[1]</span> follows the flexpage it wants to send (see also <a class="el" href="group__l4__fpage__api.html#ga8d185d1e2ec513f1b3e8a5634469b756" title="Create a memory flexpage.">l4_fpage()</a>). The server does almost the same but writes the words to <span class="tt">BR[0]</span> and <span class="tt">BR[1]</span>. (The server could also specify a hot spot, but it is currently ignored by the kernel.) The client specifies 1 typed and 0 untyped items in the message tag. The server writes 0 to <span class="tt">BDR</span> to specify that the first receive item starts at the first buffer register.</p>
|
||
<p>Both client and server initiate their IPC, the client with only a send phase to the server, and the server with an open wait receive phase. The kernel checks the compatibility of the send items and the receive buffers (e.g. that no object capability flexpage is sent to a receive buffer describing a memory mapping flexpage) and updates its internal structures to reflect the change. In our case, the sender's hot spot indicates to which of the four pages that make up the receive buffer the sent page should be mapped. The kernel also translates the typed send item to the server's address space and stores it in the server's UTCB at <span class="tt">MR[0]</span> and <span class="tt">MR[1]</span>.</p>
|
||
<p>Once the server returns from its syscall, it will have read access to the client's shared page.</p>
|
||
<h2 class="doxsection"><a class="anchor" id="l4re_concepts_ipc_examples_3"></a>
|
||
User Thread to User Object</h2>
|
||
<p>A common use case for thread to thread communication is when a server implements a number of object interfaces and a client wants to invoke methods on them. For security reasons, the server does not want to hand out its thread capability to everyone it nonetheless wants to serve. It also may not want to allow every client access to everyone of its interfaces. For this purpose, IPC gates implemented by the kernel object <a class="el" href="classL4_1_1Ipc__gate.html" title="The C++ IPC gate interface, see IPC-Gate API for the C interface.">L4::Ipc_gate</a> can be used. An IPC gate can be bound to a thread and forwards IPC to it. In doing so it applies two transformations</p><ol type="1">
|
||
<li>It sets the label to a predefined value.</li>
|
||
<li>It changes the rights of transferred items (see <a class="el" href="group__l4__fpage__api.html#ggaee60789a48cab2782f5a368237591b39acb2b2e95f6be245f64937ac48a068066" title="Interface specific 'S' right for capability flexpages.">L4_CAP_FPAGE_S</a>).</li>
|
||
</ol>
|
||
<p>For each object of every interface the server implements, it creates an IPC gate and binds it to itself (see <a class="el" href="classL4_1_1Rcv__endpoint.html#a44d288dd670226f6845b5bd8c973b15e" title="Bind the IPC receive endpoint to a thread.">L4::Ipc_gate::bind_thread()</a>). It sets the gate's label to a unique value identifying the object. Then it hands the gate out to clients. Several clients can be handed the same gate and will all end up invoking methods on the same object.</p>
|
||
<p>Instead of setting the target as the server's thread kernel object, the client uses the IPC gate's instead. The label the client sends is irrelevant, as the gate will overwrite it with the value the server has set during the bind operation. The server executes an open wait, and the kernel performs the same operation as in the above <a class="el" href="#l4re_concepts_ipc_examples_2_2">example</a> with the transformed IPC finally ending up in the server's thread.</p>
|
||
<p>The server checks that the received label refers to one of its objects. It then checks if the protocol value in the message tag matches the interface the object implements. Then it invokes the method specified in <span class="tt">MR[0]</span> with the rest of the arguments. Finally it returns the results via UTCB and message tag to the reply capability and waits for the next IPC. </p>
|
||
</div></div><!-- contents -->
|
||
</div><!-- PageDoc -->
|
||
</div><!-- doc-content -->
|
||
<div id="page-nav" class="page-nav-panel">
|
||
<div id="page-nav-resize-handle"></div>
|
||
<div id="page-nav-tree">
|
||
<div id="page-nav-contents">
|
||
</div><!-- page-nav-contents -->
|
||
</div><!-- page-nav-tree -->
|
||
</div><!-- page-nav -->
|
||
</div><!-- container -->
|
||
<!-- HTML footer for doxygen 1.9.1-->
|
||
<!-- start footer part -->
|
||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||
<ul>
|
||
<li class="navelem"><a href="l4re_concepts.html">Programming for L4Re</a></li>
|
||
<li class="footer">Generated on <span class="timestamp"></span> for L4Re Operating System Framework by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.15.0 </li>
|
||
</ul>
|
||
</div>
|
||
</body>
|
||
</html>
|