Tech-note on how to write device drivers in BF.
[barrelfish] / doc / 019-device-drivers / DeviceDriver.tex
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 % Copyright (c) 2013, ETH Zurich.
3 % All rights reserved.
4 %
5 % This file is distributed under the terms in the attached LICENSE file.
6 % If you do not find this file, copies can be found by writing to:
7 % ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group.
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9
10 \documentclass[a4paper,11pt,twoside]{report}
11 \usepackage{bftn}
12 \usepackage{calc}
13 \usepackage{verbatim}
14 \usepackage{xspace}
15 \usepackage{pifont}
16 \usepackage{textcomp}
17 \usepackage{amsmath}
18 \usepackage{multirow}
19 \usepackage{listings}
20
21 \title{Device Drivers in Barrelfish}
22 \author{Barrelfish project}
23 % \date{\today}         % Uncomment (if needed) - date is automatic
24 \tnnumber{19}
25 \tnkey{Drivers}
26
27 \begin{document}
28 \maketitle                      % Uncomment for final draft
29
30 \begin{versionhistory}
31 \vhEntry{0.1}{05.12.2013}{GZ}{Initial Version}
32 \end{versionhistory}
33
34 % \intro{Abstract}              % Insert abstract here
35 % \intro{Acknowledgements}      % Uncomment (if needed) for acknowledgements
36 \tableofcontents                % Uncomment (if needed) for final draft
37 % \listoffigures                % Uncomment (if needed) for final draft
38 % \listoftables                 % Uncomment (if needed) for final draft
39 \cleardoublepage
40 \setcounter{secnumdepth}{2}
41
42 \newcommand{\fnname}[1]{\textit{\texttt{#1}}}%
43 \newcommand{\datatype}[1]{\textit{\texttt{#1}}}%
44 \newcommand{\varname}[1]{\texttt{#1}}%
45 \newcommand{\keywname}[1]{\textbf{\texttt{#1}}}%
46 \newcommand{\pathname}[1]{\texttt{#1}}%
47 \newcommand{\tabindent}{\hspace*{3ex}}%
48
49 \lstset{
50   language=C,
51   basicstyle=\ttfamily \small,
52   flexiblecolumns=false,
53   basewidth={0.5em,0.45em},
54   boxpos=t,
55   captionpos=b
56 }
57
58 \chapter{Introduction}
59 \label{chap:introduction}
60
61 This document describes the way we write device drivers in Barrelfish. It will
62 walk you through the necessary steps to integrate your driver in the
63 Barrelfish infrastructure and gives an overview of available APIs,
64 libraries and tools to help you with the process.
65
66 In the next chapter, we will give a short overview and walkthrough of an
67 existing driver in the Barrelfish code base, to introduce most of the common
68 terms and concepts. In the following chapters, we will then go deeper and look
69 into the hardware specific APIs available for all the different architectures
70 that Barrelfish supports.
71
72 Unfortunately, at this point, there is no unified interface for drivers on ARM
73 and x86. So, we will usually distinguish between these two architectures in
74 the document.
75
76 \chapter{High-level overview: A first look at device drivers in Barrelfish}
77 \label{chap:overview}
78
79 In a first step, we will look at the necessary bits and pieces to write a new
80 driver in Barrelfish on the ARM platform, by using an existing, very simple
81 driver as a walkthrough from the Barrelfish code base -- the FDIF driver, a
82 device used for face detection typically found on OMAP chips.
83
84 The relevant code for the driver resides in the tree at
85 \pathname{usr/drivers/omap44xx/fdif/}. In order to get an idea of what the
86 driver entails, we will look at its Hakefile. Hakefiles are the declarative
87 description of a how a program is built in Barrelfish and what its
88 dependencies are. If you need more informations on our build system, you
89 should have a look at the Hake technote~\cite{btn003-hake}, which provides a
90 detailed description of Hake, the Barrelfish build system. We will look at the
91 Hakefile for the FDIF driver in Listing~\ref{lst:hakefile} (a Haskell program,
92 really) and explain what it means for the driver program. \varname{cFiles} is
93 a list of C source files that are compiled and linked for this driver. In our
94 case, we use hake to just search for every file that has a "c" file extension
95 in the current directory and return this as a list of files for
96 \varname{cFiles}. If you go and look at \pathname{usr/drivers/omap44xx/fdif}
97 you will find that this will encompass only two files, \pathname{fdif.c} and
98 \pathname{picture.c}.
99
100 The next attribute, \varname{mackerelDevices}, contains a list Mackerl files,
101 these are devices that we have specified in our domain specific language
102 called Mackerel, and we would now like to use in our driver. If you do not
103 know what Mackerel is, let me explain it to you: Mackerel is a DSL for
104 describing device registers. You can find an abundance of Mackerel files in
105 the \pathname{devices} directory inside the source tree. For example, the
106 \keywname{omap44xx\_fdif} device mentioned in the Hakefile at the third
107 position is found in \pathname{devices/omap/omap44xx\_fdif.dev}. They all,
108 describe a particular device we use in Barrelfish to varying degrees of
109 detail, ranging from ethernet cards to xAPIC or even descriptions of the file-
110 allocation-table for the FAT file-system. Now, you might think, well, why
111 can't I just use a regular C struct or even integer types with bit operations
112 for that? And in general you could. However, the Mackerel compiler gives you a
113 lot of nice things on top of this description. For one thing, it will generate
114 for you all the code you need to program the register with certain values,
115 that means it takes care of all the bit-shifting and masking operations based
116 on your description. On the other hand, it will generate functions that let
117 you print the contents of the register in a human readable way, which is a
118 very useful thing for debugging. For more information on Mackerel you should
119 read the Mackerel Technote~\cite{btn002-mackerel}.
120
121 The \varname{addLibraries} entry specifies the libraries your application
122 needs in order to run. In this example, we add driverkit, a helper library for
123 finding, and mapping our device registers in the virtual memory space of the
124 application.
125
126 The last argument specifies the architectures we want to build this driver
127 for. Since we are currently using this device on ARM/OMAP4 platforms, this is
128 set to ARMv7 and ARMv7-M architectures.
129
130 \begin{lstlisting}[caption={A Hakefile for a simple device driver}, label={lst:hakefile}]
131 [   build application {
132         target = "fdif",
133         cFiles = (find withSuffices [".c"]),
134         mackerelDevices = [
135             "omap/omap44xx_cam_prm",
136             "omap/omap44xx_cam_cm2",
137             "omap/omap44xx_fdif",
138             "omap/omap44xx_device_prm" ],
139         addLibraries = ["driverkit"],
140         architectures = ["armv7", "armv7-m"]
141 }]
142 \end{lstlisting}
143
144 Now let's have a look at \pathname{usr/drivers/omap44xx/fdif/fdif.c}, the
145 device driver source code. If you open the file, aside from the comment
146 header, you will see a bunch of included header files that are of interest to
147 us (Listing~\ref{lst:mackerel}).
148
149 \begin{lstlisting}[caption={Mackerel includes in driver source code.}, label={lst:mackerel}]
150 #include <dev/omap/omap44xx_cam_prm_dev.h>
151 #include <dev/omap/omap44xx_cam_cm2_dev.h>
152 #include <dev/omap/omap44xx_fdif_dev.h>
153 \end{lstlisting}
154
155 These look very familiar to our specified \varname{mackerelDevices} in the
156 Hakefile, and in fact, they are the generated header files based on our
157 mackerel files. If you want to have a look at them, you can find these header
158 files in your build directory in \pathname{<arch>/include/dev/omap}. In our
159 code, we use various functions (the ones starting with \keywname{omap44xx\_})
160 that are defined in these header files and use them to access device
161 registers.
162
163 Another interesting part is early on in the main function (Listing~\ref{lst:mapping}).
164
165 \begin{lstlisting}[caption={Mapping device registers in virtual memory.}, label={lst:mapping}]
166 err = map_device_register(0x4A10A000, 4096, &vbase);
167 \end{lstlisting}
168
169 \fnname{map\_device\_register} is a function provided by the driverkit
170 library. We will talk more about it later, but for now, here is what it does:
171 It takes the physical address of a device register (\varname{0x4A10A000}) the
172 size of the register (\varname{4096}) and will map this at a random virtual
173 address in your address space (given back to you by \varname{vbase}). Since
174 our device drivers all run in user-space this function ensures that you can
175 access the device in your address space. There is also the issue of how, and
176 which programs we allow access to what device registers. We will discuss this
177 in the next chapter.
178
179 For the the FDIF device, we can receive an interrupt from the device in case
180 the face processing is done. Since we run in user space, we have to invoke a
181 system call to register for the interrupt in the kernel. Once the interrupt
182 arrives, the kernel will use the message passing infrastructure of Barrelfish
183 to forward the IRQ to us. Fortunately, libbarrelfish provides us with a high-
184 level interface to do just that. In the function \fnname{enable\_irq\_mode},
185 we register an interrupt for the device by using
186 \fnname{inthandler\_setup\_arm} (Listing~\ref{lst:irqregister}). It takes as
187 arguments a handler function (\fnname{irq\_handler}) that is executed in case
188 the interrupt arrives, an additional state argument that is passed to that
189 function for this particular interrupt, in our case NULL, and the interrupt
190 number or vector we are interested in.
191
192 \begin{lstlisting}[caption={Register to receive an Interrupt.}, label={lst:irqregister}]
193 err = inthandler_setup_arm(irq_handler, NULL, FDIF_IRQ);
194 \end{lstlisting}
195
196 This concludes our walkthrough on the FDIF driver. So far, you have seen a
197 glimpse of the user-level side on writing device drivers for ARM. It consists
198 of an interplay of the build system, mackerel device descriptions,  mapping
199 device registers, interrupt registrations and your actual driver code. In the
200 next chapters we will have a closer look on what is actually happening behind
201 the scenes and how to adapt the infrastructure for new architcures or boards.
202
203 Note that the FDIF driver is a very minimal example of a driver. We use it to
204 teach students about the basic concepts of device drivers. However, if you
205 would want to write a real driver, you also need to export a interface for
206 clients. In Barrelfish, the typical way is to export a message passing
207 interface for the driver, so that applications can connect and communicate
208 with the driver using messages. There are many source code examples in the
209 tree on how to do this, as a starting point, have a look at
210 \pathname{usr/examples/xmpl-call-response} in the source tree and the tech-
211 note on inter-dispatcher communication~\cite{btn011-idc} to get started.
212
213 \chapter{System Knowledge Base (SKB)}
214
215 Before we start looking at the internals of device management in Barrelfish,
216 we have to introduce the system knowledge base (SKB). The goal of the SKB
217 is to store all knowledge about a system and provide an interface for
218 clients to query and reason about this knowledge.
219
220 \section{x86, Octopus and the ECLiPSe Prolog engine}
221
222 On x86 architectures, the SKB is implemented using the ECLiPSe logic and
223 constraint programming (CLP) engine. The SKB was built as a part of Adrian
224 Sch\"upbach's Phd thesis \cite{}, available on \url{barrelfish.org}. In this
225 technote we briefly cover the main aspects. The SKB provides two different
226 interfaces to clients. One of them is a direct way to access the Prolog query
227 engine of the ECLiPSe runtime. This allows you to query for facts (i.e.,
228 knowledge) about the system in a very generic and flexible way. You can find
229 an API to access the SKB in \pathname{lib/skb}. The other interface is a key--value storage engine, called Octopus, implemented in combination with
230 the ECLiPSe engine. Octopus is used to provide various functionality in
231 Barrelfish. The key--value store also offers as a publish--subscribe mechanism
232 based for stored records. It allows subscribers to receive events in case
233 of state changes in the system. We use Octopus to implement various
234 functionality in the system such as a nameserver. The system also uses Octopus
235 for device related events, if PCI devices are found in the system or CPUs
236 are discovered for example. In most cases the device manager, which we will
237 introduce in the next chapter, will handle these events for you. However, some
238 subsystems such as USB, use Octopus directly to receive events about
239 hotplugged devices. You can find the API to interact with the Octopus service
240 in \pathname{lib/octopus/client}.
241
242 A documentation of the facts stored in the SKB is on the Barrelfish
243 Wiki at \url{http://wiki.barrelfish.org/}.
244
245
246 \section{ARM and the simple SKB}
247 \label{sec:simpleskb}
248
249 If you look in the source tree of the SKB (\pathname{usr/skb/}) you will find
250 that there are currently two different versions of the SKB built. One is the
251 SKB based on the ECLiPSe runtime engine for x86 systems, the other is the SKB
252 simple for ARM. This is due to portability issues of the ECLiPSe runtime for
253 ARM. So, what is the simple SKB? It is an implementation of the Octopus API.
254 It is important to have at least a minimal a implementation of Octopus for all
255 architectures we run on. Because it provides essential system features such as
256 the name-service which is used most for of the service look-ups.
257
258 Not having the constraint logic programming interface unfortunately means we
259 can currently not use the APIs in \pathname{lib/skb} on ARM. We are currently
260 investigating alternatives for a constraint solver that will run on both
261 platforms.
262
263 \chapter{Kaluga -- The device manager}
264
265
266 Kaluga is the device manager in Barrelfish. Its responsibility is to manage
267 the periperhals of a system. That encompasses starting the correct drivers,
268 once a device is discovered, in the right order and making sure that each driver
269 has the permissions (capabilities) to access the device' memory areas
270 or I/O ports. In this chapter wewill learn how Kaluga interacts with the
271 rest of the system for device discovery and driver start-up.
272
273 For reasons stated in Section~\ref{sec:simpleskb} we currently do not have the
274 full system knowledge base on non-x86 platforms. Also, the ARM platforms we
275 support right now, do not have an infrastructure like PCI that brings
276 automatic device discovery -- there are device trees, but we do not
277 have support for them yet.
278
279 This means that right now, the way Kaluga finds the available devices differs
280 quite a bit based on the platform we are running on. This ranges from
281 automatic discovery using PCI, Octopus and the SKB on x86, to hardcoded
282 information in Kaluga for the OMAP4 SoC. However, the general way of
283 discovering what drivers are available and how we start them remains the same.
284 We will briefly look at what operations Kaluga provides for finding binaries
285 and how you can program it to start drivers the right way in your system.
286
287 If you look inside of the main function in Kaluga, you can see a call to the
288 \fnname{init\_boot\_modules} function. We usually rely on multiboot to provide
289 us with a set of ELF files at start-up. The \fnname{init\_boot\_modules}
290 function parses the information provided by multiboot (your menu.lst file)  to
291 find a list of available binaries. It then looks at the arguments that are
292 hardcoded next to those binaries and follows a simple policy for these, if a
293 binary has the argument `'auto`' next to it, it considers this binary as a
294 driver and will start it, if it finds a suitable device. How Kaluga finds a
295 suitable device is explained in the following sections. Drivers are started in
296 different ways, ranging from just starting one driver binary to a number of
297 binaries or sending notifications to other subsystems and starting a driver.
298 Kaluga supports custom start-up policies for different binaries in your
299 system, you can set a start-up policy per driver binary using the
300 \fnname{set\_start\_function}. The default start function, the one that is
301 chosen if no special start-up function, is set for a binary, is defined in
302 \pathname{usr/kaluga/driver\_startup.c}. For example, on x86, this function
303 will just spawn the binary and provide as arguments the PCI device identifiers
304 (bus, class, function etc.) to the driver program.
305
306 As we mentioned before, a driver usually needs a special set of permissions to
307 gain access to the device registers. For historical reasons, the way we
308 provide this permissions currently differs between x86 and ARM. Unifying this
309 interface is part of future work.
310
311 \section{Starting PCI drivers on x86}
312 \label{sec:pcidriverstart}
313
314 On x86, peripherals are usually in the form of PCI or PCI express cards. PCI
315 supports automatic discovery of periperhals using PCI bus enumeration. In
316 Barrelfish, the PCI related code lives in \pathname{usr/pci}. PCI is
317 structured as a hierarchical tree with it's leaves being devices. The root
318 node, called PCI root bridge, forms the entry point to such a tree. PCI root
319 bridges are found by reading the ACPI tables. ACPI, short for Advanced
320 Configuration and Power Interface, is an open standard for device
321 configuration and power management in operating systems. ACPI related code in
322 Barrelfish lives in \pathname{usr/acpi}.
323
324 The bootstrapping of an x86 machine in Barrelfish works as follows: After
325 parsing the boot script, Kaluga starts ACPI. ACPI will then add specific
326 Octopus records for every PCI root bridge it finds. Meanwhile, Kaluga will
327 receive notification for all the root bridges added to Octopus. If a root
328 bridge is found, Kaluga will start the PCI domain which in turn will do a PCI
329 bus enumeration. Devices found during PCI bus enumeration are again added to
330 Octopus and propagated to Kaluga which will start individual device drivers to
331 handle the peripherals. How does Kaluga know what driver to start for each
332 device record? We already discussed how Kaluga uses different start functions
333 for different types of devices. But how do we choose the right binary? Kaluga
334 uses the SKB that stores a mapping from PCI identifiers to driver binaries. This
335 mapping is retrieved from the SKB once Kaluga receives a Octopus record for a
336 new device. You will find the mapping database in
337 \pathname{usr/skb/programs/device\_db.pl}. If you want to start your PCI driver
338 with Kaluga, you will need to add it there and provide at least the
339 corresponding device and vendor id.
340
341 Barrelfish has a number of drivers for PCI cards. Mostly for network
342 interfaces. Barrelfish drivers, including the ones for PCI, are located in the
343 source tree in \pathname{usr/drivers/}.
344
345 \section{Writing PCI drivers}
346 \label{sec:pcidriverwriting}
347
348 In order to write a PCI driver, one has to communicate with the PCI domain.
349 There is a client library that provides a helpful API in \pathname{lib/pci} that
350 helps doing that. One of the first steps is to initialize the client library
351 by connecting to the PCI domain:
352
353 \begin{lstlisting}[caption={A client connects to the PCI subsystem.}, label={lst:pciconenct}]
354 err = pci_client_connect();
355 \end{lstlisting}
356
357 After that, you are able to invoke the library functions in
358 Listing~\ref{lst:pciapi} to initialize devices. The functions allow to gain
359 control for a specific PCI device. The device is identified by using the
360 numerous PCI identifiers (subclass, prog\_if, vendor et. al.). The caller
361 provides a callback function (\fnname{init\_func}) that gets called by the
362 library once it has registered the device with the PCI domain.
363 \fnname{init\_func} takes as an argument an array of \keywname{struct
364 device\_mem}. A description of the basic address registers (BAR) for this PCI
365 device and also permissions (capabilities) to map these address registers in
366 the drivers address space. You can use the defined in helper functions in
367 \pathname{include/pci/mem.h} to map these BARs into the address space of the
368 client. For legacy devices (such as a serial driver for example) that live in
369 the I/O address space and do not use memory mapped registers you can use the
370 \fnname{pci\_register\_legacy\_driver\_irq} function.
371
372
373 \begin{lstlisting}[caption={A driver uses one of the following functions to register for PCI devices.}, label={lst:pciapi}]
374 errval_t pci_register_driver_noirq(pci_driver_init_fn init_func, uint32_t class,
375                                    uint32_t subclass, uint32_t prog_if,
376                                    uint32_t vendor, uint32_t device,
377                                    uint32_t bus, uint32_t dev, uint32_t fun);
378
379 errval_t pci_register_driver_irq(pci_driver_init_fn init_func, uint32_t class,
380                                  uint32_t subclass, uint32_t prog_if,
381                                  uint32_t vendor, uint32_t device,
382                                  uint32_t bus, uint32_t dev, uint32_t fun,
383                                  interrupt_handler_fn handler, void *handler_arg);
384
385 errval_t pci_register_legacy_driver_irq(legacy_driver_init_fn init_func,
386                                         uint16_t iomin, uint16_t iomax, int irq,
387                                         interrupt_handler_fn handler,
388                                         void *handler_arg);
389 \end{lstlisting}
390
391 Note that the discussed PCI API is rather low-level and provides a lot of
392 freedom in who can register for PCI devices. In the future the plan is for x86
393 to push more of that complexity in Kaluga. The device registration with PCI
394 should be done by Kaluga before the driver is started, the driver then only
395 receives a list of capabilities for a particular device which it can map in
396 its address space. That means a driver no longer has the need to call these
397 functions.
398
399 \section{Writing drivers for ARM and System-on-Chip platforms}
400 \label{sec:armdriverwriting}
401
402 You have already encountered most of the provided functionality for ARM
403 drivers in the overview in Chapter~\ref{chap:overview}. This section
404 will focus on how we currently support the OMAP platform to start
405 drivers in Kaluga.
406
407 On ARM the situation differs compared to x86. There is currently no
408 established standard like PCI for x86. That means that the way we have to
409 integrate ARM differs from platform to platform. We also have no support for
410 device trees at the moment. Therefore, if you look at the \fnname{main}
411 function in Kaluga, you will find that we currently look-up the binaries using
412 the \fnname{find\_module} function and hardwire the start-up of these drivers
413 for the pandaboard platform. In \pathname{omap\_startup.c} we define the start
414 function for these binaries. If you look at the code in the file you'll also
415 see that we use the function \fnname{spawn\_program\_with\_caps} to start the
416 driver and pass the driver a list of memory capabilities to access the device
417 memory. This is the service part of the driverkit library we have seen in
418 Chapter~\ref{chap:overview}, it makes sure the capabilities are actually given
419 to the driver in a way that driverkit can map them. What capabilities we give
420 to a driver for the OMAP chip is also hardcoded at the moment, you can find a
421 series of \varname{struct allowed\_registers} in the same file that defines for a
422 given driver, what memory ranges it is allowed to access. The situation is not
423 solved sufficiently right now, in the future, we would like to store this
424 information in a SKB like system that also runs on ARM and lets us query for
425 information about various platforms.
426
427 If you go on and read the capability technote \cite{btn013-capabilities}
428 you'll learn that capabilities can only be created in the kernel, and the
429 representation we have in user-space, are references to capabilities. So, a
430 valid question here is how Kaluga gets the capabilities for these devices in
431 the first place. For that we have to look at the \fnname{device\_caps.c} file
432 inside Kaluga. The file contains the capability manager or memory manager for
433 Kaluga, it is an instance of the memory management library found in
434 \pathname{lib/mm}. The memory manager (\keywname{libmm}) manages capabilities
435 for you, in reality it is a B+-tree structure that will manage a certain range
436 of memory, in our case device memory. It allows you to request a smaller range
437 from this usually very large range that we initalize our memory manager with
438 and, \keywname{libmm} will split up the inital capability we gave to the
439 instance at the beginning into smaller pieces and hand them out to you, giving
440 you a way to have fine grained, page level access control on memory. In
441 practice, because capabilities can only be created and split in half in the
442 kernel, it has to invoke system calls to do that.
443
444 As a note aside, there are three important memory managers in the system. The
445 one found in memserv (\pathname{usr/memserv}), it manages all physical memory,
446 the one in ACPI (\pathname{usr/acpi}), it handles all device memory on x86 and
447 should really be merged with the third one in Kaluga that we use for ARM.
448
449 If you look at the function \fnname{init\_cap\_manager} in \pathname{usr/kaluga/device\_caps.c}
450 you will find a call to the monitor to request the I/O capability:
451
452 \begin{lstlisting}[caption={RPC call to receive the I/O capability from
453 the monitor.}, label={lst:getio}]
454 err = cl->vtbl.get_io_cap(cl, &requested_cap, &error_code);
455 \end{lstlisting}
456
457 In the case of the ARM Pandaboard, the requested capability allows one to
458 access the whole space of the device memory. We pass this capability on to the
459 device manager in the \fnname{mm\_add} call further down. Now, we are free to
460 use the \fnname{get\_device\_cap} function, also defined in this file to
461 create fine grained capabilities for this entire memory range. If you go back
462 and look at code in \pathname{usr/kaluga/omap\_startup.c} you will find it
463 actually uses \fnname{get\_device\_cap} to create the capabilities it needs to
464 pass on to the device drivers.
465
466 Now you should understand how the user-space side works if you want to write
467 user-space drivers for your own platform. We have not covered yet how we
468 actually create a capability in the kernel and how it ends up in the monitor,
469 but we will cover that shortly in Section~\ref{sec:kernelmemory}.
470
471 \chapter{Kernel support for user-space drivers}
472 \label{chap:kernel}
473
474 In this chapter, we will look at the necessary support in the kernel, if we
475 want to write user-level device drivers on a new, unsupported platform. We
476 cover the main parts that are needed in this case: How do we forward
477 interrupts to user-space and how we create capabilities for device memory.
478
479 \section{Interrupts}
480 \label{sec:kernelirq}
481
482 In Chapter~\ref{chap:overview} we have already seen how we can register to
483 receive interrupts using the message passing architecture in Barrelfish. In
484 this section we will look at what the kernel does in order to forward the
485 interrupt to you. It all starts with having a driver for your interrupt
486 controller. We have support for a number of interrupt controllers already in
487 Barrelfish, like the xAPIC on x86 (\pathname{kernel/x86/apic.c}) or the GIC in
488 ARMv7 (\pathname{kernel/arch/armv7/gic.c}). If there is currently no interrupt
489 controller for your architecture, you'll have to write one yourself. In any
490 case, if you want to forward interrupts to user-space, you can rely on the
491 \fnname{send\_user\_interrupt} function provided by the architecture
492 independent part of the CPU driver. It allows you to forward interrupts
493 from the kernel to a domain running on its core using the message passing
494 infrastructure of Barrelfish \cite{btn011-idc}.
495
496
497 \section{Device Memory}
498 \label{sec:kernelmemory}
499
500 In Section~\ref{sec:armdriverwriting} we talked about how Kaluga constructs a
501 series of smaller capabilities for device drivers from an initial, huge
502 capability it receives from the monitor. We also mention that capabilities are
503 created in the kernel. In this Section we look at what is necessary to
504 create capabilities for device memory and how we can pass it on to user-space.
505
506 First you need to know what memory areas your devices are in. On x86 we
507 usually ask the BIOS to get a list of memory regions for RAM and device
508 memory. In Barrelfish, we construct capabilities for these regions and we hand
509 the device regions to ACPI which is the domain that initializes the ACPI
510 subsystem and does the memory book keeping for PCI drivers. On an ARM
511 platform, the device memory usually lives in a statically pre-defined range.
512 In \pathname{kernel/arch/omap44xx/startup\_arch.c} in
513 \fnname{spawn\_init\_common} we can see how we construct a capability for the
514 device memory range of the the OMAP4 platform. The relevant parts are
515 given in Listing~\ref{lst:capcreate}.
516
517 \begin{lstlisting}[caption={Creating a cabaility in the kernel and placing
518 it in the I/O slot in a task cnode.}, label={lst:capcreate}]
519 struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO);
520 errval_t  err = caps_create_new(ObjType_DevFrame, 0x40000000, 30, 30, iocap);
521 \end{lstlisting}
522
523 \fnname{spawn\_init\_common} is setting up a new dispatcher control block, for
524 the first user-space program called init, in the system. Similar to a UNIX
525 based OS, all subsequent programs are children of init. The call to
526 \fnname{caps\_create\_new} creates a new capability of type
527 \varname{ObjType\_DevFrame}, a special type for device memory that makes sure
528 the pages are not zeroed before mapping it for the first time. The next two
529 arguments are the physical base of the address range and the size (in bits) of
530 the range. This particular capability covers a memory range of $2^{30}$ bytes,
531 or one GiB, starting from address \varname{0x40000000} -- the device memory
532 region of the OMAP4 chip. The last argument specifies where this new
533 capability is stored. The location is defined by the preceding
534 \fnname{caps\_locate\_slot} function call. You can think of the
535 \fnname{caps\_locate\_slot} function as an array look-up. We use the task
536 CNode (a table of capabilities) of \varname{spawn\_state}, a struct
537 representing the kernel state for the init domain. We use
538 \varname{TASKCN\_SLOT\_IO}  as an index to the cnode table. Once init is
539 started, it can refers to this capability by using the \varname{TASKCN\_SLOT\_IO}
540 offset to find it. If you look inside \pathname{usr/init/spawn.c} you will
541 find the code (Listing~\ref{lst:slotio}) doing just that to propagate the capability on to the monitors task cnode. Notice that \fnname{cap\_copy} is
542 now a system call. The monitor then can use the I/O capability in
543 his task cnode if somebody requests it (for example by using \fnname{get\_io\_cap},
544 seen in Listing~\ref{lst:getio}).
545
546 \begin{lstlisting}[caption={Copy of the I/O capability from
547     \varname{src} to \varname{dest}.}, label={lst:slotio}]
548 /* Give monitor IO */
549 dest.cnode = si->taskcn;
550 dest.slot  = TASKCN_SLOT_IO;
551 src.cnode = cnode_task;
552 src.slot  = TASKCN_SLOT_IO;
553 err = cap_copy(dest, src);
554 if (err_is_fail(err)) {
555     return err_push(err, INIT_ERR_COPY_IO_CAP);
556 }
557 \end{lstlisting}
558
559 \chapter{Integrating your NIC driver with the Barrelfish network stack}
560 \label{chap:network}
561
562 TODO pravin?
563
564
565 \chapter{Limitations \& Work in Progress}
566
567 Altough we currently have the necessary support for user-space drivers
568 on both major platforms Barrelfish runs on we do not yet have an
569 unified interface between ARM and x86 architectures. In this technote
570 we have seen both approaches explained to varying levels of details and
571 we mentioned briefly where the two approaches differ. In the future we will
572 most likely unify both platforms under a standardized API which will have
573 the best of both worlds.
574
575 \end{document}