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