1%
2% Copyright 2014, General Dynamics C4 Systems
3%
4% This software may be distributed and modified according to the terms of
5% the GNU General Public License version 2. Note that NO WARRANTY is provided.
6% See "LICENSE_GPLv2.txt" for details.
7%
8% @TAG(GD_GPL)
9%
10
11\chapter{\label{ch:io}Hardware I/O}
12
13\section{Interrupt Delivery}
14\label{sec:interrupts}
15
16Interrupts are delivered as notifications. A thread
17may configure the kernel to signal a particular \obj{Notification}
18object each time a certain interrupt triggers. Threads may then wait for
19interrupts to occur by calling \apifunc{seL4\_Wait}{sel4_wait} or
20\apifunc{seL4\_Poll}{sel4_poll} on
21that \obj{Notification}.
22
23
24\obj{IRQHandler} capabilities represent the ability of a thread to
25configure a certain interrupt. They have three methods:
26
27\begin{description}
28    \item[\apifunc{seL4\_IRQHandler\_SetNotification}{irq_handlersetnotification}]
29    specifies the \obj{Notification} the kernel should
30    \apifunc{signal}{sel4_signal} when an interrupt occurs. A driver
31    may then call \apifunc{seL4\_Wait}{sel4_wait} or \apifunc{seL4\_Poll}{sel4_poll}
32    on this notification to
33    wait for interrupts to arrive.
34
35    \item[\apifunc{seL4\_IRQHandler\_Ack}{irq_handleracknowledge}]
36    informs the kernel that the userspace driver has finished processing
37    the interrupt and the microkernel can send further pending or new
38    interrupts to the application.
39
40    \item[\apifunc{seL4\_IRQHandler\_Clear}{irq_handlerclear}]
41    de-registers the \obj{Notification} from the \obj{IRQHandler} object.
42\end{description}
43
44When the system first starts, no \obj{IRQHandler} capabilities are
45present. Instead, the initial thread's CSpace contains a single
46\obj{IRQControl} capability. This capability may be used to produce
47a single \obj{IRQHandler} capability for each interrupt available in the
48system. Typically, the initial thread of a system will determine which
49IRQs are required by other components in the system, produce an
50\obj{IRQHandler} capability for each interrupt, and then delegate the
51resulting capabilities as appropriate. Methods on \obj{IRQControl} can
52be used for creating \obj{IRQHandler} capabilities for interrupt sources.
53
54\ifxeightsix
55\section{x86-Specific I/O}
56
57\subsection{Interrupts}
58\label{sec:x86_interrupts}
59
60In addition to managing \obj{IRQHandler} capabilities, x86 platforms require
61the delivery location in the CPU vectors to be configured. Regardless of where
62an interrupt comes from (IOAPIC, MSI, etc) it must be assigned a unique vector
63for delivery, ranging from VECTOR\_MIN to VECTOR\_MAX. The rights to allocate
64a vector are effectively given through the \obj{IRQControl} capability and can
65be considered as the kernel outsourcing the allocation of this namespace to
66user level.
67
68\begin{description}
69    \item[\apifunc{seL4\_IRQControl\_GetIOAPIC}{x86_irq_handler_getioapic}] creates
70    an \obj{IRQHandler} capability for an IOAPIC interrupt
71
72    \item[\apifunc{seL4\_IRQControl\_GetMSI}{x86_irq_handler_getmsi}] creates
73    an \obj{IRQHandler} capability for an MSI interrupt
74\end{description}
75
76\subsection{I/O Ports}
77\label{sec:ioports}
78
79On x86 platforms, seL4 provides access to I/O ports to user-level threads.
80Access to I/O ports is controlled by \obj{IO Port} capabilities. Each
81\obj{IO Port} capability identifies a range of ports that can be accessed with
82it. Reading from I/O ports is accomplished with the
83\apifunc{seL4\_X86\_IOPort\_In8}{x86_io_port_in8},
84\apifunc{seL4\_X86\_IOPort\_In16}{x86_io_port_in16}, and
85\apifunc{seL4\_X86\_IOPort\_In32}{x86_io_port_in32} methods, which
86allow for reading of 8-, 16- and 32-bit quantities.
87Similarly, writing to I/O ports is accomplished with the
88\apifunc{seL4\_X86\_IOPort\_Out8}{x86_io_port_out8},
89\apifunc{seL4\_X86\_IOPort\_Out16}{x86_io_port_out16}, and
90\apifunc{seL4\_X86\_IOPort\_Out32}{x86_io_port_out32} methods.
91Each of these methods takes as arguments an \obj{IO Port} capability
92and an unsigned integer~\texttt{port}, which indicates the I/O port to read from
93or write to, respectively.
94In each case, \texttt{port} must be within the range of I/O ports identified
95by the given \obj{IO Port} capability in order for the method to succeed.
96
97The I/O port methods return error codes upon failure.
98A \texttt{seL4\_IllegalOperation} code is returned if port access is
99attempted outside the range allowed by the \obj{IO Port} capability. 
100Since invocations that
101read from I/O ports are required to return two values -- the value read
102and the error code -- a structure containing two members, \texttt{result}
103and \texttt{error}, is returned from these API calls.
104
105At system initialisation, the initial thread's \obj{CSpace} contains the
106\obj{IOPortControl} capability, which can be used to \apifunc{seL4\_X86\_IOPort\_Issue}{x86_ioport_issue}
107\obj{IO Port} capabilities to sub ranges of I/O ports. Any range that is issued
108may not have overlap with any existing issued \obj{IO Port} capability.
109
110\subsection{I/O Space}
111\label{sec:iospace}
112
113I/O devices capable of DMA present a security risk because the CPU's MMU
114is bypassed when the device accesses memory. In seL4, device drivers run
115in user space to keep them out of the trusted computing base.
116A malicious or buggy device driver may, however, program the device to
117access or corrupt memory that is not part of its address space, thus
118subverting security. To mitigate this threat, seL4 provides support for
119the IOMMU on Intel x86-based platforms. An IOMMU allows memory to be
120remapped from the device's point of view. It acts as an MMU for the
121device, restricting the regions of system memory that it can access.
122More information can be obtained from Intel's IOMMU documentation \cite{extra:vtd}.
123
124Two new objects are provided by the kernel to abstract the IOMMU:
125\begin{description}
126
127    \item[\obj{IOSpace}] This object represents the address space associated
128    with a hardware device on the PCI bus. It represents the right to
129    modify a device's memory mappings.
130
131    \item[\obj{IOPageTable}] This object represents a node in the multilevel
132    page-table structure used by IOMMU hardware to translate hardware
133    memory accesses.
134
135\end{description}
136
137\obj{Page} capabilities are used to represent the actual frames that are
138mapped into the I/O address space. A \obj{Page} can be mapped into
139either a \obj{VSpace} or an \obj{IOSpace} but never into both at the same time.
140
141\obj{IOSpace} and \obj{VSpace} fault handling differ significantly.
142\obj{VSpace} page faults are redirected to the thread's exception handler (see \autoref{sec:faults}), 
143which can take the
144appropriate action and restart the thread at the faulting instruction.
145There is no concept of an exception handler for an \obj{IOSpace}. Instead, faulting
146transactions are simply
147aborted; the device driver must correct the cause of the fault and retry
148the DMA transaction.
149
150An initial master \obj{IOSpace} capability is provided in the initial thread's
151CSpace. An \obj{IOSpace} capability for a specific device is created by
152using the \apifunc{seL4\_CNode\_Mint}{cnode_mint} method, passing the
153PCI identifier of the device as the low 16 bits of the \texttt{badge} argument, and
154a Domain ID as the high 16 bits of the \texttt{badge} argument.
155PCI identifiers are explained fully in the PCI specification 
156\cite{Shanley:PCISA}, but are briefly described here. A PCI identifier is
157a 16-bit quantity.  The first 8 bits identify the bus that the device is on.
158The next 5 bits are the device identifier: the number of the device on
159the bus. The last 3 bits are the function number. A single device may
160consist of several independent functions, each of which may be addressed
161by the PCI identifier.
162Domain IDs are explained fully in the Intel IOMMU documentation \cite{extra:vtd}.
163There is presently no way to query seL4 for how many Domain IDs are supported by
164the IOMMU and the \apifunc{seL4\_CNode\_Mint}{cnode_mint} method will fail if an
165unsupported value is chosen.
166
167The IOMMU page-table structure has three levels.
168Page tables are mapped into an \obj{IOSpace} using the \apifunc{seL4\_X86\_IOPageTable\_Map}{x86_io_page_table_map} method.
169This method takes the \obj{IOPageTable} to map, the \obj{IOSpace} to map into 
170and the address to map at. Three levels of page tables must be mapped before
171a frame can be mapped successfully. A frame is mapped with the
172\apifunc{seL4\_X86\_Page\_MapIO}{x86_page_map_io} method whose parameters are analogous to
173the corresponding method that maps \obj{Page}s into \obj{VSpaces} (see \autoref{ch:vspace}), 
174namely \apifunc{seL4\_X86\_Page\_Map}{x86_page_map}.
175
176Unmapping is accomplished with the usual unmap (see \autoref{ch:vspace}) API 
177call,
178\apifunc{seL4\_X86\_Page\_Unmap}{x86_page_unmap}.
179
180More information about seL4's IOMMU abstractions can be found in \cite{Palande:M}.
181\fi
182