Squashed changes of e89aa91..6ca6bdf (master as of 2016-04-18).
authorSimon Gerber <simon.gerber@inf.ethz.ch>
Mon, 18 Apr 2016 08:41:26 +0000 (10:41 +0200)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Mon, 18 Apr 2016 08:41:26 +0000 (10:41 +0200)
Take this commit out when merging

Signed-off-by: Simon Gerber <simon.gerber@inf.ethz.ch>

80 files changed:
capabilities/caps.hl
doc/022-armv8/Hakefile [new file with mode: 0644]
doc/022-armv8/report.tex [new file with mode: 0644]
doc/Hakefile
doc/style/barrelfish.bib
doc/style/defs.bib
errors/errno.fugu
hake/ArchDefaults.hs
hake/Config.hs.template
hake/HakeTypes.hs
hake/Main.hs
hake/RuleDefs.hs
hake/hake.sh
hake/symbolic_targets.mk
if/monitor_blocking.if
if/pci.if
include/arch/aarch64/barrelfish/invocations_arch.h
include/arch/arm/barrelfish/invocations_arch.h
include/arch/x86_32/barrelfish/invocations_arch.h
include/arch/x86_64/barrelfish/invocations_arch.h
include/barrelfish/inthandler.h
include/barrelfish/sys_debug.h
include/barrelfish_kpi/capabilities.h
include/barrelfish_kpi/distcaps.h
include/barrelfish_kpi/sys_debug.h
include/barrelfish_kpi/types.h
include/pci/pci_client_debug.h [new file with mode: 0644]
kernel/arch/arm/syscall.c
kernel/arch/armv7-m/paging.c
kernel/arch/x86_32/irq.c
kernel/arch/x86_32/syscall.c
kernel/arch/x86_64/irq.c
kernel/arch/x86_64/syscall.c
kernel/capabilities.c
kernel/include/arch/armv7-m/offsets.h
kernel/include/arch/armv8/irq.h
kernel/include/arch/x86_32/irq.h
kernel/include/arch/x86_64/irq.h
kernel/include/kcb.h
lib/barrelfish/arch/x86/sys_debug.c
lib/barrelfish/debug.c
lib/barrelfish/inthandler.c
lib/bulk_transfer/backends/net/e10k_queue.h
lib/compiler-rt/Hakefile [deleted file]
lib/compiler-rt/lib/builtins/Hakefile [new file with mode: 0644]
lib/compiler-rt/test/builtins/Unit/Hakefile [new file with mode: 0644]
lib/gmp/Hakefile
lib/linenoise/linenoise.c
lib/pci/Hakefile
lib/pci/mem.c
lib/pci/pci_client.c
lib/posixcompat/Hakefile
lib/thc/thcsync.c
lib/virtio/virtqueue.c
lib/virtio/virtqueue_host.c
tools/harness/builds.py
tools/harness/harness.py
tools/harness/machines/eth_machinedata.py
tools/harness/results.py
tools/harness/scalebench.py
tools/harness/tests/compiler-rt_builtins.py
tools/run-pdflatex.sh
usr/acpi/acpi.c
usr/acpi/acpica_osglue.c
usr/ahcid/ahcid.c
usr/drivers/e10k/e10k_queue.h
usr/drivers/lpc_timer/main.c
usr/drivers/serial/main.c
usr/drivers/solarflair/sfxge/common/efx_mac.c
usr/drivers/usb/usb_keyboard/usb_keyboard_driver.h
usr/drivers/usb/usb_manager/include/usb_memory.h
usr/drivers/xeon_phi/domain.c
usr/eclipseclp/sizes.h
usr/monitor/include/arch/x86_32/monitor_invocations_arch.h
usr/monitor/monitor_rpc_server.c
usr/pci/pci.c
usr/pci/pci.h
usr/pci/pci_msix.c
usr/pci/pci_service.c
usr/skb/octopus/skb_query.c

index 8082af0..48acfec 100644 (file)
@@ -386,6 +386,17 @@ cap IRQTable is_always_copy {
     **/
 };
 
+cap IRQDest {
+    eq uint64 controller;
+    eq uint64 vector;
+};
+
+cap IRQSrc {
+       /* IRQ capability. Represents an interrupt vector at an interrupt controller. */
+       eq uint64 vector;
+       eq uint64 controller;
+};
+
 cap IO {
     /* Legacy IO capability */
     eq uint16 start;
diff --git a/doc/022-armv8/Hakefile b/doc/022-armv8/Hakefile
new file mode 100644 (file)
index 0000000..f660204
--- /dev/null
@@ -0,0 +1,16 @@
+----------------------------------------------------------------------
+-- Copyright (c) 2013, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for /doc/017-ARM
+--
+----------------------------------------------------------------------
+
+[ buildTechNote "report.tex" "TN-022-ARMv8.pdf" True False
+                    [  
+                    ]
+]
diff --git a/doc/022-armv8/report.tex b/doc/022-armv8/report.tex
new file mode 100644 (file)
index 0000000..1d17518
--- /dev/null
@@ -0,0 +1,921 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Copyright (c) 2013, ETH Zurich.
+% All rights reserved.
+%
+% This file is distributed under the terms in the attached LICENSE file.
+% If you do not find this file, copies can be found by writing to:
+% ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\documentclass[a4paper,twoside]{report}
+
+\usepackage{bftn}
+\usepackage{booktabs}
+\usepackage{hyperref}
+\usepackage{hyphenat}
+\usepackage{listings}
+\usepackage{makeidx}
+\usepackage{natbib}
+
+\def\chapterautorefname{Chapter}
+\def\sectionautorefname{Section}
+\def\subsectionautorefname{Section}
+\def\subsubsectionautorefname{Section}
+\def\tableautorefname{Table}
+
+\lstdefinelanguage{armasm}{
+    numbers=left,
+    numberstyle=\tiny,
+    numbersep=5pt,
+    basicstyle=\ttfamily\small
+}
+\lstset{language=armasm}
+
+\title{Barrelfish on ARMv8}
+\author{David Cock}
+
+\tnnumber{022}  % give the number of the tech report
+\tnkey{ARMv8} % Short title, will appear in footer
+
+\begin{document}
+\maketitle
+
+\begin{versionhistory}
+\vhEntry{1.0}{11.04.2016}{DC}{Initial version}
+\end{versionhistory}
+
+\chapter{Summary}
+
+Barrelfish now supports ARMv7 and ARMv8 as primary platforms, and we have
+discontinued support for all older architecture revisions (ARMv5, ARMv6). The
+current Barrelfish release contains a port to a simulated ARMv8 environment,
+derived from the existing ARMv7 codebase and running under GEM5, with generous
+contributions from HP Research.
+
+Simultaneously, we are undertaking a clean-slate redesign of the CPU driver
+for ARMv8, as it presents a number of novel features, and greatly improved
+platform standardisation (\autoref{s:sbsa}), that should allow for a much
+cleaner and simpler implementation. This redesigned CPU driver will for the
+basis for ongoing research into large-scale non-cache-coherent systems using
+ARMv8 cores. This document presents the new CPU driver design
+(\autoref{c:design}), briefly covering those features of ARMv8 of greatest
+relevance (\autoref{c:background}), and discusses a number of technical
+challenges presented by the new architecture (\autoref{c:tech}).
+
+\chapter{Background}\label{c:background}
+
+The Barrelfish research operating system is a vehicle for research into
+software support for likely future architectures, where large numbers of
+non-coherent (or weakly-coherent) heterogeneous processor cores are assembled
+into a single large-scale system. As such, support for a common non-x86
+architecture has always been part of the project, beginning with the ARMv5
+(XScale) port, which permitted the embedded processor on a network interface
+card to be integrated as a first-class part of the system, with its own CPU
+driver. We have also actively maintained an ARMv7 port, to the OMAP4460
+processor on the Pandaboard ES, which we use as a teaching platform in the
+Advanced Operating Systems course at ETH Z\"urich. These ports are described
+more fully in the accompanying technical report, \citet{btn017-arm}.
+
+\section{The ARMv8 Architecture}
+
+The ARMv8 architecture is quite a radical departure from previous versions,
+and represents the culmination of a trend that has been developing for quite
+some time. While the first wave of ARM-based microservers, based on the 32-bit
+ARMv7 architecture, was largely a commercial failure, it's clear that ARM is
+now actively targeting the server market, where Intel currently has near-total
+dominance.
+
+ARMv8 discards some long-standing features of the ARM instruction set:
+universal conditional execution, multiple loads/stores, and the program
+counter as a general-purpose register. These most likely caused difficulty in
+scaling the processor pipeline to high clock rates, and we present some
+consequences of their loss in \autoref{s:threads} and \autoref{s:traps}. The
+instruction-set changes, however challenging to the systems programmer, are
+ultimately of little consequence compared to the consolidation of the ARM
+ecosystem into a serious server platform. The two features of most interest at
+this stage in the design process are the standardisation of hardware features
+and memory maps, and of the boot process.
+
+\subsection{ARM Server Base System Architecture}\label{s:sbsa}
+
+ARM has long been criticised by systems programmers for its highly fragmented,
+and non-uniform programming interface. Linux, in particular, has struggled for
+years with supporting the great multiplicity of ARM platforms.  The principal
+reason for this is the lack of any concept of a \emph{platform}: a set of
+assumptions (available hardware, memory map, etc.), that programmers can rely
+on when initialising and managing a system. The Linux source tree famously
+contained a vastly greater amount of code in the ARM platform support
+subtrees, than that for x86.
+
+The relative standardisation of the x86 platform is largely a historical
+accident, due to the rapid proliferation of PC/AT clones in the early 1980s.
+The x86 platform thus contains layers of ossified legacy interfaces, necessary
+to ensure broad cross and backward compatibility.  ARM's business model, on
+the contrary, has long emphasised the specialisation of implementations: an
+ARM licensee would take their ARM-designed CPU core, and integrate it
+themselves in to a complex SoC (system on a chip), with their own specialised,
+proprietary interfaces. The upsides of this were the possibility to highly
+optimise a particular design, and no requirement on ARM itself to maintain a
+coherent platform.
+
+While ARM's customisable platform worked well for embedded devices, and scaled
+reasonably well to relatively powerful smartphones, it's a disaster for
+producing high-quality systems software, able to execute on a broad range of
+hardware from competing vendors: exactly what a competitive server platform
+requires. ARM clearly know this, and since 2014 have published the Server Base
+System Architecture \citep{arm:sbsa}. To the extent that manufacturers adhere
+to these guidelines, our job as systems programmers is significantly simpler:
+it should be possible to write a single set of initialisation and
+configuration code for ARMv8, that will run on any SBSA-compliant system, much
+as we already do for x86-64.
+
+\begin{table}
+\begin{center}
+\begin{tabular}{lllp{6cm}}
+\toprule
+Supplier & Processor & Name & \\
+\midrule
+APM & APM883208 & Mustang  & 1P 8-core X-Gene 1 with serial trace. \\
+\addlinespace[2pt]
+    & APM883408-X2 & X-C2  & 1P 8-core X-Gene 2. \\
+\addlinespace[2pt]
+Cavium & CN8890 & StratusX & 1P 48-core ThunderX. \\
+\addlinespace[2pt]
+       &        & Cirrus   & 2P 48-core ThunderX. \\
+\addlinespace[2pt]
+ARM & AEM & Fixed Virtual Platform & The \emph{architectural envelope model}
+covers the range of behaviour permitted by ARMv8. Bare-metal debug. \\
+\addlinespace[2pt]
+    &     & Foundation Platform & Freely available, compatible with FVP. \\
+\bottomrule
+\end{tabular}
+\end{center}
+\caption{ARMv8 platforms of interest}\label{t:platforms}
+\end{table}
+
+Our target platforms listed in \autoref{t:platforms} all support SBSA to some
+extent, and absent any compelling reason, we will only support SBSA-compliant
+platforms.
+
+\subsection{UEFI}\label{s:uefi}
+
+One aspect of the SBSA which eases portability is the specification, for the
+first time, of a boot process for ARM systems. ARM has specified that SBSA
+systems must support UEFI \citep{uefi} (the unified extensible firmware
+interface). UEFI is a descendant of the EFI specification, developed by Intel
+for the Itanium project. While Itanium is no longer a platform of any great
+commercial interest, UEFI support is now widespread in the x86-64 market.
+UEFI, in turn, specifies the use of ACPI \citep{acpi} (the advanced
+configuration and power interface) for platform discovery and control.
+
+Supporting ACPI and UEFI requires a one-off investment of effort to design a
+new boot and configuration subsystem, but should pay off in the long term, as
+ports to new ARM boards will no longer require extensive manual configuration.
+The code should also be largely reusable for x86 UEFI systems. Our new UEFI
+bootloader is described in \autoref{s:hagfish}.
+
+\section{A Direct Port from ARMv7}
+
+As already described, the Barrelfish release current at time of writing
+includes an initial ARMv8 port to the GEM5 simulator. This port contains code
+generously contributed by HP Research.
+
+Being developed from the existing codebase, this ARMv8 port follows the
+structure of the existing ARMv7 code closely. While it is highly useful to
+have a running port, we are nevertheless continuing with a significant
+redesign of the CPU driver, as significant improvements and simplifications
+will be possible, once we no longer need to follow the existing structure,
+originally developed for a significantly different platform.
+
+The GEM5 simulator's model of an ARMv8 platform is relatively primitive, and
+does not conform to modern platform conventions, for example placing RAM at
+address \texttt{0}, rather than \texttt{0x80000000} as mandated by the SBSA.
+For this reason, in addition to better integration with ARM debugging tools,
+we have switched to the ARM Fixed Virtual Platform as our default simulation
+environment, with the Foundation Platform supported as a freely available
+simulator.
+
+\chapter{Design and Implementation}\label{c:design}
+
+\section{Redesigning the CPU Driver}
+
+Given that ARMv8 is a significantly different platform to ARMv7, and that the
+ARMv7 codebase carries a significant legacy, reaching right back to ARMv5, we
+are pursuing substantial redesign of the CPU driver. Taking advantage of the
+standardisation of the hardware platform mandated by the SBSA
+(\autoref{s:sbsa}), and the facilities provided by UEFI (\autoref{s:uefi}), in
+addition to a relatively unrestricted virtual address space, we are able to
+significantly reduce the complexity of the CPU driver.  In this section we
+describe the updated design, and our progress on its implementation, while the
+UEFI interface (Hagfish) is described separately, in \autoref{s:hagfish}.
+
+\paragraph{Terminology}
+In the interest of clarity, in the discussion that follows, we use a few terms
+with precise intent:
+\begin{description}
+\item[shall]
+    indicates features or characteristics of the design to which the
+    Barrelfish implementation must conform.
+\item[should]
+    indicates features which should be supported if at all possible.
+\item[initially]
+    indicates features which will be provided from the outset in the
+    Barrelfish implementation.
+\item[eventually]
+    indicates features which will be provided later in the Barrelfish
+    implementation, and which the initial design will aim to facilitate.
+\end{description}
+
+\subsection{Goals}
+
+Our goal is to provide a reference design for the CPU driver and user-space
+execution environment for Barrelfish on an ARMv8 core, in order to understand
+both positive and negative implications of the architecture for a multikernel
+system.  The design \textbf{should} be applicable to any ARMv8 with
+virtualisation (\texttt{EL2}) support.
+
+\textbf{Initially}, our hardware development platform is the APM X-Gene 1,
+using the Mustang Development Board. We are using the Mustang principally as
+it was relatively easily available, as well as being a comparatively complex
+and powerful CPU. The ThunderX platform from Cavium is very interesting for
+Barrelfish, as it ties a large number (48) of less-powerful (2-issue) cores.
+We do not have the resources to develop for two platforms simultaneously, but
+we hope to \textbf{eventually} add support for the ThunderX.
+
+Our target simulation environment is the ARM Fixed Virtual Platform, and the
+Foundation Platform. These models are supplied by ARM. The Foundation Platform
+is freely available, and will be the default supported simulation platform for
+the public Barrelfish tree, while we will use the FVP internally to allow
+bare-metal debugging. Future support for QEmu is desirable, to the extent that
+it models a compatible system --- GEM5, which the ARMv7 port targets,
+currently does not.
+
+\textbf{Initially}, the design will support running both the CPU driver and
+user-space processes in AArch64 mode without support for virtualisation.
+\textbf{Eventually} the design will support running the CPU driver in AArch64
+mode, and user-space processes in both AArch64 and AArch32 modes without
+virtualisation, and virtual machines in AArch64 mode. We will only support
+virtualisation on ARMv8.1 or later platforms, that support the VHE extensions,
+as described in \autoref{s:layout}.
+
+\subsection{Processor Modes and Virtualisation}
+
+Where possible, we will keep the virtualisation model similar to that on
+Barrelfish/x86. In particular, it \textbf{should} be possible to implement
+native applications, fully virtualised (e.g. Linux) VMs, and VM-level
+applications e.g. Arrakis \citep{peter:osdi14}.
+
+ARMv8 has a somewhat different virtualisation model to x86, and different
+again from the ARMv7 virtualisation extensions. Rather than having exception
+levels (rings) duplicated between guest and host, ARMv8 provides 4 exception
+levels (ELs):
+
+\begin{itemize}
+\item \texttt{EL0} is unprivileged --- user applications.
+\item \texttt{EL1} is privileged --- OS kernel.
+\item \texttt{EL2} is hypervisor state.
+\item \texttt{EL3} is for switching between secure and non-secure (TrustZone)
+                   modes. The X-Gene 1 does not implement \texttt{EL3}, and it
+                   is currently not of interest for Barrelfish.
+\end{itemize}
+
+Explicit traps (syscalls/hypercalls) target only the next level up:
+\texttt{EL0} can call \texttt{EL1} using \texttt{svc} (syscall), and
+\texttt{EL1} can call \texttt{EL2} using \texttt{hvc} (hypercall), but
+\texttt{EL0} cannot directly call \texttt{EL2}, unless \texttt{EL1} is
+completely disabled.  Exceptions return to the caller's exception level.
+
+ELs \textbf{shall} be distributed as follows: The CPU driver \textbf{shall}
+exist at both \texttt{EL1} and \texttt{EL2}, and take both syscalls
+(\texttt{svc}, from \texttt{EL0} applications) and hypercalls (\texttt{hvc},
+from \texttt{EL1} applications). The system \textbf{shall} support
+applications both at \texttt{EL0}, and at \texttt{EL1} (e.g.  Arrakis, VMs).
+Most code paths \textbf{should} be identical, as most CPU driver operations do
+not depend on \texttt{EL2} privileges.  Hypercalls from \texttt{EL0}
+\textbf{shall} be chained via \texttt{EL1} (with appropriate permission
+checks).
+
+\texttt{EL1} apps such as Arrakis, and paravirtualised VMs using hypercalls
+know that they are being virtualised, and will use \texttt{hvc} explicitly.
+Fully-virtualised \texttt{EL1} VMs do not make hypercalls.
+
+ARMv8 implements two-level address translation: VA (virtual address) to IPA
+(intermediate physical address), and IPA to PA (physical address).
+\texttt{EL1} guests \textbf{shall} be isolated at the L1 translation layer,
+and by trapping all accesses to system control registers.
+
+\subsection{Virtual Address Space Layout}\label{s:layout}
+
+ARMv8 has an effective 48-bit virtual address space. At the lowest execution
+levels (0 --- BF user \& 1 --- BF CPU driver), the hardware supports two (up to)
+48-bit (256TB) 'windows' in a 64-bit space: one at the bottom, and one at the
+top.  Each region has its own translation table base register (\texttt{TTBR0}
+\& \texttt{TTBR1}). \texttt{TTBR0} is used at \texttt{EL0}, and \texttt{TTBR1}
+at \texttt{EL1}.
+
+In the initial ARMv8 specification, this split address space was not
+implemented at \texttt{EL2}, which would require a separate CPU driver
+instance for virtualisation, and hypercalls (e.g. for Arrakis). ARMv8.1
+introduced the virtualisation host extensions (VHE) which, among other things,
+extends the split address space to \texttt{EL2}. As this provides a cleaner
+implementation model, and to avoid having to support a now-deprecated
+interface, virtualisation will \textbf{only} be supported on ARMv8.1 and
+later. This means that we will not support virtualisation on the X-Gene 1.
+Both the simulation environment (FVP/FP) and, seemingly, the ThunderX chips,
+support VHE.
+
+The CPU driver \textbf{shall} use \texttt{TTBR1} to provide a complete
+physical window. The ARMv8 CPU driver \textbf{shall not} dynamically map
+device memory into its own window (as the ARMv7 CPU driver does) --- the few
+memory-mapped devices required will be statically mapped on boot, with
+appropriate memory attributes. All physical addresses, RAM and device,
+\textbf{shall} be accessible at a static, standard offset (the base of the
+\texttt{TTBR1} region).
+
+User-level page tables will \textbf{initially} be limited to a 4k translation
+granularity.  \textbf{Eventually} user-level page tables \textbf{should} have
+access to all page-table formats and page sizes, as is the case in the current
+Barrelfish x86 implementation.
+
+\subsection{Address Space, Context, and Thread Identifiers}
+
+ARMv8 also provides address-space identifiers (ASIDs) in the TLB to avoid
+flushing the translation cache on a context switch.
+
+ARMv8 ASIDs (referred to in ARM documentation as context IDs) are
+architecturally allowed to be either 8 or 16 bits, although the SBSA
+specifies that they must be at least 16. Relying on the SBSA platform will
+allow us to avoid multiplexing IDs among active processes, on any
+reasonably-sized system.  Managing the reuse of context IDs can be left to
+user-level code, and does not need to be on the critical path of a context
+switch. The CPU driver need only ensure that every allocated dispatcher has a
+unique ASID, which is loaded into the \texttt{ContextID} register on dispatch.
+
+The value in the \texttt{ContextID} register is also checked against the
+hardware breakpoint and watchpoint registers, in generating debug exceptions.
+Therefore, it \texttt{shall} be possible for authorised user-level code to
+load the Context ID for a given dispatcher into a breakpoint register --- this
+\texttt{may} be an invocation on the dispatcher capability.
+
+\begin{table}
+\begin{center}
+\begin{tabular}{ll}
+\texttt{tpidrro\_el0} & EL0 Read-Only Software Thread ID Register \\
+\texttt{tpidr\_el0} & EL0 Read/Write Software Thread ID Register \\
+\texttt{tpidr\_el1} & EL1 Read/Write Software Thread ID Register \\
+\texttt{tpidr\_el2} & EL2 Read/Write Software Thread ID Register \\
+\texttt{tpidr\_el3} & EL3 Read/Write Software Thread ID Register \\
+\end{tabular}
+\end{center}
+\caption{Thread ID registers in ARMv8}
+\label{t:threadid}
+\end{table}
+
+In addition to the \texttt{ContextID} register, used to tag TLB entries, ARMv8
+also provides a set of thread ID registers with no architecturally-defined
+semantics, as listed in \autoref{t:threadid}. The client-writeable
+\texttt{tpidr\_el0} and \texttt{tpidr\_el1} \textbf{shall} have no CPU
+driver-defined purpose, but \textbf{shall} be saved and restored in a
+dispatcher's trap frame, to allow their use as thread-local storage (TLS).
+Recall that the Barrelfish CPU driver has no awareness of threads, which are
+implemented purely at user level.
+
+To implement the upcall/dispatch mechanism of Barrelfish, the CPU driver and
+the user-level dispatcher need to share a certain amount of state --- the
+user-visible portion of the dispatcher control block, which contains the trap
+frames, and the disabled flag (used to achieve atomic dispatch). The address
+of this structure needs to be known to both the CPU driver, and to user-level
+code, and moreover be efficiently-accessible, as the CPU driver needs to find
+the trap frame on the critical path of system calls and exceptions. This
+pointer also needs to be trustworthy, from the CPU driver's perspective, and
+thus cannot be directly modifiable by user-level code.
+
+The x86-32, x86-64, and ARMv7 CPU drivers all store the address of the running
+dispatcher's shared segment at a fixed known address, \texttt{dcb\_current},
+which is loaded by the trap handler. At user level, on x86 this address is
+held in a \emph{segment register} (\texttt{fs} on x86-64, and \texttt{gs} on
+x86-32), while on ARMv7 we sacrifice a general-purpose register (\texttt{r9})
+for this purpose. Using the \texttt{tpidrro\_el0} register to hold the address
+of the current dispatcher structure will allow us to avoid both a memory load
+on the fast path, and sacrificing a register in user-level code, thus
+\texttt{tpidrro\_el0} \textbf{shall} hold the address of the currently-running
+dispatcher.
+
+\subsection{Instruction Sets}
+
+ARMv8 supports both AArch64, and legacy ARM/Thumb (renamed AArch32). Switching
+execution mode is only possible when switching execution level i.e. on a trap
+or return, and can only be changed while at the higher execution level. Thus,
+\texttt{EL2} can set execution mode for \texttt{EL1}, and \texttt{EL1} for
+\texttt{EL0}. There is no way for a program to change its own execution mode.
+If \texttt{ELn} is in AArch64, then \texttt{EL(n-1)} can be in either AArch64
+or AArch32. If \texttt{ELn} is in AArch32, all lower ELs must also be AArch32.
+
+The CPU driver \textbf{shall} execute in AArch64.
+
+\textbf{Initially}, the CPU driver will enforce that all directly-scheduled
+threads also use AArch64, by controlling all downward EL transitions. An
+\texttt{EL1} client (such as Arrakis or a full virtual machine) may execute
+its own \texttt{EL0} clients in AArch32 (and there is no way to prevent this).
+However, all transitions into the CPU driver (\texttt{svc}, \texttt{hvc} or
+exception) must come from a direct client of the CPU driver, and thus from
+AArch64. The syscall ABI \textbf{shall} be AArch64.
+
+\textbf{Eventually}, Barrelfish \textbf{should} also support the execution of
+AArch32 dispatcher processes, by marking each dispatcher with a flag
+indicating the instruction set to be used (much as is already done with
+VM/non-VM mode in the Arrakis CPU driver).
+
+\subsection{User-Space Access to Architectural Functions}
+
+Generally, anything that can be safely exported, \textbf{should} be made
+available outside of the CPU driver, preferable as a memory-mapped interface,
+at 4kiB granularity. The SBSA mandates that devices be present at addresses
+that can be individually mapped, thus this should not be a problem.
+
+\subsection{Cache Management}
+
+ARMv8 has moved most cache and TLB management from the system control
+coprocessor (cp15), into the core ISA. Several cache operations
+(invalidate/clean by VA) are executable at \texttt{EL0}, and thus no kernel
+interface is required. The system must take into account that user-directed
+flushes may have occurred, or may occur concurrently with any memory
+operation.
+
+\subsection{Performance Monitors}
+
+Performance monitors \textbf{should} be exposed, if it can be done safely.
+
+\subsection{Debugging}
+
+Self-hosted debug \textbf{should} be exposed, if it can be done safely. This
+is under active development.
+
+\subsection{Booting}
+
+Platform support i.e.~a standard set of peripherals, and a defined boot
+process, has improved dramatically on ARM, as it has been repositioned as a
+server platform. UEFI and ACPI support are widespread, including on the
+Mustang development board. We will assume support for UEFI booting, make use
+of ACPI data, where available.
+
+The Barrelfish CPU driver and initial image \textbf{shall} be loaded and
+executed by a UEFI shim, which will pass through all UEFI-supplied
+information, such as ACPI tables, and be able to interpret a Barrelfish
+Multiboot image.  This shim, or second-stage bootloader, is called Hagfish,
+and is described in \autoref{s:hagfish}.
+
+\subsection{Interrupts}
+
+ARMv8 interrupt handling is not substantially different from the existing
+architectures and platforms supported by Barrelfish. While a redesign of the
+Barrelfish interrupt system is under way (to use capabilities to grant access
+to receive interrupts), we do not anticipate ARMv8 to impose any particular
+challenges.
+
+The ARMv8 systems we \textbf{initially} target all use minor variations on the
+ARM Generic Interrupt Controller (GIC) design, already supported in
+Barrelfish. We currently have support for version 2 of the GIC, with which
+later implementations are backward-compatible. We will \textbf{eventually}
+support GICv3, the current specification at time of writing.
+
+\subsection{Inter-Domain Communication}
+
+User-level communication between cache-coherent cores in Barrelfish for ARMv8
+is likely to the same as with ARMv7 and x86, and we expect the existing
+User-level Message-Passing over Cache-Coherence (UMP-CC) interconnect driver
+to work unmodified.
+
+Between dispatchers on the same core, however, the different register set on
+the ARMv8 is likely to result in a very different Local Message Passing (LMP)
+interconnect driver---this is always an architecture-specific part of the CPU
+driver. In practice, its design will be closely tied to the context switch and
+upcall dispatch code.
+
+\section{Hagfish}\label{s:hagfish}
+
+The Barrelfish/ARMv8 UEFI loader prototype is called Hagfish\footnote{A
+hagfish is a basal chordate i.e. something like the ancestor of all fishes.}.
+Hagfish is a second-stage bootloader for Barrelfish on UEFI platforms,
+initially the ARMv8 server platform.  Hagfish is loaded as a UEFI application,
+and uses the large set of supplied services to do as much of the one-time
+(boot core) setup that the CPU driver needs as is reasonably possible. More
+specifically, Hagfish:
+
+\begin{itemize}
+\item Is loaded over BOOTP/PXE.
+\item Reuses the PXE environment to load a menu.lst-style configuration.
+\item Loads the kernel image and the initial applications, as directed, and
+builds a Multiboot image.
+\item Allocates and builds the CPU driver's page tables.
+\item Activates the initial page table, and allocates a stack.
+\end{itemize}
+
+\subsection{Why Another Bootloader?}
+
+The ARMv8 machines that we're porting to are different to both existing ARM
+boards, and to x86. They have a full pre-boot environment, unlike most
+embedded boards, but it's not a PC-style BIOS. The ARM Server Base Boot
+Requirements specify UEFI. Moreover, there is no mainline support from GNU
+GRUB for the ARMv8 architecture, so no matter what, we need some amount of
+fresh code.
+
+Given that we had to write at least a shim loader, and keeping in mind that
+UEFI is multi-platform (and becoming more and more common in the x86 world),
+we're taking the opportunity to simplify the initial boot process within the
+CPU driver by moving the once-only initialisation into the bootloader. In
+particular, while running under UEFI boot services, we have memory allocation
+available for free, e.g. for the initial page tables. By moving ELF loading
+and relocation code into the bootloader, we can eliminate the need to relocate
+running code, and can cut down (hopefully eliminate) special-case code for
+booting the initial core. Subsequent cores can rely on user-level Coreboot
+code to relocate them, and to construct their page tables.
+
+\subsection{Assumptions and Requirements}
+
+Hagfish is (initially at least) intended to support development work on
+AArch64 server-style hardware and, as such, makes the following assumptions:
+
+\begin{itemize}
+\item 64-bit architecture, using ELF binaries. Porting to 32-bit architectures
+wouldn't be hard, if it were ever necessary (probably not).
+\item PXE/BOOTP/TFTP available for booting. Hagfish expects to load its
+configuration, and any binaries needed, using the same PXE context with which
+it was booted. Changing this to boot from a local device (e.g. HDD) wouldn't
+be hard, as the UEFI \texttt{LoadFile} interface abstracts from the hardware.
+\end{itemize}
+
+\subsection{Boot Process}
+
+In detail, Hagfish currently boots as follows:
+
+\begin{enumerate}
+\item \texttt{Hagfish.efi} is loaded over PXE by UEFI, and is executed at a
+runtime-allocated address, with translation (MMU) and caching enabled.
+\item Hagfish queries EFI for the PXE protocol instance used to load it, and
+squirrels away the current network configuration.
+\item Hagfish loads the file \texttt{hagfish.A.B.C.D.cfg} from the TFTP server
+root (where \texttt{A.B.C.D} is the IP address on the interface that ran PXE).
+\item Hagfish parses its configuration, which is essentially a GRUB menu.lst,
+and loads the kernel image and any additional modules specified therein. All
+ELF images are loaded into page-aligned regions of type
+\texttt{EfiBarrelfishELFData}.
+\item Hagfish queries UEFI for the system memory map, then allocates and
+initialises the inital page tables for the CPU driver (mapping all occupied
+physical addresses, within the \texttt{TTBR1} window, see \autoref{s:layout}).
+The frames holding these tables are marked with the EFI memory type\\
+\texttt{EfiBarrelfishBootPagetable}, allocated from the OS-specific range
+(\texttt{0x80000000}--\texttt{0x8fffffff}). All memory allocated by Hagfish on
+behalf of the CPU driver is page-aligned, and tagged with an OS-specific type,
+to allow EFI and Hagfish regions to be safely reclaimed.
+\item Hagfish builds a Multiboot 2 information structure, containing as much
+information as it can get from EFI, including:
+    \begin{itemize}
+    \item ACPI 1.0 and 2.0 tables.
+    \item The EFI memory map (including Hagfish's custom-tagged regions).
+    \item Network configuration (the saved DHCP ack packet).
+    \item The kernel command line.
+    \item All loaded modules.
+    \item The kernel's ELF section headers.
+    \end{itemize}
+\item Hagfish allocates a page-aligned kernel stack (type
+\texttt{EfiBarrelfishCPUDriverStack}), of the size specified in the
+configuration.
+\item Hagfish terminates EFI boot services (calls \texttt{ExitBootServices}),
+activates the CPU driver page table, switches to the kernel stack, and jumps
+into the relocated CPU driver image.
+\end{enumerate}
+
+\subsection{Post-Boot state}
+
+When the CPU driver on the boot core begins executing, it can assume the
+following:
+
+\begin{itemize}
+\item The MMU is configured with all RAM and I/O regions mapped via
+\texttt{TTBR1}.
+\item The CPU driver's code and data are both fully relocated into one or more
+distinct 4kiB-aligned regions.
+\item The stack pointer is at the top of a distinct 4kiB-aligned region of at
+least the requested size.
+\item The first argument register holds the Multiboot 2 magic value.
+\item The second holds a pointer to a Multiboot 2 information structure, in
+its own distinct 4kiB-aligned region.
+\item The console device is configured.
+\item Only one core is enabled.
+\item The Multiboot structure contains at least:
+    \begin{itemize}
+    \item The final EFI memory map, with all areas allocated by Hagfish to
+    hold data passed to the CPU driver marked with OS-specific types, all of
+    which refer to non-overlapping 4k-aligned regions:
+        \begin{description}
+        \item[\ttfamily EfiBarrelfishCPUDriver]
+        The currently-executing CPU driver's text and data segments.
+        \item[\ttfamily EfiBarrelfishCPUDriverStack]
+        The CPU driver's stack.
+        \item[\ttfamily EfiBarrelfishMultibootData]
+        The Multiboot structure.
+        \item[\ttfamily EfiBarrelfishELFData]
+        The unrelocated ELF image for a boot-time module (including that for
+        the CPU driver itself), as loaded over TFTP.
+        \item[\ttfamily EfiBarrelfishBootPageTable]
+        The currently-active page tables.
+        \end{description}
+    \item The CPU driver (kernel) command line.
+    \item A copy of the last DHCP Ack packet.
+    \item A copy of the section headers from the CPU driver's ELF image.
+    \item Module descriptions for the CPU driver and all other boot modules.
+    \item If UEFI provided an ACPI root table, the Multiboot structure
+    contains a pointer to it.
+    \end{itemize}
+\end{itemize}
+
+\subsection{Configuration}
+
+Hagfish configures itself by loading a file whose path is generated from its
+assigned IP address. Thus if your development machine receives the address
+192.168.1.100, Hagfish will load the file\\
+\texttt{hagfish.192.168.1.100.cfg}
+from the same TFTP server used to load it. The format is intended to be as
+close as practical to that of an old-style GRUB menu.lst file. The example
+configuration in \autoref{f:hag_config} loads
+\texttt{/armv8/sbin/cpu\_apm88xxxx} as the CPU driver, with arguments
+\texttt{loglevel=4}, and an 8192B (2-page) stack.
+
+\begin{figure}[htb]
+\begin{center}
+\begin{lstlisting}
+kernel /armv8/sbin/cpu_apm88xxxx loglevel=4
+stack 8192
+module /armv8/sbin/cpu_apm88xxxx
+module /armv8/sbin/init
+
+# Domains spawned by init
+module /armv8/sbin/mem_serv
+module /armv8/sbin/monitor
+
+# Special boot time domains spawned by monitor
+module /armv8/sbin/chips boot
+module /armv8/sbin/ramfsd boot
+module /armv8/sbin/skb boot
+module /armv8/sbin/kaluga boot
+module /armv8/sbin/spawnd boot bootarm=0
+module /armv8/sbin/startd boot
+
+# General user domains
+module /armv8/sbin/serial auto portbase=2
+module /armv8/sbin/fish nospawn
+module /armv8/sbin/angler serial0.terminal xterm
+
+module /armv8/sbin/memtest
+
+module /armv8/sbin/corectrl auto
+module /armv8/sbin/usb_manager auto
+module /armv8/sbin/usb_keyboard auto
+module /armv8/sbin/sdma auto
+\end{lstlisting}
+\end{center}
+\caption{Hagfish configuration file}
+\label{f:hag_config}
+\end{figure}
+
+\chapter{Technical Observations}\label{c:tech}
+
+\section{User-Space Threading}\label{s:threads}
+
+\begin{figure}[htb]
+\begin{center}
+\begin{minipage}[t]{0.3\textwidth}
+\begin{lstlisting}
+clrex
+/* Restore CPSR */
+ldr r0, [r1], #4
+msr cpsr, r0
+/* Restore registers */
+ldmia r1, {r0-r15}
+\end{lstlisting}
+\end{minipage}
+\hspace{2cm}
+\begin{minipage}[t]{0.5\textwidth}
+\begin{lstlisting}
+/* Restore PSTATE, load resume
+ * address into x18 */
+ldp x18, x2, [x1, #(PC_REG * 8)]
+/* Set only NZCV. */
+and x2, x2, #0xf0000000
+msr nzcv, x2
+/* Restore the stack pointer and x30. */
+ldp x30, x2, [x1, #(30 * 8)]
+mov sp, x2
+/* Restore everything else. */
+ldp x28, x29, [x1, #(28 * 8)]
+ldp x26, x27, [x1, #(26 * 8)]
+ldp x24, x25, [x1, #(24 * 8)]
+ldp x22, x23, [x1, #(22 * 8)]
+ldp x20, x21, [x1, #(20 * 8)]
+/* n.b. don't reload x18 */
+ldr      x19, [x1, #(19 * 8)]
+ldp x16, x17, [x1, #(16 * 8)]
+ldp x14, x15, [x1, #(14 * 8)]
+ldp x12, x13, [x1, #(12 * 8)]
+ldp x10, x11, [x1, #(10 * 8)]
+ldp  x8,  x9, [x1, #( 8 * 8)]
+ldp  x6,  x7, [x1, #( 6 * 8)]
+ldp  x4,  x5, [x1, #( 4 * 8)]
+ldp  x2,  x3, [x1, #( 2 * 8)]
+/* n.b. this clobbers x0&x1 */
+ldp  x0,  x1, [x1, #( 0 * 8)]
+/* Return to the thread. */
+br x18
+\end{lstlisting}
+\end{minipage}
+\end{center}
+\caption{\texttt{disp\_resume\_context} on ARMv7 (left) and ARMv8 (right)}
+\label{f:disp_resume}
+\end{figure}
+
+The ARMv8 architecture is in some ways an improvement, and in other ways
+problematic, for the sort of user-level threading implemented in Barrelfish,
+via \emph{scheduler activations}. Under this scheme, the kernel (in Barrelfish
+terms, the \emph{CPU driver}), does not schedule threads directly, but instead
+exposes all scheduling-relevant events via \emph{upcalls} to predefined
+user-level handlers (in Barrelfish, the \emph{dispatcher}), which then
+implements thread scheduling (or something else entirely), as it sees fit.
+This differs from the behaviour of a system such as UNIX, which only ever
+restores a user-level execution context simultaneously with dropping from a
+privileged to an unprivileged execution level.
+
+Processor architectures are, understandably, designed with common software in
+mind. Thus, the primitives available for restoring an execution context i.e.
+register state are often tied closely to those for changing privilege level. A
+common design (which ARMv8 also implements) is the \emph{exception return},
+where privileged code can atomically drop its privilege, and jump to a
+user-level execution address. In ARMv8, the \texttt{eret} instruction
+atomically updates the program state (PSTATE, most importantly the privilege
+level bits), and branches to the address held in the \emph{exception link
+register}, \texttt{elr}.
+
+In implementing user-level threading, we're not concerned with privilege
+levels, but the lack of some equivalent of \texttt{elr} is frustrating. Not
+only does \texttt{eret} provide an atomic update of the program counter and
+the program state, it does so without modifying any general-purpose register.
+Replicating this behaviour at \texttt{EL0}, where \texttt{eret} is unavailable
+is problematic. ARMv8 differs from ARMv7, in that the program counter can no
+longer be the target of a load instruction, but can only be loaded via a
+general-purpose register.
+
+Specifically, the only PC-modifying instructions (other than \texttt{eret})
+are PC-relative branches (which are useless in this scenario) and
+branch-to-register (of which \texttt{br}, \texttt{blr} and \texttt{ret} are
+all special encodings). Since ARMv8 has also removed the \texttt{ldm} (load
+multiple) instruction, there is no way to load the program counter with an
+arbitrary value (the thread's restart address), without overwriting one of the
+general-purpose registers. We cannot restore the thread's register value
+\emph{before} we branch to it, as we'd overwrite the return address, and we
+obviously can't do so afterwards, as the thread likely has no idea that it's
+been interrupted. The only alternative is to trampoline through kernel mode in
+order to use \texttt{eret} (which would eliminate the speed benefit of
+user-level threading), or to reserve a general-purpose register for use by the
+dispatcher. Neither option is appealing, but we went with the second option,
+reserving \texttt{x18}, reasoning that with 31 general-purpose registers
+available, the loss of one isn't a huge penalty. Register \texttt{x18} is
+explicitly marked as the \emph{platform register} in the AArch64 ABI
+\citep{arm:aa64pcs}, for such a purpose.
+
+Future revisions of the ARM architecture could prevent this issue in a number
+of ways: allowing the use of \texttt{eret} at \texttt{EL0} or providing an
+equivalent functionality (specifically a non-general-purpose register such as
+\texttt{elr}, that doesn't need to be restored); or alternatively, adding
+indirect jumps (load to PC) back to the instruction set.
+
+\autoref{f:disp_resume} compares the user-level thread resume code for the
+Barrelfish dispatcher (function \texttt{disp\_resume}) for ARMv7 and ARMv8
+side-by-side. The effect of removing the load-multiple instructions, and
+direct-to-SP loads, on code density is clearly visible: everything on lines
+8--29 for ARMv8 corresponds to the single \texttt{ldmia} instruction on lines
+9 for ARMv7 --- one instruction is now 18, on the thread-switch critical path!
+Note also, on line 17, that the ARMv8 code does not restore the thread's
+\texttt{r18}, but instead uses it to hold the branch address for use on line
+29. The only improvement on ARMv8 is that the \texttt{clrex} (clear exclusive
+monitor) instruction is no longer required, as the monitor is cleared on
+returning from the kernel. Note also that the usual method to efficiently load
+multiple registers, using 16-word SIMD (NEON) loads, isn't available, as
+there's no guarantee that the SIMD extensions are enabled on this dispatcher,
+and we cannot handle a fault in this code.
+
+\section{Trap Handling}\label{s:traps}
+
+\begin{figure}
+\begin{lstlisting}
+el0_aarch64_sync:
+    msr daifset, #3 /* IRQ and FIQ masked, Debug and Abort enabled. */
+
+    stp x11, x12, [sp, #-(2 * 8)]!
+    stp x9,  x10, [sp, #-(2 * 8)]!
+
+    mrs x10, tpidr_el1
+    mrs x9, elr_el1
+
+    ldp x11, x12, [x10, #OFFSETOF_DISP_CRIT_PC_LOW]
+    cmp x11, x9
+    ccmp x12, x9, #0, ls
+    ldr w11, [x10, #OFFSETOF_DISP_DISABLED]
+    ccmp x11, xzr, #0, ls
+    /* NE <-> (low <= PC && PC < high) || disabled != 0 */
+
+    mrs x11, esr_el1  /* Exception Syndrome Register */
+    lsr x11, x11, #26 /* Exception Class field is bits [31:26] */
+
+    b.ne el0_sync_disabled
+
+    add x10, x10, #OFFSETOF_DISP_ENABLED_AREA
+
+save_syscall_context:
+    str x7,       [x10, #(7 * 8)]
+
+    stp x19, x20, [x10, #(19 * 8)]
+    stp x21, x22, [x10, #(21 * 8)]
+    stp x23, x24, [x10, #(23 * 8)]
+    stp x25, x26, [x10, #(25 * 8)]
+    stp x27, x28, [x10, #(27 * 8)]
+    stp x29, x30, [x10, #(29 * 8)] /* FP & LR */
+
+    mrs x20, sp_el0
+    stp x20, x9, [x10, #(31 * 8)]
+
+    mrs x19, spsr_el1
+    str x19, [x10, #(33 * 8)]
+
+    cmp x11, #0x15 /* SVC or HVC from AArch64 EL0 */
+    b.ne el0_abort_enabled
+
+    add sp, sp, #(4 * 8)
+
+    mov x7, x10
+
+    b sys_syscall
+\end{lstlisting}
+\caption{BF/ARMv8 synchronous exception handler}
+\label{f:sync_el0}
+\end{figure}
+
+\autoref{f:sync_el0} shows the CPU driver exception stub, for a synchronous
+abort from \texttt{EL0}. This exception class includes system calls,
+breakpoints, and page faults on both code and data. The effect of the loss of
+store multiple instructions is again visible, for example on lines 27--32.
+Although not as severe as in the case of the user-level thread restore in
+\autoref{s:threads}, the extra instructions required do constrain us somewhat,
+as each trap handler is constrained to 128 bytes, or 32 instructions, before
+branching to another code block.
+
+We were able to squeeze the necessary code into the space available, including
+the optimised test for a disabled dispatcher at lines 10--14, but only by
+splitting the page fault handler (\texttt{el0\_abort\_enabled}) into a
+separate subroutine, incurring an unnecessary branch. A more significant
+annoyance is that system calls (\texttt{svc} and \texttt{hvc}) are routed to
+the same exception vector as page faults (aborts).  The effect of this is that
+we are forced to spill registers to the stack (\texttt{x9}--\texttt{x12} on
+lines 4--5), even on the system call fast path, as we need at least one
+register to check the exception syndrome (\texttt{esr\_el1}) to distinguish
+aborts (where we must preserve all registers) from system calls (where we
+could immediately begin using the caller-saved registers). Note that the code
+on lines 27--32 only needs to stack the callee-saved registers, and leaves the
+system call arguments in \texttt{x0}--\texttt{x7}, to be read as required by
+\texttt{sys\_syscall} (in C).
+
+This sort of mismatch between the exception-handling interface of the CPU
+architecture, and what is required for really high-performance systems code is
+unfortunately extremely common. Unnecessary overheads, such as the additional
+stacked registers here hurt the performance of highly-componentised systems,
+such as Barrelfish, which rely on frequently crossing protection domains.
+
+The relatively well-compressed boolean arithmetic on lines 10--14 demonstrates
+that, even with the loss of ARM's fully-conditional instructions, the
+conditional compares which remain are still relatively powerful.
+
+\section{Cache Coherence}
+
+One aspect of the ARM architecture that is of particular interest for the
+Barrelfish project, but which we have not yet explored in depth, is the
+configurable cache coherency and fine-grained cache management operations
+available. Any virtual mapping on a recent ARM architecture, including both
+ARMv7 and ARMv8, can be tagged with various cacheability properties: inner
+(L1), outer (L2+, usually), write-back or write-through. Combined with the
+explicit flush operations at cache-line granularity, able to target either PoU
+(point of unification, where data and instruction caches merge) or PoC (point
+of coherency, typically RAM), a multi-core, multi-socket ARMv8 system would
+make a very interesting testbed for investigating efficient cache management
+and communication primitives for future partially-coherent architectures.
+Indeed, the latest revision of the ARMv8 specification, ARMv8.2, introduced
+flush to PoP, or \emph{point of persistence} --- perhaps in response to
+interest from well-known systems integration firms investigating large
+persistent memories.
+
+The design presented in this report is intended to expose as much control over
+the caching hierarchy as possible to user-level code, to provide a platform
+for future research.
+
+\bibliographystyle{plainnat}
+\bibliography{defs,barrelfish}
+
+\end{document}
index 42b9d98..a779004 100644 (file)
@@ -32,6 +32,7 @@
          "TN-018-PracticalGuide.pdf",
          "TN-019-DeviceDriver.pdf",
          "TN-020-Sockeye.pdf",
-         "TN-021-CPUDriver.pdf" ]]
+         "TN-021-CPUDriver.pdf",
+         "TN-022-ARMv8.pdf" ]]
     "Documentation for Barrelfish"
 ]
index 3c9f4a6..4306693 100644 (file)
@@ -48,6 +48,44 @@ Note that this file will not compile without defs.bib; ie. you need to do:
   year =        2007
 }
 
+@techreport{arm:aa64pcs,
+  author = {ARM},
+  title = {Procedure Call Standard for the {ARM} 64-bit Architecture ({AArch64})},
+  number = {ARM-IHI-0055B},
+  version = {1.0},
+  year = {2013},
+  month = may,
+  url = {http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf}
+}
+
+@techreport{arm:sbsa,
+  author = {ARM},
+  title = {Server Base System Architecture},
+  number = {ARM-DEN-0029},
+  version = {3.0},
+  year = {2016},
+  month = feb,
+  url = {http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029/index.html}
+}
+
+@techreport{acpi,
+  author = {UEFI},
+  title = {Advanced Configuration and Power Interface Specification},
+  version = {6.1},
+  year = {2016},
+  month = jan,
+  url = {http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf}
+}
+
+@techreport{uefi,
+  author = {UEFI},
+  title = {Unified Extensible Firmware Interface Specification},
+  version = {2.6},
+  year = {2016},
+  month = jan,
+  url = {http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf}
+}
+
 @TechReport{rockcreek_core_eas,
   author =      {Michael Konow},
   title =       {{Rock Creek Core}},
@@ -708,6 +746,18 @@ Henry M. Levy},
   year = 2008
 }
 
+@inproceedings{peter:osdi14,
+  title = {{Arrakis: The Operating System is the Control Plane}}, 
+  author = {Simon Peter and Jialin Li and Irene Zhang and
+            Dan R. K. Ports and Doug Woos and Arvind Krishnamurthy and
+            Thomas Anderson and Timothy Roscoe},
+  booktitle = osdi14,
+  year = {2014},
+  month = oct,
+  address = {Broomfield, Colorado, USA},
+  note = {}
+}
+
 @article{planas:hierarchical,
  author = {Planas, Judit and Badia, Rosa M. and Ayguad\'{e}, Eduard and Labarta, Jesus},
  title = {Hierarchical Task-Based Programming With {StarSs}},
@@ -1193,6 +1243,15 @@ D. E. Long and Carlos Maltzahn},
   number =      013,
   month =       mar}
 
+@TechReport{btn017-arm,
+  author =      bft,
+  title =       {{Barrelfish} on {ARMv7}},
+  institution =  {Systems Group, ETH Zurich},
+  year =        2013,
+  type =        btn,
+  number =      017,
+  month =       dec}
+
 @article{gem5:sigarch11,
  author = {Binkert, Nathan and Beckmann, Bradford and Black, Gabriel and Reinhardt, Steven K. and Saidi, Ali and Basu, Arkaprava and Hestness, Joel and Hower, Derek R. and Krishna, Tushar and Sardashti, Somayeh and Sen, Rathijit and Sewell, Korey and Shoaib, Muhammad and Vaish, Nilay and Hill, Mark D. and Wood, David A.},
  title = {The Gem5 Simulator},
@@ -1261,4 +1320,4 @@ D. E. Long and Carlos Maltzahn},
 @Misc{multiboot1,
   title =    {Multiboot Specification (latest version)},
   note =     {\url{http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.texi?h=multiboot}}
-}
\ No newline at end of file
+}
index 59c2284..108ae0c 100644 (file)
@@ -67,6 +67,7 @@ Implementation"}
 @string{osdi04 = proc#"6th "#osdi}
 @string{osdi06 = proc#"7th "#osdi}
 @string{osdi08 = proc#"8th "#osdi}
+@string{osdi14 = proc#"11th "#osdi}
 
 @string{pldi = "ACM SIGPLAN Conference on Programming Language Design and Implementation"}
 @string{pldi96 = proc#pldi}
index f646d6a..99bd7ea 100755 (executable)
@@ -91,11 +91,15 @@ errors kernel SYS_ERR_ {
     failure VM_FRAME_TOO_SMALL      "Frame too small for superpage mapping",
 
     // errors related to IRQ table
-    failure IRQ_LOOKUP          "Specified capability was not found while inserting in IRQ table",
-    failure IRQ_NOT_ENDPOINT    "Specified capability is not an endpoint cap",
-    failure IRQ_NO_LISTENER     "No listener on specified endpoint cap", // ??
-    failure IRQ_INVALID         "Invalid interrupt number",
-    failure IRQ_NO_FREE_VECTOR  "Unable to allocate vector",
+    failure IRQ_LOOKUP              "Specified capability was not found while inserting in IRQ table",
+    failure IRQ_NOT_ENDPOINT        "Specified capability is not an endpoint cap",
+    failure IRQ_NO_LISTENER         "No listener on specified endpoint cap", // ??
+    failure IRQ_INVALID             "Invalid interrupt number",
+    failure IRQ_NO_FREE_VECTOR      "Unable to allocate vector",
+    failure IRQ_LOOKUP_DEST         "Specified capability was not found while connecting IRQ",
+    failure IRQ_LOOKUP_EP           "Specified endpoint capability was not found while connecting IRQ",
+    failure IRQ_NOT_IRQ_TYPE        "Specified capability is not an IRQ cap",
+    failure IRQ_WRONG_CONTROLLER    "Specified IRQ capability does not target local controller",
 
     // IO capability
     failure IO_PORT_INVALID     "IO port out of range",
@@ -775,6 +779,7 @@ errors driverkit DRIVERKIT_ {
 
 // errors in PCI/device handling
 errors pci PCI_ERR_ {
+    failure DEVICE_NOT_INIT     "Device not initialized",
     failure IOAPIC_INIT         "Failed in ioapic_init()",
     failure MINT_IOCAP          "Failed to mint IO cap",
     failure ROUTING_IRQ         "Failed while routing interrupt",
index cf94dec..5e334e1 100644 (file)
@@ -25,6 +25,7 @@ commonFlags = [ Str s | s <- [ "-fno-builtin",
                                 "-Wshadow",
                                 "-Wmissing-declarations",
                                 "-Wmissing-field-initializers",
+                                "-Wtype-limits",
                                 "-Wredundant-decls",
                                 "-Werror" ] ]
 
index 70124c7..23f328a 100644 (file)
@@ -121,6 +121,9 @@ source_dir :: String
 install_dir :: String
 -- install_dir = undefined -- (set by hake.sh, see end of file)
 
+cache_dir :: String
+-- cache_dir = undefined -- (set by hake.sh, see end of file)
+
 -- Set of architectures for which to generate rules
 architectures :: [String]
 -- architectures = undefined -- (set by hake.sh, see end of file)
@@ -223,6 +226,12 @@ libacpi_debug = False
 acpi_interface_debug :: Bool
 acpi_interface_debug = False
 
+acpi_service_debug :: Bool
+acpi_service_debug = False
+
+acpi_server_debug :: Bool
+acpi_server_debug = False
+
 lpc_timer_debug :: Bool
 lpc_timer_debug = False
 
@@ -295,6 +304,7 @@ memserv_percore = False
 lazy_thc :: Bool
 lazy_thc
     | elem "armv7" architectures   = False
+    | elem "armv7-m" architectures   = False
     | elem "armv5" architectures   = False
     | elem "armv8" architectures   = False
     | elem "xscale" architectures  = False
@@ -391,9 +401,10 @@ defines = [ Str ("-D" ++ d) | d <- [
              if netd_debug then "NETD_SERVICE_DEBUG" else "",
              if libacpi_debug then "ACPI_DEBUG_OUTPUT" else "",
              if acpi_interface_debug then "ACPI_BF_DEBUG" else "",
+             if acpi_service_debug then "ACPI_SERVICE_DEBUG" else "",
              if lpc_timer_debug then "LPC_TIMER_DEBUG" else "",
              if lwip_debug then "LWIP_BARRELFISH_DEBUG" else "",
-             if libpci_debug then "PCI_CLIENT_DEBUG" else "",
+             if libpci_debug then "PCI_LIB_DEBUG" else "",
              if usrpci_debug then "PCI_SERVICE_DEBUG" else "",
              if timer_debug then "TIMER_CLIENT_DEBUG" else "",
              if eclipse_kernel_debug then "ECLIPSE_KERNEL_DEBUG" else "",
index 22cd930..492b4d7 100644 (file)
@@ -17,6 +17,11 @@ import Data.Typeable
 data TreeRef = SrcTree | BuildTree | InstallTree
              deriving (Show,Eq,Ord)
 
+-- Note on Abs:
+-- The first parameter is a rule referring to an absolute resource whereas the
+-- second one is converted as all other rules. Dependencies and targets are
+-- generated from the second one to.
+
 data RuleToken = In     TreeRef String String -- Input to the computation
                | Dep    TreeRef String String -- Extra (implicit) dependency
                | NoDep  TreeRef String String -- File that's not a dependency
@@ -28,8 +33,13 @@ data RuleToken = In     TreeRef String String -- Input to the computation
                | ContStr Bool String String   -- Conditional string 
                | ErrorMsg String              -- Error message: $(error x)
                | NL                           -- New line
+               | Abs RuleToken RuleToken      -- Absolute path rule token
                  deriving (Show,Eq,Ord)
 
+-- Convert a rule into an absolute rule
+makeAbs :: RuleToken -> RuleToken
+makeAbs rule = Abs rule rule
+
 data HRule = Rule [ RuleToken ]
            | Include RuleToken
            | Error String
@@ -44,6 +54,7 @@ frArch (Dep _ a _ ) = a
 frArch (NoDep _ a _ ) = a
 frArch (PreDep _ a _ ) = a
 frArch (Target a _ ) = a
+frArch (Abs rule _) = frArch rule
 frArch t = ""
 
 frPath :: RuleToken -> String
@@ -53,6 +64,7 @@ frPath (Dep _ _ p) = p
 frPath (NoDep _ _ p) = p
 frPath (PreDep _ _ p) = p
 frPath (Target _ p) = p
+frPath (Abs rule _) = frPath rule
 frPath t = ""
 
 frTree :: RuleToken -> TreeRef
@@ -60,6 +72,7 @@ frTree (In t _ _) = t
 frTree (Dep t _ _) = t
 frTree (NoDep t _ _) = t
 frTree (PreDep t _ _) = t
+frTree (Abs rule _) = frTree rule
 frTree t = BuildTree
 
 isFileRef :: RuleToken -> Bool
@@ -67,20 +80,24 @@ isFileRef (Str _ ) = False
 isFileRef (NStr _ ) = False
 isFileRef (ErrorMsg _) = False
 isFileRef NL = False
+isFileRef (Abs rule _) = isFileRef rule
 isFileRef _ = True
 
 isDependency :: RuleToken -> Bool
 isDependency (In _ _ _) = True
 isDependency (Dep _ _ _) = True
+isDependency (Abs rule _) = isDependency rule
 isDependency _ = False
 
 isPredependency :: RuleToken -> Bool
 isPredependency (PreDep _ _ _) = True
+isPredependency (Abs rule _) = isPredependency rule
 isPredependency _ = False
 
 isOutput :: RuleToken -> Bool
 isOutput (Out _ _) = True
 isOutput (Target _ _) = True
+isOutput (Abs rule _) = isOutput rule
 isOutput _ = False
 
 formatToken :: RuleToken -> String
@@ -92,6 +109,7 @@ formatToken (PreDep _ a f) = f ++ " "
 formatToken (Target a f) = f ++ " "
 formatToken (Str s) = s ++ " "
 formatToken (NStr s) = s 
+formatToken (Abs rule _) = formatToken rule
 formatToken (ErrorMsg s) = "$(error " ++ s ++ ")"
 formatToken (NL) = "\n\t"
 
index ac1882e..219e452 100644 (file)
@@ -58,6 +58,7 @@ data Opts = Opts { opt_makefilename :: String,
                    opt_installdir :: String,
                    opt_sourcedir :: String,
                    opt_bfsourcedir :: String,
+                   opt_builddir :: String,
                    opt_abs_installdir :: String,
                    opt_abs_sourcedir :: String,
                    opt_abs_bfsourcedir :: String,
@@ -74,6 +75,7 @@ parse_arguments [] =
          opt_installdir = Config.install_dir,
          opt_sourcedir = Config.source_dir,
          opt_bfsourcedir = Config.source_dir,
+         opt_builddir = ".",
          opt_abs_installdir = "",
          opt_abs_sourcedir = "",
          opt_abs_bfsourcedir = "",
@@ -365,13 +367,19 @@ data CompiledRule =
         ruleDirs       :: S.Set FilePath
     }
 
+
+-- Get the relative rule from an absolute rule pair
+makeRelativeRule :: RuleToken -> RuleToken
+makeRelativeRule (Abs _ t) = t
+makeRelativeRule t = t
+
 compileRule :: [RuleToken] -> CompiledRule
 compileRule [] = CompiledRule S.empty  S.empty  S.empty  []  S.empty
 compileRule (t:ts) =
     let CompiledRule outs deps predeps body dirs = compileRule ts
-        outs'    = if isOutput t then S.insert t outs else outs
-        deps'    = if isDependency t then S.insert t deps else deps
-        predeps' = if isPredependency t then S.insert t predeps else predeps
+        outs'    = if isOutput t then S.insert (makeRelativeRule t) outs else outs
+        deps'    = if isDependency t then S.insert (makeRelativeRule t) deps else deps
+        predeps' = if isPredependency t then S.insert (makeRelativeRule t) predeps else predeps
         body'    = if inRule t then t:body else body
         dirs'    = if isFileRef t &&
                       inTree (frPath t) &&
@@ -444,10 +452,6 @@ makefilePreamble h opts args =
            [ "# ",
              "Q=@",
              "SRCDIR=" ++ opt_sourcedir opts,
-             "INSTALLDIR=" ++ opt_installdir opts,
-             "ABSINSTALLDIR=" ++ opt_abs_installdir opts,
-             "ABSSRCDIR=" ++ opt_abs_sourcedir opts,
-             "ABSBUILDDIR=" ++ opt_abs_builddir opts,
              "HAKE_ARCHS=" ++ intercalate " " Config.architectures,
              "include ./symbolic_targets.mk" ])
 
@@ -455,7 +459,7 @@ makefilePreamble h opts args =
 -- architecture-specific one.
 arch_list :: S.Set String
 arch_list = S.fromList (Config.architectures ++
-                        ["", "src", "hake", "root", "tools", "docs"])
+                        ["", "src", "hake", "root", "tools", "docs", "cache"])
 
 -- A rule is included if it applies to only "special" and configured
 -- architectures.
@@ -586,6 +590,14 @@ resolveTokenPath o hakepath (PreDep tree arch path) =
 -- An target token implicitly refers to the build tree.
 resolveTokenPath o hakepath (Target arch path) = 
     (Target arch (treePath o BuildTree arch path hakepath))
+-- A target token referring to an absolute resource
+resolveTokenPath o hakepath (Abs rule rule2) =
+    let o' = o {
+            opt_sourcedir = opt_abs_sourcedir o,
+            opt_installdir = opt_abs_installdir o,
+            opt_builddir = opt_abs_builddir o
+        }
+    in Abs (resolveTokenPath o' hakepath rule) (resolveTokenPath o hakepath rule2)
 -- Other tokens don't contain paths to resolve.
 resolveTokenPath _ _ token = token
 
@@ -603,14 +615,21 @@ treePath :: Opts -> TreeRef -> FilePath -> FilePath -> FilePath -> FilePath
 treePath o SrcTree "root" path hakepath = 
     relPath (opt_sourcedir o) path hakepath
 treePath o BuildTree "root" path hakepath = 
-    relPath "." path hakepath
+    relPath (opt_builddir o) path hakepath
 treePath o InstallTree "root" path hakepath = 
     relPath (opt_installdir o) path hakepath
+-- The architecture 'cache' is special.
+treePath o SrcTree "cache" path hakepath =
+    relPath Config.cache_dir path hakepath
+treePath o BuildTree "cache" path hakepath =
+    relPath Config.cache_dir path hakepath
+treePath o InstallTree "cache" path hakepath =
+    relPath Config.cache_dir path hakepath
 -- Source-tree paths don't get an architecture.
 treePath o SrcTree arch path hakepath =
     relPath (opt_sourcedir o) path hakepath
 treePath o BuildTree arch path hakepath =
-    relPath ("." </> arch) path hakepath
+    relPath ((opt_builddir o) </> arch) path hakepath
 treePath o InstallTree arch path hakepath =
     relPath (opt_installdir o </> arch) path hakepath
 
index f63c696..9172e7a 100644 (file)
@@ -672,7 +672,8 @@ flounderTHCStub opts ifn srcs =
                    ],
               compileGeneratedCFile opts cfile,
               extraCDependencies opts hfile srcs,
-              extraGeneratedCDependency opts hfile cfile
+              extraGeneratedCDependency opts hfile cfile,
+              extraGeneratedCDependency opts (flounderIfDefsPath ifn) cfile
             ]
 
 --
@@ -1281,4 +1282,16 @@ boot name archs tokens docstr =
 copyFile :: TreeRef -> String -> String -> String -> String -> HRule
 copyFile stree sarch spath darch dpath =
   Rule [ Str "cp", Str "-v", In stree sarch spath, Out darch dpath ]
-  
+
+getExternalDependency :: String -> String -> [ HRule ]
+getExternalDependency url name =
+    [
+        Rule ( [
+            Str "curl",
+            Str "--create-dirs",
+            Str "-o",
+            Out "cache" name,
+            Str url
+        ] ),
+        copyFile SrcTree "cache" name "" name
+    ]
index 3659425..6f0285e 100755 (executable)
@@ -14,6 +14,7 @@ RUN_HAKE="Yes"
 HAKEDIR=$(dirname $0)
 DEFAULT_JOBS=4
 JOBS="$DEFAULT_JOBS"
+CACHEDIR="$HOME/.cache/barrelfish"
 
 # Don't override the default toolchain unless asked to.
 TOOLROOT=Nothing
@@ -38,6 +39,8 @@ usage() {
     echo "   -r|--toolroot <path>: where should I look for toolchains (instead"
     echo "       of (/home/netos/tools)"
     echo "   -j|--jobs: Number of parallel jobs to run (default $DEFAULT_JOBS)."
+    echo "   --cachedir: Cache directory (default $CACHEDIR)."
+    echo "   --help: Print this help."
     echo ""
     echo "  The way you use this script is to create a new directory for your"
     echo "  build tree, cd into it, and run this script with the --source-dir"
@@ -51,7 +54,7 @@ usage() {
 #
 # Legacy compatibility to avoid breaking the harness...
 #
-if [ $# -eq 1 ]; then
+if [[ $# -eq 1 ]] && [[ $1 != "-"* ]]; then
     echo "WARNING: old usage of hake.sh (sole argument gives the source directory) is"
     echo "deprecated: please use --source-dir instead."
     SRCDIR="$1"
@@ -120,6 +123,13 @@ while [ $# -ne 0 ]; do
            JOBS="$2"
         shift 
         ;;
+    "--cachedir")
+        CACHEDIR="$2"
+        shift
+        ;;
+    "--help")
+        usage
+        ;;
        *) 
            usage
            ;;
@@ -153,6 +163,11 @@ else
 fi
 echo "Architectures to build: $ARCHS"
 
+if [ ! -d "$CACHEDIR" ] ; then
+    mkdir -p "$CACHEDIR"
+    chmod g+rw "$CACHEDIR"
+fi
+
 if [ ! -d hake ] ; then
     echo "Creating a local hake directory..."
     mkdir -p hake
@@ -176,6 +191,7 @@ thumb_toolspec   = $THUMB_TOOLSPEC
 armeb_toolspec   = $ARMEB_TOOLSPEC
 x86_toolspec     = $X86_TOOLSPEC
 k1om_toolspec    = $K1OM_TOOLSPEC
+cache_dir         = "$CACHEDIR"
 EOF
 else
     echo "You already have Config.hs, leaving it as-is."
index e85da74..1468249 100644 (file)
@@ -417,7 +417,7 @@ rehake: ./hake/hake
 .PHONY: rehake
 
 clean::
-       $(RM) -r tools docs $(HAKE_ARCHS)
+       $(RM) -r tools docs $(HAKE_ARCHS) $(MODULES_GENERIC)
 .PHONY: clean
 
 realclean:: clean
index a6ab867..d73c003 100644 (file)
@@ -34,6 +34,9 @@ interface monitor_blocking "The monitor to client RPC interface" {
 
     rpc get_phyaddr_cap(out cap pyaddr, out errval err);
     rpc get_io_cap(out cap io, out errval err);
+    
+    // Get a capability that is targeted at the local apic.
+    rpc get_irq_dest_cap(out cap io, out errval err);
 
     // Resource control
     rpc rsrc_manifest(in cap dispatcher, in string manifest,
index 331e5ed..3deca93 100644 (file)
--- a/if/pci.if
+++ b/if/pci.if
@@ -19,10 +19,8 @@ interface pci "The PCI Interface" {
                         in uint32 bus,
                         in uint32 dev,
                         in uint32 fun,
-                        in uint8 coreid,  // core ID for interrupt handler
-                        in uint32 vector, // interrupt vector (0 == no interrupt)
                         out errval err,
-                        out uint8 nr_allocated_bars,
+                        out uint8 nr_allocated_bars, // Number of bars supported
                         out caps_per_bar caps_per_bar);
 
     /* Init legacy IO device */
@@ -34,10 +32,16 @@ interface pci "The PCI Interface" {
                            out errval err,
                            out cap iocap);
 
-    /* request the cap for a previously-initialised device */
-    rpc get_cap(in uint32 idx, in uint32 cap_nr,
+    /* request a bar cap for a previously-initialised device */
+    rpc get_bar_cap(in uint32 idx, in uint32 cap_nr,
                 out errval err, out cap cap, out uint8 type, out uint8 bar_nr);
 
+    /* request an io cap for a previously-initialised device */
+    rpc get_io_cap(in uint16 idx, out errval err, out cap cap);
+
+    /* request an irq cap for a previously-initialised device */
+    rpc get_irq_cap(in uint16 idx, out errval err, out cap cap);
+
     /* reregister interrupt for a previously-initialized device */
     rpc reregister_interrupt(in uint32 class_code,
                         in uint32 sub_class,
@@ -61,6 +65,9 @@ interface pci "The PCI Interface" {
 
     /* write PCI conf header */
     rpc write_conf_header(in uint32 dword, in uint32 val, out errval err);
+    
+    /* Enable (legacy) interrupt */
+    rpc irq_enable(out errval err);
 
     /* Enable MSI-X for the specified PCI device. */
     rpc msix_enable_addr(in uint8 bus, in uint8 dev, in uint8 fn,
index df61af1..bb9c53c 100644 (file)
@@ -126,7 +126,7 @@ static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap,
     uint8_t invoke_bits = get_cap_valid_bits(root);
     capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
 
-    assert(newtype <= 0xffff);
+    assert(newtype < ObjType_Num);
     assert(objbits <= 0xff);
     assert(bits <= 0xff);
     return syscall6((invoke_bits << 16) | (CNodeCmd_Retype << 8) | SYSCALL_INVOKE, invoke_cptr, cap,
@@ -166,9 +166,7 @@ static inline errval_t invoke_cnode_create(struct capref root,
     uint8_t invoke_bits = get_cap_valid_bits(root);
     capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
 
-    assert(type <= 0xffff);
-    assert(objbits <= 0xff);
-    assert(dest_vbits <= 0xff);
+    assert(type < ObjType_Num);
 
     return syscall5((invoke_bits << 16) | (CNodeCmd_Create << 8) | SYSCALL_INVOKE,
                     invoke_cptr, (type << 16) | (objbits << 8) | dest_vbits,
@@ -500,8 +498,6 @@ invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher,
     uint8_t invoke_bits = get_cap_valid_bits(dispatcher);
     capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits);
 
-    assert(root_vbits <= 0xff);
-
     return syscall7((invoke_bits << 16) | (DispatcherCmd_Setup << 8) | SYSCALL_INVOKE,
                     invoke_cptr, dd_caddr, root_caddr,
                     (run << 8) | (root_vbits & 0xff), vtree_caddr,
@@ -522,6 +518,34 @@ static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher,
     return LIB_ERR_NOT_IMPLEMENTED;
 }
 
+static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap)
+{
+    struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap));
+    return ret.error;
+}
+
+static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
+{
+    uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
+    capaddr_t dcn_addr = get_cnode_addr(dest_cap);
+    struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
+    return ret.error;
+}
+
 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
 {
     uint8_t invoke_bits = get_cap_valid_bits(irqcap);
@@ -605,11 +629,6 @@ invoke_dispatcher_properties(
     uint8_t invoke_bits = get_cap_valid_bits(dispatcher);
     capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits);
 
-    if (weight > 0xffff)
-    {
-        weight = 0xffff;
-    }
-
     return syscall7((invoke_bits << 16) | (DispatcherCmd_Properties << 8) | SYSCALL_INVOKE,
                     invoke_cptr,
                     (type << 16) | weight,
index 5068266..96290fa 100644 (file)
@@ -125,7 +125,7 @@ static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap,
     uint8_t invoke_bits = get_cap_valid_bits(root);
     capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
 
-    assert(newtype <= 0xffff);
+    assert(newtype < ObjType_Num);
     assert(objbits <= 0xff);
     assert(bits <= 0xff);
     return syscall6((invoke_bits << 16) | (CNodeCmd_Retype << 8) | SYSCALL_INVOKE, invoke_cptr, cap,
@@ -165,9 +165,7 @@ static inline errval_t invoke_cnode_create(struct capref root,
     uint8_t invoke_bits = get_cap_valid_bits(root);
     capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
 
-    assert(type <= 0xffff);
-    assert(objbits <= 0xff);
-    assert(dest_vbits <= 0xff);
+    assert(type < ObjType_Num);
 
     return syscall5((invoke_bits << 16) | (CNodeCmd_Create << 8) | SYSCALL_INVOKE,
                     invoke_cptr, (type << 16) | (objbits << 8) | dest_vbits,
@@ -497,8 +495,6 @@ invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher,
     uint8_t invoke_bits = get_cap_valid_bits(dispatcher);
     capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits);
 
-    assert(root_vbits <= 0xff);
-
     return syscall7((invoke_bits << 16) | (DispatcherCmd_Setup << 8) | SYSCALL_INVOKE,
                     invoke_cptr, dd_caddr, root_caddr,
                     (run << 8) | (root_vbits & 0xff), vtree_caddr,
@@ -519,6 +515,34 @@ static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher,
     return LIB_ERR_NOT_IMPLEMENTED;
 }
 
+static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap)
+{
+    struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap));
+    return ret.error;
+}
+
+static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
+{
+    uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
+    capaddr_t dcn_addr = get_cnode_addr(dest_cap);
+    struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
+    return ret.error;
+}
+
 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
 {
     uint8_t invoke_bits = get_cap_valid_bits(irqcap);
@@ -602,11 +626,6 @@ invoke_dispatcher_properties(
     uint8_t invoke_bits = get_cap_valid_bits(dispatcher);
     capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits);
 
-    if (weight > 0xffff)
-    {
-        weight = 0xffff;
-    }
-
     return syscall7((invoke_bits << 16) | (DispatcherCmd_Properties << 8) | SYSCALL_INVOKE,
                     invoke_cptr,
                     (type << 16) | weight,
index c4a8087..993eb5d 100644 (file)
@@ -80,7 +80,7 @@ static inline errval_t invoke_cnode_retype(struct capref root, capaddr_t cap,
     uint8_t invoke_bits = get_cap_valid_bits(root);
     capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
 
-    assert(newtype <= 0xffff);
+    assert(newtype <= ObjType_Num);
     assert(objbits <= 0xff);
     assert(bits <= 0xff);
 
@@ -121,9 +121,7 @@ static inline errval_t invoke_cnode_create(struct capref root,
     uint8_t invoke_bits = get_cap_valid_bits(root);
     capaddr_t invoke_cptr = get_cap_addr(root) >> (CPTR_BITS - invoke_bits);
 
-    assert(type <= 0xffff);
-    assert(objbits <= 0xff);
-    assert(dest_vbits <= 0xff);
+    assert(type <= ObjType_Num);
 
     return syscall5((invoke_bits << 16) | (CNodeCmd_Create << 8) | SYSCALL_INVOKE,
                     invoke_cptr, (type << 16) | (objbits << 8) | dest_vbits,
@@ -448,8 +446,6 @@ invoke_dispatcher(struct capref dispatcher, struct capref domdispatcher,
     uint8_t invoke_bits = get_cap_valid_bits(dispatcher);
     capaddr_t invoke_cptr = get_cap_addr(dispatcher) >> (CPTR_BITS - invoke_bits);
 
-    assert(root_vbits <= 0xff);
-
     return syscall7((invoke_bits << 16) | (DispatcherCmd_Setup << 8) |
                     SYSCALL_INVOKE,
                     invoke_cptr, dd_caddr, root_caddr,
@@ -472,6 +468,37 @@ static inline errval_t invoke_dispatcher_setup_guest(struct capref dispatcher,
     return LIB_ERR_NOT_IMPLEMENTED;
 }
 
+static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap)
+{
+    struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap));
+    return ret.error;
+}
+
+static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
+{
+    uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
+    capaddr_t dcn_addr = get_cnode_addr(dest_cap);
+    struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
+    return ret.error;
+}
+
+/**
+ * Deprecated. Use invoke_irqtable_alloc_dest_cap
+ */
 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
 {
     uint8_t invoke_bits = get_cap_valid_bits(irqcap);
index 41cb8a7..a1e93b4 100644 (file)
@@ -413,7 +413,37 @@ invoke_dispatcher_setup_guest(struct capref dispatcher,
                        get_cap_addr(guest_control_cap)).error;
 }
 
+static inline errval_t invoke_irqdest_connect(struct capref irqcap, struct capref epcap)
+{
+    struct sysret ret = cap_invoke2(irqcap, IRQDestCmd_Connect, get_cap_addr(epcap));
+    return ret.error;
+}
 
+static inline errval_t invoke_irqdest_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQDestCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqsrc_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQSrcCmd_GetVector);
+    *out_vec = ret.value;
+    return ret.error;
+}
+
+static inline errval_t invoke_irqtable_alloc_dest_cap(struct capref irqcap, struct capref dest_cap)
+{
+    uint8_t dcn_vbits = get_cnode_valid_bits(dest_cap);
+    capaddr_t dcn_addr = get_cnode_addr(dest_cap);
+    struct sysret ret = cap_invoke4(irqcap, IRQTableCmd_AllocDestCap, dcn_vbits, dcn_addr, dest_cap.slot);
+    return ret.error;
+}
+
+/**
+ * Deprecated. Use invoke_irqtable_alloc_dest_cap
+ */
 static inline errval_t invoke_irqtable_alloc_vector(struct capref irqcap, int *retirq)
 {
     struct sysret ret = cap_invoke1(irqcap, IRQTableCmd_Alloc);
index a3bf461..2828ed3 100644 (file)
@@ -16,6 +16,11 @@ __BEGIN_DECLS
 
 typedef void (*interrupt_handler_fn)(void *);
 
+
+errval_t inthandler_setup_movable_cap(struct capref dest_cap, interrupt_handler_fn handler, void *handler_arg,
+                                  interrupt_handler_fn reloc_handler,
+                                  void *reloc_handler_arg);
+
 errval_t inthandler_setup_movable(interrupt_handler_fn handler, void *handler_arg,
                                   interrupt_handler_fn reloc_handler,
                                   void *reloc_handler_arg,
@@ -25,6 +30,8 @@ errval_t inthandler_setup(interrupt_handler_fn handler, void *handler_arg,
 errval_t inthandler_setup_arm(interrupt_handler_fn handler, void *handler_arg,
         uint32_t irq);
 
+errval_t alloc_dest_irq_cap(struct capref *retcap);
+
 extern struct waitset *barrelfish_interrupt_waitset;
 
 __END_DECLS
index 8ec884f..9d6909d 100644 (file)
@@ -16,6 +16,7 @@
 #define BARRELFISH_SYS_DEBUG_H
 
 #include <sys/cdefs.h>
+#include <barrelfish/caddr.h>
 
 __BEGIN_DECLS
 
@@ -43,6 +44,7 @@ errval_t sys_debug_hardware_timer_read(uintptr_t* ret);
 errval_t sys_debug_hardware_timer_hertz_read(uintptr_t* ret);
 errval_t sys_debug_hardware_global_timer_read(uint64_t *ret);
 errval_t sys_debug_get_apic_ticks_per_sec(uint32_t *ret);
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi);
 
 #ifdef ENABLE_FEIGN_FRAME_CAP
 errval_t sys_debug_feign_frame_cap(struct capref slot, lpaddr_t base,
index c8340d9..05272cd 100644 (file)
@@ -55,7 +55,7 @@ struct dcb;
 
 static inline bool type_is_vnode(enum objtype type)
 {
-    STATIC_ASSERT(44 == ObjType_Num, "Check VNode definitions");
+    STATIC_ASSERT(46 == ObjType_Num, "Check VNode definitions");
 
     return (type == ObjType_VNode_x86_64_pml4 ||
             type == ObjType_VNode_x86_64_pdpt ||
@@ -82,7 +82,7 @@ static inline bool type_is_vnode(enum objtype type)
 static inline size_t vnode_objbits(enum objtype type)
 {
     // This function should be emitted by hamlet or somesuch.
-    STATIC_ASSERT(44 == ObjType_Num, "Check VNode definitions");
+    STATIC_ASSERT(46 == ObjType_Num, "Check VNode definitions");
 
     if (type == ObjType_VNode_x86_64_pml4 ||
         type == ObjType_VNode_x86_64_pdpt ||
@@ -120,7 +120,7 @@ static inline size_t vnode_objbits(enum objtype type)
  */
 static inline size_t vnode_entry_bits(enum objtype type) {
     // This function should be emitted by hamlet or somesuch.
-    STATIC_ASSERT(44 == ObjType_Num, "Check VNode definitions");
+    STATIC_ASSERT(46 == ObjType_Num, "Check VNode definitions");
 
     if (type == ObjType_VNode_x86_64_pml4 ||
         type == ObjType_VNode_x86_64_pdpt ||
@@ -173,7 +173,7 @@ static inline size_t vnode_entry_bits(enum objtype type) {
 
 static inline enum objtype get_mapping_type(enum objtype captype)
 {
-    STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all mapping types");
+    STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all mapping types");
 
     switch (captype) {
         case ObjType_Frame:
@@ -212,7 +212,7 @@ static inline enum objtype get_mapping_type(enum objtype captype)
 
 static inline bool type_is_mapping(enum objtype type)
 {
-    STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all mapping types");
+    STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all mapping types");
 
     switch (type) {
         case ObjType_Frame_Mapping:
@@ -333,11 +333,30 @@ enum frame_cmd {
  */
 enum irqtable_cmd {
     IRQTableCmd_Alloc,  ///< Allocate new vector (XXX: HACK: this is x86 specific)
+    IRQTableCmd_AllocDestCap,  ///< Allocate new dest capability (XXX: HACK: this is x86 specific)
     IRQTableCmd_Set,    ///< Set endpoint for IRQ# notifications
     IRQTableCmd_Delete  ///< Remove notification endpoint for IRQ#
 };
 
 /**
+ * IRQ Vector commands.
+ */
+
+enum irqdest_cmd {
+       IRQDestCmd_Connect,     ///< Connect this capability to a messaging channel
+       IRQDestCmd_GetVector ///< Return the local interrupt vector
+};
+
+/**
+ * IRQ Vector commands.
+ */
+
+enum irqsrc_cmd {
+    IRQSrcCmd_GetVector   ///< Return vector and controller saved in this cap.
+};
+
+
+/**
  * IO capability commands.
  */
 enum io_cmd {
index 356ebb8..b225156 100644 (file)
@@ -40,7 +40,7 @@ distcap_state_is_foreign(distcap_state_t state)
  * Predicates related to sharing capabilities
  */
 
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 static inline bool
 distcap_needs_locality(enum objtype type)
 {
@@ -87,7 +87,7 @@ distcap_needs_locality(enum objtype type)
     }
 }
 
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 static inline bool
 distcap_is_moveable(enum objtype type)
 {
index cd1caa1..f7dc3f7 100644 (file)
@@ -33,7 +33,8 @@ enum debug_message {
     DEBUG_GET_APIC_TICKS_PER_SEC,
     DEBUG_FEIGN_FRAME_CAP,
     DEBUG_TRACE_PMEM_CTRL,
-    DEBUG_GET_APIC_ID
+    DEBUG_GET_APIC_ID,
+    DEBUG_CREATE_IRQ_SRC_CAP
 };
 
 #endif //BARRELFISH_KPI_SYS_DEBUG_H
index 400cbd0..41fbacf 100644 (file)
@@ -88,7 +88,7 @@ typedef uint8_t       coreid_t;
 #define PRIxCOREID  PRIx8
 
 #ifndef MAX_COREID
-#define MAX_COREID  255 // limit of coreid_t type (see comment above)
+#define MAX_COREID  254 // limit of coreid_t type (see comment above)
 #endif
 
 /* node id type */
diff --git a/include/pci/pci_client_debug.h b/include/pci/pci_client_debug.h
new file mode 100644 (file)
index 0000000..687fd13
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef PCI_CLIENT_DEBUG_H
+#define PCI_CLIENT_DEBUG_H
+
+#if defined(PCI_LIB_DEBUG) || defined(GLOBAL_DEBUG)
+#define PCI_CLIENT_DEBUG(x...) printf("pci_client: " x)
+#else
+#define PCI_CLIENT_DEBUG(x...) ((void)0)
+#endif
+
+#endif
index b76904a..30f87d8 100644 (file)
@@ -1075,6 +1075,7 @@ static struct sysret handle_debug_syscall(int msg)
             retval.value = tsc_get_hz();
             break;
 
+#if !defined(__ARM_ARCH_7M__)
         /* XXX - not revision-independent. */
         case DEBUG_HARDWARE_GLOBAL_TIMER_LOW:
             retval.value = gt_read_low();
@@ -1083,6 +1084,7 @@ static struct sysret handle_debug_syscall(int msg)
         case DEBUG_HARDWARE_GLOBAL_TIMER_HIGH:
             retval.value = gt_read_high();
             break;
+#endif
 
         default:
             printk(LOG_ERR, "invalid sys_debug msg type %d\n", msg);
index 6e3ae91..fde3ecd 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * Copyright (c) 2009 - 2012 ETH Zurich.
+ * Copyright (c) 2009 - 2012, 2016 ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
  * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
  */
 
 #include <kernel.h>
@@ -15,6 +15,7 @@
 #include <arm_hal.h>
 #include <cap_predicates.h>
 #include <dispatch.h>
+#include <mdb/mdb_tree.h>
 #include <dev/omap/omap44xx_mmu_dev.h>
 #include <omap44xx_map.h>
 
@@ -303,7 +304,8 @@ caps_map_l1(struct capability* dest,
             struct capability* src,
             uintptr_t          kpi_paging_flags,
             uintptr_t          offset,
-            uintptr_t          pte_count)
+            uintptr_t          pte_count,
+            struct cte*        mapping_cte)
 {
     //
     // Note:
@@ -354,10 +356,9 @@ caps_map_l1(struct capability* dest,
     assert(aligned(src_lpaddr, 1u << 10));
     assert((src_lpaddr < dest_lpaddr) || (src_lpaddr >= dest_lpaddr + 16384));
 
-    struct cte *src_cte = cte_for_cap(src);
-    src_cte->mapping_info.pte_count = pte_count;
-    src_cte->mapping_info.pte = dest_lpaddr + (slot * ARM_L1_SCALE);
-    src_cte->mapping_info.offset = 0;
+    create_mapping_cap(mapping_cte, src,
+                       dest_lpaddr + slot * sizeof(union arm_l1_entry),
+                       pte_count);
 
     for (int i = 0; i < 4; i++, entry++)
     {
@@ -381,7 +382,8 @@ caps_map_l2(struct capability* dest,
             struct capability* src,
             uintptr_t          kpi_paging_flags,
             uintptr_t          offset,
-            uintptr_t          pte_count)
+            uintptr_t          pte_count,
+            struct cte*        mapping_cte)
 {
     assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK));
 
@@ -423,10 +425,9 @@ caps_map_l2(struct capability* dest,
         panic("Invalid target");
     }
 
-    struct cte *src_cte = cte_for_cap(src);
-    src_cte->mapping_info.pte_count = pte_count;
-    src_cte->mapping_info.pte = dest_lpaddr;
-    src_cte->mapping_info.offset = offset;
+    create_mapping_cap(mapping_cte, src,
+                       dest_lpaddr + slot * sizeof(union arm_l2_entry),
+                       pte_count);
 
     for (int i = 0; i < pte_count; i++) {
         entry->raw = 0;
@@ -435,10 +436,10 @@ caps_map_l2(struct capability* dest,
         paging_set_flags(entry, kpi_paging_flags);
         entry->small_page.base_address = (src_lpaddr + i * BYTES_PER_PAGE) >> 12;
 
-        entry++;
-
         debug(SUBSYS_PAGING, "L2 mapping %08"PRIxLVADDR"[%"PRIuCSLOT"] @%p = %08"PRIx32"\n",
                dest_lvaddr, slot, entry, entry->raw);
+
+        entry++;
     }
 
     // Flush TLB if remapping.
@@ -450,34 +451,50 @@ caps_map_l2(struct capability* dest,
 /// Create page mappings
 errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
                             struct cte *src_cte, uintptr_t flags,
-                            uintptr_t offset, uintptr_t pte_count)
+                            uintptr_t offset, uintptr_t pte_count,
+                            struct cte *mapping_cte)
 {
     struct capability *src_cap  = &src_cte->cap;
     struct capability *dest_cap = &dest_vnode_cte->cap;
-
-    if (src_cte->mapping_info.pte) {
-        return SYS_ERR_VM_ALREADY_MAPPED;
-    }
+    assert(mapping_cte->cap.type == ObjType_Null);
+    errval_t err;
 
     if (ObjType_VNode_ARM_l1 == dest_cap->type) {
         //printf("caps_map_l1: %zu\n", (size_t)pte_count);
-        return caps_map_l1(dest_cap, dest_slot, src_cap,
+        err = caps_map_l1(dest_cap, dest_slot, src_cap,
                            flags,
                            offset,
-                           pte_count
+                           pte_count,
+                           mapping_cte
                           );
     }
     else if (ObjType_VNode_ARM_l2 == dest_cap->type) {
         //printf("caps_map_l2: %zu\n", (size_t)pte_count);
-        return caps_map_l2(dest_cap, dest_slot, src_cap,
+        err = caps_map_l2(dest_cap, dest_slot, src_cap,
                            flags,
                            offset,
-                           pte_count
+                           pte_count,
+                           mapping_cte
                           );
     }
     else {
         panic("ObjType not VNode");
     }
+
+    if (err_is_fail(err)) {
+        memset(mapping_cte, 0, sizeof(*mapping_cte));
+        return err;
+    }
+
+    assert(type_is_mapping(mapping_cte->cap.type));
+    err = mdb_insert(mapping_cte);
+    if (err_is_fail(err)) {
+        printk(LOG_ERR, "%s: mdb_insert: %"PRIuERRV"\n", __FUNCTION__, err);
+    }
+
+    TRACE_CAP_MSG("created", mapping_cte);
+
+    return err;
 }
 
 size_t do_unmap(lvaddr_t pt, cslot_t slot, size_t num_pages)
@@ -491,94 +508,19 @@ size_t do_unmap(lvaddr_t pt, cslot_t slot, size_t num_pages)
     return unmapped_pages;
 }
 
-static inline void read_pt_entry(struct capability *pgtable, size_t slot, genpaddr_t *paddr)
-{
-    assert(type_is_vnode(pgtable->type));
-    assert(paddr);
-
-    genpaddr_t gp = get_address(pgtable);
-    lpaddr_t lp = gen_phys_to_local_phys(gp);
-    lvaddr_t lv = local_phys_to_mem(lp);
-
-    switch (pgtable->type) {
-        case ObjType_VNode_ARM_l1:
-        {
-            union arm_l1_entry *e = (union arm_l1_entry*)lv;
-            *paddr = (genpaddr_t)(e->page_table.base_address) << 10;
-            return;
-        }
-        case ObjType_VNode_ARM_l2:
-        {
-            union arm_l2_entry *e = (union arm_l2_entry*)lv;
-            *paddr = (genpaddr_t)(e->small_page.base_address) << 12;
-            return;
-        }
-        default:
-            assert(!"Should not get here");
-    }
-}
-
-errval_t page_mappings_unmap(struct capability *pgtable, struct cte *mapping, size_t slot, size_t num_pages)
-{
-    assert(type_is_vnode(pgtable->type));
-    //printf("page_mappings_unmap(%zd pages, slot = %zd)\n", num_pages, slot);
-
-    // get page table entry data
-    genpaddr_t paddr;
-    //lpaddr_t pte;
-    read_pt_entry(pgtable, slot, &paddr);
-    lvaddr_t pt = local_phys_to_mem(gen_phys_to_local_phys(get_address(pgtable)));
-
-    // get virtual address of first page
-    // TODO: error checking
-    genvaddr_t vaddr;
-    struct cte *leaf_pt = cte_for_cap(pgtable);
-    compile_vaddr(leaf_pt, slot, &vaddr);
-    //genvaddr_t vend = vaddr + num_pages * BASE_PAGE_SIZE;
-    // printf("vaddr = 0x%"PRIxGENVADDR"\n", vaddr);
-    // printf("num_pages = %zu\n", num_pages);
-
-    // get cap for mapping
-    /*
-    struct cte *mem;
-    errval_t err = lookup_cap_for_mapping(paddr, pte, &mem);
-    if (err_is_fail(err)) {
-        printf("page_mappings_unmap: %ld\n", err);
-        return err;
-    }
-    */
-    //printf("state before unmap: mapped_pages = %zd\n", mem->mapping_info.mapped_pages);
-    //printf("state before unmap: num_pages    = %zd\n", num_pages);
-
-    if (num_pages != mapping->mapping_info.pte_count) {
-        printf("num_pages = %zu, mapping = %zu\n", num_pages, mapping->mapping_info.pte_count);
-        // want to unmap a different amount of pages than was mapped
-        return SYS_ERR_VM_MAP_SIZE;
-    }
-
-    do_unmap(pt, slot, num_pages);
-
-    // flush TLB for unmapped pages
-    // TODO: selective TLB flush
-    do_full_tlb_flush();
-
-    // update mapping info
-    memset(&mapping->mapping_info, 0, sizeof(struct mapping_info));
-
-    return SYS_ERR_OK;
-}
-
-errval_t paging_modify_flags(struct capability *frame, uintptr_t offset,
+errval_t paging_modify_flags(struct capability *mapping, uintptr_t offset,
                              uintptr_t pages, uintptr_t kpi_paging_flags)
 {
+    // XXX: modify flags for sections?
+    assert(type_is_mapping(mapping->type));
     // we currently ignore all permission flags
 //    assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK));
 
-    struct cte *mapping = cte_for_cap(frame);
-    struct mapping_info *info = &mapping->mapping_info;
+    struct Frame_Mapping *info = &mapping->u.frame_mapping;
 
     /* Calculate location of page table entries we need to modify */
-    lvaddr_t base = local_phys_to_mem(info->pte) + offset;
+    lvaddr_t base = local_phys_to_mem(info->pte) +
+        offset * sizeof(union arm_l2_entry);
 
     for (int i = 0; i < pages; i++) {
         union arm_l2_entry *entry =
@@ -586,12 +528,16 @@ errval_t paging_modify_flags(struct capability *frame, uintptr_t offset,
         paging_set_flags(entry, kpi_paging_flags);
     }
 
-    return paging_tlb_flush_range(mapping, offset, pages);
+    return paging_tlb_flush_range(cte_for_cap(mapping), offset, pages);
 }
 
 void paging_dump_tables(struct dcb *dispatcher)
 {
-    printf("dump_hw_page_tables\n");
+    if (!local_phys_is_valid(dispatcher->vspace)) {
+        printk(LOG_ERR, "dispatcher->vspace = 0x%"PRIxLPADDR": too high!\n" ,
+               dispatcher->vspace);
+        return;
+    }
     lvaddr_t l1 = local_phys_to_mem(dispatcher->vspace);
 
     for (int l1_index = 0; l1_index < ARM_L1_MAX_ENTRIES; l1_index++) {
index 07a909d..8330d0b 100644 (file)
@@ -347,6 +347,14 @@ static struct gate_descriptor idt[NIDT] __attribute__ ((aligned (16)));
 /// System call entry point
 void syscall_entry(void);
 
+static inline bool bitmap_get(uint8_t * bitmap, int idx){
+    return (bitmap[idx/8] >> (idx % 8)) & 1;
+}
+
+static inline void bitmap_set_true(uint8_t * bitmap, int idx){
+    bitmap[idx/8] |= (1 << (idx % 8));
+}
+
 /**
  * \brief Send interrupt notification to user-space listener.
  *
@@ -435,52 +443,125 @@ errval_t irq_table_alloc(int *outvec)
     }
 }
 
-errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
 {
+    // This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
     errval_t err;
-    struct cte *recv;
+    struct cte out_cap;
+    memset(&out_cap, 0, sizeof(struct cte));
+
+    out_cap.cap.type = ObjType_IRQSrc;
+    out_cap.cap.u.irqsrc.vector = gsi;
+    const uint32_t ioapic_controller_id = 1000;
+    out_cap.cap.u.irqsrc.controller = ioapic_controller_id;
+
+    struct cte * cn;
+    err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
+    if(err_is_fail(err)){
+        return err;
+    }
+    err = caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+    if(err_is_fail(err)){
+        return err;
+    }
+
+    return SYS_ERR_OK;
+}
 
-    err = caps_lookup_slot(&dcb_current->cspace.cap, endpoint,
-                           CPTR_BITS, &recv, CAPRIGHTS_WRITE);
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr)
+{
+    errval_t err;
+
+    int i;
+    bool i_usable = false;
+    for (i = 0; i < NDISPATCH; i++) {
+        i_usable = true;
+        //Iterate over all kcbs
+        struct kcb *k = kcb_current;
+        do {
+            if(bitmap_get(k->irq_in_use, i)){
+                i_usable = false;
+                break;
+            }
+            k = k->next;
+        } while (k && k != kcb_current);
+        if(i_usable) break; // Skip increment
+    }
+
+    if (i == NDISPATCH) {
+        return SYS_ERR_IRQ_NO_FREE_VECTOR;
+    } else {
+        struct cte out_cap;
+        memset(&out_cap, 0, sizeof(struct cte));
+        bitmap_set_true(kcb_current->irq_in_use, i);
+
+        out_cap.cap.type = ObjType_IRQDest;
+        out_cap.cap.u.irqdest.controller = my_core_id;
+        out_cap.cap.u.irqdest.vector = i;
+
+        struct cte * cn;
+        err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
+        if(err_is_fail(err)){
+            return err;
+        }
+
+        caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+        //printk(LOG_NOTE, "irq: Allocated cap for vec: %d\n", i);
+        return SYS_ERR_OK;
+    }
+}
+
+errval_t irq_connect(struct capability *dest_cap, capaddr_t endpoint_adr)
+{
+    errval_t err;
+    struct cte *endpoint;
+
+    // Lookup & check message endpoint cap
+    err = caps_lookup_slot(&dcb_current->cspace.cap, endpoint_adr,
+                           CPTR_BITS, &endpoint, CAPRIGHTS_WRITE);
     if (err_is_fail(err)) {
-        return err_push(err, SYS_ERR_IRQ_LOOKUP);
+        return err_push(err, SYS_ERR_IRQ_LOOKUP_EP);
     }
 
-    assert(recv != NULL);
+    assert(endpoint != NULL);
 
     // Return w/error if cap is not an endpoint
-    if(recv->cap.type != ObjType_EndPoint) {
+    if(endpoint->cap.type != ObjType_EndPoint) {
         return SYS_ERR_IRQ_NOT_ENDPOINT;
     }
 
     // Return w/error if no listener on endpoint
-    if(recv->cap.u.endpoint.listener == NULL) {
+    if(endpoint->cap.u.endpoint.listener == NULL) {
         return SYS_ERR_IRQ_NO_LISTENER;
     }
 
-    if(nidt < NDISPATCH) {
-        // check that we don't overwrite someone else's handler
-        if (kcb_current->irq_dispatch[nidt].cap.type != ObjType_Null) {
-            printf("kernel: installing new handler for IRQ %d\n", nidt);
-        }
-        err = caps_copy_to_cte(&kcb_current->irq_dispatch[nidt], recv, false, 0, 0);
-        if (err_is_fail(err)) {
-            printf("caps copy to cte failed");
-        }
-        return err;
-    } else {
-        return SYS_ERR_IRQ_INVALID;
+    assert(dest_cap->type == ObjType_IRQDest);
+    if(dest_cap->u.irqdest.controller != my_core_id){
+        return SYS_ERR_IRQ_WRONG_CONTROLLER;
     }
+
+    uint64_t dest_vec = dest_cap->u.irqdest.vector;
+    assert(kcb_current->irq_dispatch[dest_vec].cap.type == ObjType_Null);
+    caps_copy_to_cte(&kcb_current->irq_dispatch[dest_vec],
+            endpoint,0,0,0);
+
+    //printk(LOG_NOTE, "irq: connected vec: %"PRIu64"\n", dest_vec);
+    return SYS_ERR_OK;
+}
+
+/**
+ * Deprecated. Use capabilities.
+ */
+errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
+{
+    printk(LOG_ERR, "Used deprecated irq_table_set. Not setting interrupt\n");
+    return SYS_ERR_IRQ_INVALID;
 }
 
 errval_t irq_table_delete(unsigned int nidt)
 {
-    if(nidt < NDISPATCH) {
-        kcb_current->irq_dispatch[nidt].cap.type = ObjType_Null;
-        return SYS_ERR_OK;
-    } else {
-        return SYS_ERR_IRQ_INVALID;
-    }
+    printk(LOG_ERR, "Used deprecated irq_table_delete. Not setting interrupt\n");
+    return SYS_ERR_IRQ_INVALID;
 }
 
 errval_t irq_table_notify_domains(struct kcb *kcb)
index 6576b33..3f0a567 100644 (file)
@@ -629,6 +629,32 @@ static struct sysret handle_trace_setup(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
+static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
+        uintptr_t *args)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqsrc.vector;
+    return ret;
+
+}
+
+
+static struct sysret handle_irqdest_get_vector(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqdest.vector;
+    return ret;
+}
+
+static struct sysret handle_irqdest_connect(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    return SYSRET(irq_connect(to, args[0]));
+}
+
 static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
                                             uintptr_t *args)
 {
@@ -639,6 +665,12 @@ static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
     return ret;
 }
 
+static struct sysret handle_irq_table_alloc_dest_cap(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2]));
+}
+
 static struct sysret handle_irq_table_set(struct capability *to, int cmd, uintptr_t *args)
 {
     return SYSRET(irq_table_set(args[0], args[1]));
@@ -877,8 +909,16 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [IPICmd_Send_Start] = kernel_send_start_ipi,
         [IPICmd_Send_Init] = kernel_send_init_ipi,
     },
+    [ObjType_IRQDest] = {
+        [IRQDestCmd_Connect] = handle_irqdest_connect,
+        [IRQDestCmd_GetVector] = handle_irqdest_get_vector
+    },
+    [ObjType_IRQSrc] = {
+        [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
+    },
     [ObjType_IRQTable] = {
         [IRQTableCmd_Alloc] = handle_irq_table_alloc,
+        [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
         [IRQTableCmd_Set] = handle_irq_table_set,
         [IRQTableCmd_Delete] = handle_irq_table_delete
     },
index 28a593a..6bfafb7 100644 (file)
@@ -68,6 +68,7 @@
 #include <barrelfish_kpi/cpu_arch.h>
 #include <kcb.h>
 #include <mdb/mdb_tree.h>
+#include <sys_debug.h>
 
 #include <dev/ia32_dev.h>
 
@@ -403,6 +404,15 @@ static int timer_fired = 0;
 #endif // CONFIG_TRACE && NETWORK_STACK_TRACE
 
 
+static inline bool bitmap_get(uint8_t * bitmap, int idx){
+    return (bitmap[idx/8] >> (idx % 8)) & 1;
+}
+
+static inline void bitmap_set_true(uint8_t * bitmap, int idx){
+    bitmap[idx/8] |= (1 << (idx % 8));
+}
+
+
 /**
  * \brief Send interrupt notification to user-space listener.
  *
@@ -477,8 +487,12 @@ static void send_user_interrupt(int irq)
 #endif
 }
 
+/*
+ * This interface is deprecated. Use irq_table_alloc_dest_caps
+ */
 errval_t irq_table_alloc(int *outvec)
 {
+    printk(LOG_WARN, "irq_table_alloc is deprecated\n");
     assert(outvec);
     // XXX: this is O(#kcb*NDISPATCH)
     int i;
@@ -486,12 +500,12 @@ errval_t irq_table_alloc(int *outvec)
         struct kcb *k = kcb_current;
         bool found_free = true;
         do {
-            if (kcb_current->irq_dispatch[i].cap.type == ObjType_EndPoint) {
+            if (k->irq_dispatch[i].cap.type == ObjType_EndPoint) {
                 found_free = false;
                 break;
             }
-            k=k->next?k->next:k;
-        } while(k != kcb_current);
+            k = k->next;
+        } while(k && k != kcb_current);
         if (found_free) {
             break;
         }
@@ -505,49 +519,125 @@ errval_t irq_table_alloc(int *outvec)
     }
 }
 
-errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
 {
+    // This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
     errval_t err;
-    struct cte *recv;
+    struct cte out_cap;
+    memset(&out_cap, 0, sizeof(struct cte));
+
+    out_cap.cap.type = ObjType_IRQSrc;
+    out_cap.cap.u.irqsrc.vector = gsi;
+    const uint32_t ioapic_controller_id = 1000;
+    out_cap.cap.u.irqsrc.controller = ioapic_controller_id;
+
+    struct cte * cn;
+    err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
+    if(err_is_fail(err)){
+        return err;
+    }
+    err = caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+    if(err_is_fail(err)){
+        return err;
+    }
 
-    err = caps_lookup_slot(&dcb_current->cspace.cap, endpoint,
-                           CPTR_BITS, &recv, CAPRIGHTS_WRITE);
+    return SYS_ERR_OK;
+}
+
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr)
+{
+    errval_t err;
+
+    int i;
+    bool i_usable = false;
+    for (i = 0; i < NDISPATCH; i++) {
+        i_usable = true;
+        //Iterate over all kcbs
+        struct kcb *k = kcb_current;
+        do {
+            if(bitmap_get(k->irq_in_use, i)){
+                i_usable = false;
+                break;
+            }
+            k = k->next;
+        } while (k && k != kcb_current);
+        if(i_usable) break; // Skip increment
+    }
+
+    if (i == NDISPATCH) {
+        return SYS_ERR_IRQ_NO_FREE_VECTOR;
+    } else {
+        struct cte out_cap;
+        memset(&out_cap, 0, sizeof(struct cte));
+        bitmap_set_true(kcb_current->irq_in_use, i);
+
+        out_cap.cap.type = ObjType_IRQDest;
+        out_cap.cap.u.irqdest.controller = my_core_id;
+        out_cap.cap.u.irqdest.vector = i;
+
+        struct cte * cn;
+        err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
+        if(err_is_fail(err)){
+            return err;
+        }
+
+        caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+        //printk(LOG_NOTE, "irq: Allocated cap for vec: %d\n", i);
+        return SYS_ERR_OK;
+    }
+}
+
+errval_t irq_connect(struct capability *dest_cap, capaddr_t endpoint_adr)
+{
+    errval_t err;
+    struct cte *endpoint;
+
+    // Lookup & check message endpoint cap
+    err = caps_lookup_slot(&dcb_current->cspace.cap, endpoint_adr,
+                           CPTR_BITS, &endpoint, CAPRIGHTS_WRITE);
     if (err_is_fail(err)) {
-        return err_push(err, SYS_ERR_IRQ_LOOKUP);
+        return err_push(err, SYS_ERR_IRQ_LOOKUP_EP);
     }
 
-    assert(recv != NULL);
+    assert(endpoint != NULL);
 
     // Return w/error if cap is not an endpoint
-    if(recv->cap.type != ObjType_EndPoint) {
+    if(endpoint->cap.type != ObjType_EndPoint) {
         return SYS_ERR_IRQ_NOT_ENDPOINT;
     }
 
     // Return w/error if no listener on endpoint
-    if(recv->cap.u.endpoint.listener == NULL) {
+    if(endpoint->cap.u.endpoint.listener == NULL) {
         return SYS_ERR_IRQ_NO_LISTENER;
     }
 
-    if(nidt < NDISPATCH) {
-        // check that we don't overwrite someone else's handler
-        if (kcb_current->irq_dispatch[nidt].cap.type != ObjType_Null) {
-            printf("kernel: installing new handler for IRQ %d\n", nidt);
-        }
-        err = caps_copy_to_cte(&kcb_current->irq_dispatch[nidt], recv, false, 0, 0);
-        return err;
-    } else {
-        return SYS_ERR_IRQ_INVALID;
+    assert(dest_cap->type == ObjType_IRQDest);
+    if(dest_cap->u.irqdest.controller != my_core_id){
+        return SYS_ERR_IRQ_WRONG_CONTROLLER;
     }
+
+    uint64_t dest_vec = dest_cap->u.irqdest.vector;
+    assert(kcb_current->irq_dispatch[dest_vec].cap.type == ObjType_Null);
+    caps_copy_to_cte(&kcb_current->irq_dispatch[dest_vec],
+            endpoint,0,0,0);
+
+    //printk(LOG_NOTE, "irq: connected vec: %"PRIu64"\n", dest_vec);
+    return SYS_ERR_OK;
+}
+
+/**
+ * Deprecated. Use capabilities.
+ */
+errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint)
+{
+    printk(LOG_ERR, "Used deprecated irq_table_set. Not setting interrupt\n");
+    return SYS_ERR_IRQ_INVALID;
 }
 
 errval_t irq_table_delete(unsigned int nidt)
 {
-    if(nidt < NDISPATCH) {
-        kcb_current->irq_dispatch[nidt].cap.type = ObjType_Null;
-        return SYS_ERR_OK;
-    } else {
-        return SYS_ERR_IRQ_INVALID;
-    }
+    printk(LOG_ERR, "Used deprecated irq_table_delete. Not setting interrupt\n");
+    return SYS_ERR_IRQ_INVALID;
 }
 
 errval_t irq_table_notify_domains(struct kcb *kcb)
index ac71f7b..58884f9 100644 (file)
@@ -807,6 +807,32 @@ static struct sysret handle_trace_setup(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
+static struct sysret handle_irqsrc_get_vector(struct capability * to, int cmd,
+        uintptr_t *args)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqsrc.vector;
+    return ret;
+
+}
+
+
+static struct sysret handle_irqdest_get_vector(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irqdest.vector;
+    return ret;
+}
+
+static struct sysret handle_irqdest_connect(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    return SYSRET(irq_connect(to, args[0]));
+}
+
 static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
                                             uintptr_t *args)
 {
@@ -817,6 +843,12 @@ static struct sysret handle_irq_table_alloc(struct capability *to, int cmd,
     return ret;
 }
 
+static struct sysret handle_irq_table_alloc_dest_cap(struct capability *to, int cmd,
+                                            uintptr_t *args)
+{
+    return SYSRET(irq_table_alloc_dest_cap(args[0],args[1],args[2]));
+}
+
 
 static struct sysret handle_irq_table_set(struct capability *to, int cmd,
                                           uintptr_t *args)
@@ -1157,8 +1189,16 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [IPICmd_Send_Start] = kernel_send_start_ipi,
         [IPICmd_Send_Init] = kernel_send_init_ipi,
     },
+       [ObjType_IRQDest] = {
+        [IRQDestCmd_Connect] = handle_irqdest_connect,
+        [IRQDestCmd_GetVector] = handle_irqdest_get_vector
+       },
+       [ObjType_IRQSrc] = {
+        [IRQSrcCmd_GetVector] = handle_irqsrc_get_vector,
+       },
     [ObjType_IRQTable] = {
         [IRQTableCmd_Alloc] = handle_irq_table_alloc,
+        [IRQTableCmd_AllocDestCap] = handle_irq_table_alloc_dest_cap,
         [IRQTableCmd_Set] = handle_irq_table_set,
         [IRQTableCmd_Delete] = handle_irq_table_delete
     },
@@ -1327,6 +1367,8 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
             // Call the invocation
             invocation_handler_t invocation = invocations[to->type][cmd];
             if(invocation == NULL) {
+                printk(LOG_WARN, "invocation not found. type: %"PRIu32", cmd: %"PRIu64"\n",
+                              to->type, cmd);
                 retval.error = SYS_ERR_ILLEGAL_INVOCATION;
             } else {
                 retval = invocation(to, cmd, &args[1]);
@@ -1433,6 +1475,10 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
             retval.value = apic_get_id();
             break;
 
+        case DEBUG_CREATE_IRQ_SRC_CAP:
+            retval.error = irq_debug_create_src_cap(arg1, args[0], args[1], args[2]);
+            break;
+
         default:
             printk(LOG_ERR, "invalid sys_debug msg type\n");
         }
index 465ce6b..aefbaf6 100644 (file)
@@ -52,7 +52,7 @@ void caps_trace_ctrl(uint64_t types, genpaddr_t start, gensize_t size)
 
 struct capability monitor_ep;
 
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 int sprint_cap(char *buf, size_t len, struct capability *cap)
 {
     switch (cap->type) {
@@ -236,6 +236,10 @@ int sprint_cap(char *buf, size_t len, struct capability *cap)
     case ObjType_IRQTable:
         return snprintf(buf, len, "IRQTable cap");
 
+    case ObjType_IRQDest:
+        return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", ctrl: %"PRIu64")",
+                cap->u.irqdest.vector, cap->u.irqdest.controller);
+
     case ObjType_EndPoint:
         return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
                         cap->u.endpoint.listener, cap->u.endpoint.epoffset);
@@ -258,6 +262,9 @@ int sprint_cap(char *buf, size_t len, struct capability *cap)
     case ObjType_Null:
         return snprintf(buf, len, "Null capability (empty slot)");
 
+    case ObjType_IPI:
+        return snprintf(buf, len, "IPI cap");
+
     default:
         return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
     }
@@ -329,7 +336,7 @@ static errval_t set_cap(struct capability *dest, struct capability *src)
 
 // If you create more capability types you need to deal with them
 // in the table below.
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 
 static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
 {
@@ -388,6 +395,8 @@ static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
 
     case ObjType_Kernel:
     case ObjType_IRQTable:
+    case ObjType_IRQDest:
+    case ObjType_IRQSrc:
     case ObjType_IO:
     case ObjType_EndPoint:
     case ObjType_ID:
@@ -422,7 +431,7 @@ static size_t caps_numobjs(enum objtype type, uint8_t bits, uint8_t objbits)
  *
  * For the meaning of the parameters, see the 'caps_create' function.
  */
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 
 static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
                                   bits, uint8_t objbits, size_t numobjs)
@@ -502,7 +511,7 @@ static errval_t caps_init_objects(enum objtype type, lpaddr_t lpaddr, uint8_t
  */
 // If you create more capability types you need to deal with them
 // in the table below.
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 
 static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
                             uint8_t objbits, size_t numobjs, coreid_t owner,
@@ -984,6 +993,8 @@ static errval_t caps_create(enum objtype type, lpaddr_t lpaddr, uint8_t bits,
     case ObjType_Kernel:
     case ObjType_IPI:
     case ObjType_IRQTable:
+    case ObjType_IRQDest:
+    case ObjType_IRQSrc:
     case ObjType_EndPoint:
     case ObjType_Notify_RCK:
     case ObjType_Notify_IPI:
@@ -1269,7 +1280,7 @@ errval_t caps_create_new(enum objtype type, lpaddr_t addr, size_t bits,
 }
 
 
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 /// Retype caps
 errval_t caps_retype(enum objtype type, size_t objbits,
                      struct capability *dest_cnode, cslot_t dest_slot,
index c6efeb7..e215343 100644 (file)
@@ -167,6 +167,16 @@ static inline lvaddr_t local_phys_to_mem(lpaddr_t addr)
     return (lvaddr_t)(addr + ((lpaddr_t)MEMORY_OFFSET - (lpaddr_t)PHYS_MEMORY_START));
 }
 
+/**
+ * Checks whether absolute local physical address `addr` is valid.
+ * \param addr Absolute local physical address
+ * \return True iff addr is a valid local physical address
+ */
+static inline bool local_phys_is_valid(lpaddr_t addr)
+{
+    return addr < PHYS_MEMORY_START + PADDR_SPACE_LIMIT;
+}
+
 static inline lpaddr_t mem_to_local_phys(lvaddr_t addr)
 {
     assert(addr >= MEMORY_OFFSET);
index 3b89065..f9724cc 100644 (file)
@@ -23,6 +23,7 @@ struct capability;
 struct idc_recv_msg;
 //struct sysret irq_table_set(struct capability *to, struct idc_recv_msg *msg);
 //struct sysret irq_table_delete(struct capability *to, struct idc_recv_msg *msg);
+
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
 struct kcb;
index b6412e0..a2fcf4b 100644 (file)
@@ -210,10 +210,14 @@ struct task_state_segment {
 
 void setup_default_idt(void);
 
+errval_t irq_connect(struct capability *dest_cap, capaddr_t endpoint_adr);
 errval_t irq_table_alloc(int *outvec);
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
 struct kcb;
 errval_t irq_table_notify_domains(struct kcb *kcb);
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr);
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi);
+
 
 #endif
index 95801bf..1413a2a 100644 (file)
@@ -158,10 +158,13 @@ struct task_state_segment {
 
 void setup_default_idt(void);
 
+errval_t irq_connect(struct capability *dest_cap, capaddr_t endpoint_adr);
 errval_t irq_table_alloc(int *outvec);
 errval_t irq_table_set(unsigned int nidt, capaddr_t endpoint);
 errval_t irq_table_delete(unsigned int nidt);
 struct kcb;
 errval_t irq_table_notify_domains(struct kcb *kcb);
+errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr);
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi);
 
 #endif
index 3e873d8..b20c66a 100644 (file)
@@ -66,6 +66,7 @@ struct kcb {
     //driver whose kernel_now > this kcb's kernel_off.
     int64_t kernel_off;
 
+    uint8_t irq_in_use[NDISPATCH / 8]; // Bitmap of handed out caps.
     struct cte irq_dispatch[NDISPATCH];
     // TODO: maybe add a shared part which can replace struct core_data?
 };
index bb29ef1..fc85612 100644 (file)
@@ -27,6 +27,16 @@ errval_t sys_debug_get_tsc_per_ms(uint64_t *ret)
     return sr.error;
 }
 
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+{
+    uint8_t dcn_vbits = get_cnode_valid_bits(cap);
+    capaddr_t dcn_addr = get_cnode_addr(cap);
+
+    struct sysret sr = syscall6(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP, dcn_vbits, dcn_addr,
+        cap.slot, gsi);
+    return sr.error;
+}
+
 errval_t sys_debug_get_apic_id(uint8_t *ret)
 {
     struct sysret sr = syscall2(SYSCALL_DEBUG, DEBUG_GET_APIC_ID);
index 1ff4d09..41d3ea5 100644 (file)
@@ -128,7 +128,7 @@ void debug_printf(const char *fmt, ...)
 /**
  * \brief Function to do the actual printing based on the type of capability
  */
-STATIC_ASSERT(44 == ObjType_Num, "Knowledge of all cap types");
+STATIC_ASSERT(46 == ObjType_Num, "Knowledge of all cap types");
 int debug_print_cap(char *buf, size_t len, struct capability *cap)
 {
     switch (cap->type) {
@@ -309,9 +309,14 @@ int debug_print_cap(char *buf, size_t len, struct capability *cap)
                                   cap->u.vnode_aarch64_l3_mapping.pte,
                                   cap->u.vnode_aarch64_l3_mapping.pte_count);
 
+
     case ObjType_IRQTable:
         return snprintf(buf, len, "IRQTable cap");
 
+    case ObjType_IRQDest:
+        return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", ctrl: %"PRIu64")",
+                cap->u.irqdest.vector, cap->u.irqdest.controller);
+
     case ObjType_EndPoint:
         return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
                         cap->u.endpoint.listener, cap->u.endpoint.epoffset);
index d83cd7b..aa6ad22 100644 (file)
@@ -32,20 +32,19 @@ static errval_t arm_allocirq(struct capref ep, uint32_t irq)
     }
 }
 
-/* Allocate vector from local monitor */
-static errval_t allocirq(struct capref ep, uint32_t *retvector)
+
+/**
+ * Get a new irq destination capability for the current core using the monitor.
+ */
+errval_t alloc_dest_irq_cap(struct capref *retcap)
 {
     errval_t err, msgerr;
-    uint32_t vector;
 
     struct monitor_blocking_rpc_client *r = get_monitor_blocking_rpc_client();
-    err = r->vtbl.irq_handle(r, ep, &msgerr, &vector);
+    err = r->vtbl.get_irq_dest_cap(r, retcap, &msgerr);
     if (err_is_fail(err)){
         return err;
-    } else if (err_is_fail(msgerr)) {
-        return msgerr;
     } else {
-        *retvector = vector;
         return msgerr;
     }
 }
@@ -152,7 +151,64 @@ errval_t inthandler_setup_arm(interrupt_handler_fn handler, void *handler_arg,
 }
 
 /**
- * \brief Setup an interrupt handler function to receive device interrupts
+ * \brief Setup an interrupt handler function to receive device interrupts targeted at dest_cap
+ *
+ * \param dest_cap Capability to an interrupt line that targets the last level controller (such as local APIC)
+ * \param handler Handler function
+ * \param handler_arg Argument passed to #handler
+ */
+errval_t inthandler_setup_movable_cap(struct capref dest_cap, interrupt_handler_fn handler, void *handler_arg,
+                                  interrupt_handler_fn reloc_handler,
+                                  void *reloc_handler_arg)
+{
+    errval_t err;
+
+    if(barrelfish_interrupt_waitset == NULL) {
+        barrelfish_interrupt_waitset = get_default_waitset();
+    }
+
+    /* alloc state */
+    struct interrupt_handler_state *state;
+    state = malloc(sizeof(struct interrupt_handler_state));
+    assert(state != NULL);
+
+    state->handler = handler;
+    state->handler_arg = handler_arg;
+    state->reloc_handler = reloc_handler;
+    state->reloc_handler_arg = reloc_handler_arg;
+
+    /* create endpoint to handle interrupts */
+    struct capref epcap;
+
+    // use minimum-sized endpoint, because we don't need to buffer >1 interrupt
+    err = endpoint_create(LMP_RECV_LENGTH, &epcap, &state->idcep);
+    if (err_is_fail(err)) {
+        free(state);
+        return err_push(err, LIB_ERR_ENDPOINT_CREATE);
+    }
+
+    // register to receive on this endpoint
+    struct event_closure cl = {
+        .handler = generic_interrupt_handler,
+        .arg = state,
+    };
+    err = lmp_endpoint_register(state->idcep, barrelfish_interrupt_waitset, cl);
+    if (err_is_fail(err)) {
+        lmp_endpoint_free(state->idcep);
+        // TODO: release vector
+        free(state);
+        return err_push(err, LIB_ERR_LMP_ENDPOINT_REGISTER);
+    }
+
+    // Connect dest_cap with endpoint
+    invoke_irqdest_connect(dest_cap, epcap);
+
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief Deprecated. inthandler_setup_moveable_cap Setup an interrupt handler function to receive device interrupts.
  *
  * \param handler Handler function
  * \param handler_arg Argument passed to #handler
@@ -180,7 +236,15 @@ errval_t inthandler_setup_movable(interrupt_handler_fn handler, void *handler_ar
     state->reloc_handler = reloc_handler;
     state->reloc_handler_arg = reloc_handler_arg;
 
-    /* create endpoint to handle interrupts */
+    // Get irq_dest_cap from monitor
+    struct capref irq_dest_cap;
+    err = alloc_dest_irq_cap(&irq_dest_cap);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "Could not allocate dest irq cap");
+        return err;
+    }
+
+    // create endpoint to handle interrupts
     struct capref epcap;
 
     // use minimum-sized endpoint, because we don't need to buffer >1 interrupt
@@ -190,9 +254,15 @@ errval_t inthandler_setup_movable(interrupt_handler_fn handler, void *handler_ar
         return err_push(err, LIB_ERR_ENDPOINT_CREATE);
     }
 
-    // allocate a local interrupt vector for this endpoint
-    err = allocirq(epcap, ret_vector);
+    err = invoke_irqdest_connect(irq_dest_cap, epcap);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "Could not connect irq_cap and endpoint");
+        return err;
+    }
+
+    err = invoke_irqdest_get_vector(irq_dest_cap, ret_vector);
     if (err_is_fail(err)) {
+        DEBUG_ERR(err, "Could not lookup irq vector");
         return err;
     }
 
@@ -215,5 +285,6 @@ errval_t inthandler_setup_movable(interrupt_handler_fn handler, void *handler_ar
 errval_t inthandler_setup(interrupt_handler_fn handler, void *handler_arg,
                           uint32_t *ret_vector)
 {
+
     return inthandler_setup_movable(handler, handler_arg, NULL, NULL, ret_vector);
 }
index 3ad7b14..40358a1 100644 (file)
@@ -133,7 +133,7 @@ static inline int e10k_queue_add_txbuf_ctx(e10k_queue_t* q, uint64_t phys,
     e10k_q_tdesc_adv_rd_ifcs_insert(d, 1);
     e10k_q_tdesc_adv_rd_eop_insert(d, last);
 
-    if (ctx != -1U) {
+    if (ctx != (uint8_t)-1) {
         e10k_q_tdesc_adv_rd_idx_insert(d, ctx);
         e10k_q_tdesc_adv_rd_cc_insert(d, 1);
         e10k_q_tdesc_adv_rd_ixsm_insert(d, ixsm);
diff --git a/lib/compiler-rt/Hakefile b/lib/compiler-rt/Hakefile
deleted file mode 100644 (file)
index 972459e..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
---------------------------------------------------------------------------
--- Copyright (c) 2016, ETH Zurich.
--- All rights reserved.
---
--- This file is distributed under the terms in the attached LICENSE file.
--- If you do not find this file, copies can be found by writing to:
--- ETH Zurich D-INFK, Universitaetstrasse 4, CH-8092 Zurich. Attn: Systems Group.
---
--- Hakefile for /lib/compiler-rt
---
---------------------------------------------------------------------------
-
-let
-  builtins_dir = "lib/builtins/"
-  builtins_generic = [ builtins_dir ++ x | x <- [
-    "absvdi2.c",
-    "absvsi2.c",
-    "absvti2.c",
-    "adddf3.c",
-    "addsf3.c",
-    "addtf3.c",
-    "addvdi3.c",
-    "addvsi3.c",
-    "addvti3.c",
-    "apple_versioning.c",
-    "ashldi3.c",
-    "ashlti3.c",
-    "ashrdi3.c",
-    "ashrti3.c",
-    -- FIXME: atomic.c may only be compiled if host compiler understands _Atomic
-    -- atomic.c
-    "clear_cache.c",
-    "clzdi2.c",
-    "clzsi2.c",
-    "clzti2.c",
-    "cmpdi2.c",
-    "cmpti2.c",
-    "comparedf2.c",
-    "comparesf2.c",
-    "ctzdi2.c",
-    "ctzsi2.c",
-    "ctzti2.c",
-    "divdc3.c",
-    "divdf3.c",
-    "divdi3.c",
-    "divmoddi4.c",
-    "divmodsi4.c",
-    "divsc3.c",
-    "divsf3.c",
-    "divsi3.c",
-    -- GCC complains that __divtc3 has conflicting types with built-in __divtc3
-    -- "divtc3.c",
-    "divti3.c",
-    "divtf3.c",
-    "divxc3.c",
-    "enable_execute_stack.c",
-    -- "eprintf.c",
-    "extendsfdf2.c",
-    "extendhfsf2.c",
-    "ffsdi2.c",
-    "ffsti2.c",
-    "fixdfdi.c",
-    "fixdfsi.c",
-    "fixdfti.c",
-    "fixsfdi.c",
-    "fixsfsi.c",
-    "fixsfti.c",
-    "fixunsdfdi.c",
-    "fixunsdfsi.c",
-    "fixunsdfti.c",
-    "fixunssfdi.c",
-    "fixunssfsi.c",
-    "fixunssfti.c",
-    "fixunsxfdi.c",
-    "fixunsxfsi.c",
-    "fixunsxfti.c",
-    "fixxfdi.c",
-    "fixxfti.c",
-    "floatdidf.c",
-    "floatdisf.c",
-    "floatdixf.c",
-    "floatsidf.c",
-    "floatsisf.c",
-    "floattidf.c",
-    "floattisf.c",
-    "floattixf.c",
-    "floatundidf.c",
-    "floatundisf.c",
-    "floatundixf.c",
-    "floatunsidf.c",
-    "floatunsisf.c",
-    "floatuntidf.c",
-    "floatuntisf.c",
-    "floatuntixf.c",
-    "int_util.c",
-    "lshrdi3.c",
-    "lshrti3.c",
-    "moddi3.c",
-    "modsi3.c",
-    "modti3.c",
-    "muldc3.c",
-    "muldf3.c",
-    "muldi3.c",
-    "mulodi4.c",
-    "mulosi4.c",
-    "muloti4.c",
-    "mulsc3.c",
-    "mulsf3.c",
-    "multi3.c",
-    "multf3.c",
-    "mulvdi3.c",
-    "mulvsi3.c",
-    "mulvti3.c",
-    "mulxc3.c",
-    "negdf2.c",
-    "negdi2.c",
-    "negsf2.c",
-    "negti2.c",
-    "negvdi2.c",
-    "negvsi2.c",
-    "negvti2.c",
-    "paritydi2.c",
-    "paritysi2.c",
-    "parityti2.c",
-    "popcountdi2.c",
-    "popcountsi2.c",
-    "popcountti2.c",
-    "powidf2.c",
-    "powisf2.c",
-    "powitf2.c",
-    "powixf2.c",
-    "subdf3.c",
-    "subsf3.c",
-    "subvdi3.c",
-    "subvsi3.c",
-    "subvti3.c",
-    "subtf3.c",
-    "trampoline_setup.c",
-    "truncdfhf2.c",
-    "truncdfsf2.c",
-    "truncsfhf2.c",
-    "ucmpdi2.c",
-    "ucmpti2.c",
-    "udivdi3.c",
-    "udivmoddi4.c",
-    "udivmodsi4.c",
-    "udivmodti4.c",
-    "udivsi3.c",
-    "udivti3.c",
-    "umoddi3.c",
-    "umodsi3.c",
-    "umodti3.c" ] ]
-
-  builtins_asm_arch arch = case arch of
-    "x86_32" -> [ builtins_dir ++ x | x <- [
-        "i386/ashldi3.S",
-        "i386/ashrdi3.S",
-        "i386/chkstk.S",
-        "i386/chkstk2.S",
-        "i386/divdi3.S",
-        "i386/floatdidf.S",
-        "i386/floatdisf.S",
-        "i386/floatdixf.S",
-        "i386/floatundidf.S",
-        "i386/floatundisf.S",
-        "i386/floatundixf.S",
-        "i386/lshrdi3.S",
-        "i386/moddi3.S",
-        "i386/muldi3.S",
-        "i386/udivdi3.S",
-        "i386/umoddi3.S" ] ]
-    "x86_64" -> [ builtins_dir ++ x | x <- [
-        "x86_64/chkstk.S",
-        "x86_64/chkstk2.S",
-        "x86_64/floatundidf.S",
-        "x86_64/floatundisf.S",
-        "x86_64/floatundixf.S" ] ]
-    "k1om" -> builtins_asm_arch "x86_64"
-    "armv5" -> [ builtins_dir ++ x | x <- [
--- compiler-rt: *vfp: designed for Thumb1 CPUs with VFPv2
---        "arm/adddf3vfp.S",
---        "arm/addsf3vfp.S",
-        "arm/aeabi_cdcmp.S",
-        "arm/aeabi_cfcmp.S",
-        "arm/aeabi_dcmp.S",
-        "arm/aeabi_fcmp.S",
-        "arm/aeabi_idivmod.S",
-        "arm/aeabi_ldivmod.S",
-        "arm/aeabi_memcmp.S",
-        "arm/aeabi_memcpy.S",
-        "arm/aeabi_memmove.S",
-        "arm/aeabi_memset.S",
-        "arm/aeabi_uidivmod.S",
-        "arm/aeabi_uldivmod.S",
-        "arm/bswapdi2.S",
-        "arm/bswapsi2.S",
-        "arm/clzdi2.S",
-        "arm/clzsi2.S",
-        "arm/comparesf2.S",
---        "arm/divdf3vfp.S",
-        "arm/divmodsi4.S",
---        "arm/divsf3vfp.S",
-        "arm/divsi3.S",
---        "arm/eqdf2vfp.S",
---        "arm/eqsf2vfp.S",
---        "arm/extendsfdf2vfp.S",
---        "arm/fixdfsivfp.S",
---        "arm/fixsfsivfp.S",
---        "arm/fixunsdfsivfp.S",
---        "arm/fixunssfsivfp.S",
---        "arm/floatsidfvfp.S",
---        "arm/floatsisfvfp.S",
---        "arm/floatunssidfvfp.S",
---        "arm/floatunssisfvfp.S",
---        "arm/gedf2vfp.S",
---        "arm/gesf2vfp.S",
---        "arm/gtdf2vfp.S",
---        "arm/gtsf2vfp.S",
---        "arm/ledf2vfp.S",
---        "arm/lesf2vfp.S",
---        "arm/ltdf2vfp.S",
---        "arm/ltsf2vfp.S",
-        "arm/modsi3.S",
---        "arm/muldf3vfp.S",
---        "arm/mulsf3vfp.S",
---        "arm/nedf2vfp.S",
---        "arm/negdf2vfp.S",
---        "arm/negsf2vfp.S",
---        "arm/nesf2vfp.S",
---        "arm/restore_vfp_d8_d15_regs.S",
---        "arm/save_vfp_d8_d15_regs.S",
---        "arm/subdf3vfp.S",
---        "arm/subsf3vfp.S",
-        "arm/switch16.S",
-        "arm/switch32.S",
-        "arm/switch8.S",
-        "arm/switchu8.S",
-        "arm/sync_fetch_and_add_4.S",
-        "arm/sync_fetch_and_add_8.S",
-        "arm/sync_fetch_and_and_4.S",
-        "arm/sync_fetch_and_and_8.S",
-        "arm/sync_fetch_and_max_4.S",
-        "arm/sync_fetch_and_max_8.S",
-        "arm/sync_fetch_and_min_4.S",
-        "arm/sync_fetch_and_min_8.S",
-        "arm/sync_fetch_and_nand_4.S",
-        "arm/sync_fetch_and_nand_8.S",
-        "arm/sync_fetch_and_or_4.S",
-        "arm/sync_fetch_and_or_8.S",
-        "arm/sync_fetch_and_sub_4.S",
-        "arm/sync_fetch_and_sub_8.S",
-        "arm/sync_fetch_and_umax_4.S",
-        "arm/sync_fetch_and_umax_8.S",
-        "arm/sync_fetch_and_umin_4.S",
-        "arm/sync_fetch_and_umin_8.S",
-        "arm/sync_fetch_and_xor_4.S",
-        "arm/sync_fetch_and_xor_8.S",
-        "arm/sync_synchronize.S",
---        "arm/truncdfsf2vfp.S",
-        "arm/udivmodsi4.S",
-        "arm/udivsi3.S",
-        "arm/umodsi3.S" --,
---        "arm/unorddf2vfp.S",
---        "arm/unordsf2vfp.S"
-        ] ]
-    "armv7" -> builtins_asm_arch "armv5"
-    "armv7-m" -> builtins_asm_arch "armv5"
-    "armv8" -> [ ]
-    "xscale" -> [ ]
-    x -> error ("Unknown architecture for compiler-rt: " ++ x)
-
-  builtins_c_arch arch = case arch of
-    "x86_32" -> [ ]
-    "x86_64" -> [ builtins_dir ++ x | x <- [
-        "x86_64/floatdidf.c",
-        "x86_64/floatdisf.c",
-        "x86_64/floatdixf.c" ] ]
-    "k1om" -> builtins_c_arch "x86_64"
-    "armv5" -> [ builtins_dir ++ x | x <- [
-        "arm/aeabi_cdcmpeq_check_nan.c",
-        "arm/aeabi_cfcmpeq_check_nan.c",
-        "arm/aeabi_div0.c",
-        "arm/aeabi_drsub.c",
-        "arm/aeabi_frsub.c" ] ]
-    "armv7" -> builtins_c_arch "armv5"
-    "armv7-m" -> builtins_c_arch "armv5"
-    "armv8" -> [ builtins_dir ++ x | x <- [
-        "comparetf2.c",
-        "extenddftf2.c",
-        "extendsftf2.c",
-        "fixtfdi.c",
-        "fixtfsi.c",
-        "fixtfti.c",
-        "fixunstfdi.c",
-        "fixunstfsi.c",
-        "fixunstfti.c",
-        "floatditf.c",
-        "floatsitf.c",
-        "floatunditf.c",
-        "floatunsitf.c",
-        "multc3.c",
-        "trunctfdf2.c",
-        "trunctfsf2.c" ] ]
-    "xscale" -> [ ]
-    x -> error ("Unknown architecture for compiler-rt: " ++ x)
-
-  builtins_unittest_dir = "test/builtins/Unit/"
-  builtins_unittest_files = [
-    "absvdi2_test.c",
-    "absvsi2_test.c",
-    "absvti2_test.c",
-    "adddf3vfp_test.c",
-    "addsf3vfp_test.c",
-    "addtf3_test.c",
-    "addvdi3_test.c",
-    "addvsi3_test.c",
-    "addvti3_test.c",
-    "ashldi3_test.c",
-    "ashlti3_test.c",
-    "ashrdi3_test.c",
-    "ashrti3_test.c",
-    "bswapdi2_test.c",
-    "bswapsi2_test.c",
-    -- "clear_cache_test.c", -- requires mprotect
-    "clzdi2_test.c",
-    "clzsi2_test.c",
-    "clzti2_test.c",
-    "cmpdi2_test.c",
-    "cmpti2_test.c",
-    "comparedf2_test.c",
-    "comparesf2_test.c",
-    "ctzdi2_test.c",
-    "ctzsi2_test.c",
-    "ctzti2_test.c",
-    "divdc3_test.c",
-    "divdf3vfp_test.c",
-    "divdi3_test.c",
-    "divmodsi4_test.c",
-    "divsc3_test.c",
-    "divsf3vfp_test.c",
-    "divsi3_test.c",
-    -- "divtc3_test.c",
-    "divtf3_test.c",
-    "divti3_test.c",
-    "divxc3_test.c",
-    -- "enable_execute_stack_test.c", -- requires mprotect
-    "eqdf2vfp_test.c",
-    "eqsf2vfp_test.c",
-    "eqtf2_test.c",
-    "extebdsfdf2vfp_test.c",
-    "extenddftf2_test.c",
-    -- "extendhfsf2_test.c", -- requires __fp16 type
-    "extendsftf2_test.c",
-    "ffsdi2_test.c",
-    "ffsti2_test.c",
-    "fixdfdi_test.c",
-    "fixdfsivfp_test.c",
-    "fixdfti_test.c",
-    "fixsfdi_test.c",
-    "fixsfsivfp_test.c",
-    "fixsfti_test.c",
-    "fixtfdi_test.c",
-    "fixtfsi_test.c",
-    "fixtfti_test.c",
-    "fixunsdfdi_test.c",
-    "fixunsdfsi_test.c",
-    "fixunsdfsivfp_test.c",
-    "fixunsdfti_test.c",
-    "fixunssfdi_test.c",
-    "fixunssfsi_test.c",
-    "fixunssfsivfp_test.c",
-    "fixunssfti_test.c",
-    "fixunstfdi_test.c",
-    "fixunstfsi_test.c",
-    "fixunstfti_test.c",
-    "fixunsxfdi_test.c",
-    "fixunsxfsi_test.c",
-    "fixunsxfti_test.c",
-    "fixxfdi_test.c",
-    "fixxfti_test.c",
-    "floatdidf_test.c",
-    "floatdisf_test.c",
-    "floatditf_test.c",
-    "floatdixf_test.c",
-    "floatsidfvfp_test.c",
-    "floatsisfvfp_test.c",
-    "floatsitf_test.c",
-    "floattidf_test.c",
-    "floattisf_test.c",
-    "floattixf_test.c",
-    "floatundidf_test.c",
-    "floatundisf_test.c",
-    "floatunditf_test.c",
-    "floatundixf_test.c",
-    "floatunsitf_test.c",
-    "floatunssidfvfp_test.c",
-    "floatunssisfvfp_test.c",
-    "floatuntidf_test.c",
-    "floatuntisf_test.c",
-    "floatuntixf_test.c",
-    "gcc_personality_test.c",
-    "gedf2vfp_test.c",
-    "gesf2vfp_test.c",
-    "getf2_test.c",
-    "gtdf2vfp_test.c",
-    "gtsf2vfp_test.c",
-    "gttf2_test.c",
-    "ledf2vfp_test.c",
-    "lesf2vfp_test.c",
-    "letf2_test.c",
-    "lshrdi3_test.c",
-    "lshrti3_test.c",
-    "ltdf2vfp_test.c",
-    "ltsf2vfp_test.c",
-    "lttf2_test.c",
-    "moddi3_test.c",
-    "modsi3_test.c",
-    "modti3_test.c",
-    "muldc3_test.c",
-    "muldf3vfp_test.c",
-    "muldi3_test.c",
-    "mulodi4_test.c",
-    "mulosi4_test.c",
-    "muloti4_test.c",
-    "mulsc3_test.c",
-    "mulsf3vfp_test.c",
-    "multc3_test.c",
-    "multf3_test.c",
-    "multi3_test.c",
-    "mulvdi3_test.c",
-    "mulvsi3_test.c",
-    "mulvti3_test.c",
-    "mulxc3_test.c",
-    "nedf2vfp_test.c",
-    "negdf2vfp_test.c",
-    "negdi2_test.c",
-    "negsf2vfp_test.c",
-    "negti2_test.c",
-    "negvdi2_test.c",
-    "negvsi2_test.c",
-    "negvti2_test.c",
-    "nesf2vfp_test.c",
-    "netf2_test.c",
-    "paritydi2_test.c",
-    "paritysi2_test.c",
-    "parityti2_test.c",
-    "popcountdi2_test.c",
-    "popcountsi2_test.c",
-    "popcountti2_test.c",
-    "powidf2_test.c",
-    "powisf2_test.c",
-    "powitf2_test.c",
-    "powixf2_test.c",
-    "subdf3vfp_test.c",
-    "subsf3vfp_test.c",
-    "subtf3_test.c",
-    "subvdi3_test.c",
-    "subvsi3_test.c",
-    "subvti3_test.c",
-    -- "trampoline_setup_test.c", -- GCC extension, not supported on BF
-    -- "truncdfhf2_test.c",
-    "truncdfsf2_test.c",
-    "truncdfsf2vfp_test.c",
-    -- "truncsfhf2_test.c",
-    "trunctfdf2_test.c",
-    "trunctfsf2_test.c",
-    "ucmpdi2_test.c",
-    "ucmpti2_test.c",
-    "udivdi3_test.c",
-    "udivmoddi4_test.c",
-    "udivmodsi4_test.c",
-    "udivmodti4_test.c",
-    "udivsi3_test.c",
-    "udivti3_test.c",
-    "umoddi3_test.c",
-    "umodsi3_test.c",
-    "umodti3_test.c",
-    "unorddf2vfp_test.c",
-    "unordsf2vfp_test.c",
-    "unordtf2_test.c" ]
-
-  common_cFlags = [
-    "-Wno-missing-prototypes",
-    "-Wno-missing-declarations",
-    "-Wno-strict-prototypes",
-    "-Wno-old-style-definition",
-    "-Wno-redundant-decls"
-    ]
-
-  arch_cFlags arch = case arch of "x86_64"  -> [ ]
-                                  "k1om"    -> [ ]
-                                  "x86_32"  -> [ ]
-                                  "armv5"   -> [ "-D__ARM_EABI__" ]
-                                  "xscale"  -> [ "-D__ARM_EABI__" ]
-                                  "armv7"   -> [ "-D__ARM_EABI__" ]
-                                  "armv7-m" -> [ "-D__ARM_EABI__" ]
-                                  "armv8"   -> [ ]
-
-  builtin_unittests = [ build application {
-        target = "compiler-rt/" ++ builtins_unittest_dir ++ (take ((length f) - 2) f),
-        cFiles = [ builtins_unittest_dir ++ f ],
-        addCFlags = common_cFlags,
-        addLibraries = libDeps [
-            "compiler-rt",
-            "m"
-        ],
-        addIncludes = [
-            builtins_dir
-        ]
-    } | f <- builtins_unittest_files ]
-
-in [
-    build library {
-        target = "compiler-rt",
-        addCFlags = common_cFlags ++ (arch_cFlags arch),
-        cFiles = builtins_generic ++ builtins_c_arch arch,
-        assemblyFiles = builtins_asm_arch arch,
-        addLibraries = libDeps [
-            "m"
-        ],
-        architectures = [
-            arch
-        ]
-    } | arch <- allArchitectures
-] ++ builtin_unittests
diff --git a/lib/compiler-rt/lib/builtins/Hakefile b/lib/compiler-rt/lib/builtins/Hakefile
new file mode 100644 (file)
index 0000000..b811259
--- /dev/null
@@ -0,0 +1,338 @@
+--------------------------------------------------------------------------
+-- Copyright (c) 2016, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Universitaetstrasse 4, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for /lib/compiler-rt
+--
+--------------------------------------------------------------------------
+
+let
+  builtins_generic = [
+    "absvdi2.c",
+    "absvsi2.c",
+    "absvti2.c",
+    "adddf3.c",
+    "addsf3.c",
+    "addtf3.c",
+    "addvdi3.c",
+    "addvsi3.c",
+    "addvti3.c",
+    "apple_versioning.c",
+    "ashldi3.c",
+    "ashlti3.c",
+    "ashrdi3.c",
+    "ashrti3.c",
+    -- FIXME: atomic.c may only be compiled if host compiler understands _Atomic
+    -- atomic.c
+    "clear_cache.c",
+    "clzdi2.c",
+    "clzsi2.c",
+    "clzti2.c",
+    "cmpdi2.c",
+    "cmpti2.c",
+    "comparedf2.c",
+    "comparesf2.c",
+    "ctzdi2.c",
+    "ctzsi2.c",
+    "ctzti2.c",
+    "divdc3.c",
+    "divdf3.c",
+    "divdi3.c",
+    "divmoddi4.c",
+    "divmodsi4.c",
+    "divsc3.c",
+    "divsf3.c",
+    "divsi3.c",
+    -- GCC complains that __divtc3 has conflicting types with built-in __divtc3
+    -- "divtc3.c",
+    "divti3.c",
+    "divtf3.c",
+    "divxc3.c",
+    "enable_execute_stack.c",
+    -- "eprintf.c",
+    "extendsfdf2.c",
+    "extendhfsf2.c",
+    "ffsdi2.c",
+    "ffsti2.c",
+    "fixdfdi.c",
+    "fixdfsi.c",
+    "fixdfti.c",
+    "fixsfdi.c",
+    "fixsfsi.c",
+    "fixsfti.c",
+    "fixunsdfdi.c",
+    "fixunsdfsi.c",
+    "fixunsdfti.c",
+    "fixunssfdi.c",
+    "fixunssfsi.c",
+    "fixunssfti.c",
+    "fixunsxfdi.c",
+    "fixunsxfsi.c",
+    "fixunsxfti.c",
+    "fixxfdi.c",
+    "fixxfti.c",
+    "floatdidf.c",
+    "floatdisf.c",
+    "floatdixf.c",
+    "floatsidf.c",
+    "floatsisf.c",
+    "floattidf.c",
+    "floattisf.c",
+    "floattixf.c",
+    "floatundidf.c",
+    "floatundisf.c",
+    "floatundixf.c",
+    "floatunsidf.c",
+    "floatunsisf.c",
+    "floatuntidf.c",
+    "floatuntisf.c",
+    "floatuntixf.c",
+    "int_util.c",
+    "lshrdi3.c",
+    "lshrti3.c",
+    "moddi3.c",
+    "modsi3.c",
+    "modti3.c",
+    "muldc3.c",
+    "muldf3.c",
+    "muldi3.c",
+    "mulodi4.c",
+    "mulosi4.c",
+    "muloti4.c",
+    "mulsc3.c",
+    "mulsf3.c",
+    "multi3.c",
+    "multf3.c",
+    "mulvdi3.c",
+    "mulvsi3.c",
+    "mulvti3.c",
+    "mulxc3.c",
+    "negdf2.c",
+    "negdi2.c",
+    "negsf2.c",
+    "negti2.c",
+    "negvdi2.c",
+    "negvsi2.c",
+    "negvti2.c",
+    "paritydi2.c",
+    "paritysi2.c",
+    "parityti2.c",
+    "popcountdi2.c",
+    "popcountsi2.c",
+    "popcountti2.c",
+    "powidf2.c",
+    "powisf2.c",
+    "powitf2.c",
+    "powixf2.c",
+    "subdf3.c",
+    "subsf3.c",
+    "subvdi3.c",
+    "subvsi3.c",
+    "subvti3.c",
+    "subtf3.c",
+    "trampoline_setup.c",
+    "truncdfhf2.c",
+    "truncdfsf2.c",
+    "truncsfhf2.c",
+    "ucmpdi2.c",
+    "ucmpti2.c",
+    "udivdi3.c",
+    "udivmoddi4.c",
+    "udivmodsi4.c",
+    "udivmodti4.c",
+    "udivsi3.c",
+    "udivti3.c",
+    "umoddi3.c",
+    "umodsi3.c",
+    "umodti3.c" ]
+
+  builtins_asm_arch arch = case arch of
+    "x86_32" -> [
+        "i386/ashldi3.S",
+        "i386/ashrdi3.S",
+        "i386/chkstk.S",
+        "i386/chkstk2.S",
+        "i386/divdi3.S",
+        "i386/floatdidf.S",
+        "i386/floatdisf.S",
+        "i386/floatdixf.S",
+        "i386/floatundidf.S",
+        "i386/floatundisf.S",
+        "i386/floatundixf.S",
+        "i386/lshrdi3.S",
+        "i386/moddi3.S",
+        "i386/muldi3.S",
+        "i386/udivdi3.S",
+        "i386/umoddi3.S" ]
+    "x86_64" -> [
+        "x86_64/chkstk.S",
+        "x86_64/chkstk2.S",
+        "x86_64/floatundidf.S",
+        "x86_64/floatundisf.S",
+        "x86_64/floatundixf.S" ]
+    "k1om" -> [ ]
+    "armv5" -> [
+-- compiler-rt: *vfp: designed for Thumb1 CPUs with VFPv2
+--        "arm/adddf3vfp.S",
+--        "arm/addsf3vfp.S",
+        "arm/aeabi_cdcmp.S",
+        "arm/aeabi_cfcmp.S",
+        "arm/aeabi_dcmp.S",
+        "arm/aeabi_fcmp.S",
+        "arm/aeabi_idivmod.S",
+        "arm/aeabi_ldivmod.S",
+        "arm/aeabi_memcmp.S",
+        "arm/aeabi_memcpy.S",
+        "arm/aeabi_memmove.S",
+        "arm/aeabi_memset.S",
+        "arm/aeabi_uidivmod.S",
+        "arm/aeabi_uldivmod.S",
+        "arm/bswapdi2.S",
+        "arm/bswapsi2.S",
+        "arm/clzdi2.S",
+        "arm/clzsi2.S",
+        "arm/comparesf2.S",
+--        "arm/divdf3vfp.S",
+        "arm/divmodsi4.S",
+--        "arm/divsf3vfp.S",
+        "arm/divsi3.S",
+--        "arm/eqdf2vfp.S",
+--        "arm/eqsf2vfp.S",
+--        "arm/extendsfdf2vfp.S",
+--        "arm/fixdfsivfp.S",
+--        "arm/fixsfsivfp.S",
+--        "arm/fixunsdfsivfp.S",
+--        "arm/fixunssfsivfp.S",
+--        "arm/floatsidfvfp.S",
+--        "arm/floatsisfvfp.S",
+--        "arm/floatunssidfvfp.S",
+--        "arm/floatunssisfvfp.S",
+--        "arm/gedf2vfp.S",
+--        "arm/gesf2vfp.S",
+--        "arm/gtdf2vfp.S",
+--        "arm/gtsf2vfp.S",
+--        "arm/ledf2vfp.S",
+--        "arm/lesf2vfp.S",
+--        "arm/ltdf2vfp.S",
+--        "arm/ltsf2vfp.S",
+        "arm/modsi3.S",
+--        "arm/muldf3vfp.S",
+--        "arm/mulsf3vfp.S",
+--        "arm/nedf2vfp.S",
+--        "arm/negdf2vfp.S",
+--        "arm/negsf2vfp.S",
+--        "arm/nesf2vfp.S",
+--        "arm/restore_vfp_d8_d15_regs.S",
+--        "arm/save_vfp_d8_d15_regs.S",
+--        "arm/subdf3vfp.S",
+--        "arm/subsf3vfp.S",
+        "arm/sync_synchronize.S",
+--        "arm/truncdfsf2vfp.S",
+        "arm/udivmodsi4.S",
+        "arm/udivsi3.S",
+        "arm/umodsi3.S" --,
+--        "arm/unorddf2vfp.S",
+--        "arm/unordsf2vfp.S"
+        ]
+    "armv7" -> (builtins_asm_arch "armv5")
+        ++ [
+        "arm/switch16.S",
+        "arm/switch32.S",
+        "arm/switch8.S",
+        "arm/switchu8.S",
+        "arm/sync_fetch_and_add_4.S",
+        "arm/sync_fetch_and_add_8.S",
+        "arm/sync_fetch_and_and_4.S",
+        "arm/sync_fetch_and_and_8.S",
+        "arm/sync_fetch_and_max_4.S",
+        "arm/sync_fetch_and_max_8.S",
+        "arm/sync_fetch_and_min_4.S",
+        "arm/sync_fetch_and_min_8.S",
+        "arm/sync_fetch_and_nand_4.S",
+        "arm/sync_fetch_and_nand_8.S",
+        "arm/sync_fetch_and_or_4.S",
+        "arm/sync_fetch_and_or_8.S",
+        "arm/sync_fetch_and_sub_4.S",
+        "arm/sync_fetch_and_sub_8.S",
+        "arm/sync_fetch_and_umax_4.S",
+        "arm/sync_fetch_and_umax_8.S",
+        "arm/sync_fetch_and_umin_4.S",
+        "arm/sync_fetch_and_umin_8.S",
+        "arm/sync_fetch_and_xor_4.S",
+        "arm/sync_fetch_and_xor_8.S"
+        ]
+    "armv7-m" -> [ ]
+    "armv8" -> [ ]
+    "xscale" -> [ ]
+    x -> error ("Unknown architecture for compiler-rt: " ++ x)
+
+  builtins_c_arch arch = case arch of
+    "x86_32" -> [ ]
+    "x86_64" -> [
+        "x86_64/floatdidf.c",
+        "x86_64/floatdisf.c",
+        "x86_64/floatdixf.c" ]
+    "k1om" -> builtins_c_arch "x86_64"
+    "armv5" -> [
+        "arm/aeabi_cdcmpeq_check_nan.c",
+        "arm/aeabi_cfcmpeq_check_nan.c",
+        "arm/aeabi_div0.c",
+        "arm/aeabi_drsub.c",
+        "arm/aeabi_frsub.c" ]
+    "armv7" -> builtins_c_arch "armv5"
+    "armv7-m" -> builtins_c_arch "armv5"
+    "armv8" -> [
+        "comparetf2.c",
+        "extenddftf2.c",
+        "extendsftf2.c",
+        "fixtfdi.c",
+        "fixtfsi.c",
+        "fixtfti.c",
+        "fixunstfdi.c",
+        "fixunstfsi.c",
+        "fixunstfti.c",
+        "floatditf.c",
+        "floatsitf.c",
+        "floatunditf.c",
+        "floatunsitf.c",
+        "multc3.c",
+        "trunctfdf2.c",
+        "trunctfsf2.c" ]
+    "xscale" -> [ ]
+    x -> error ("Unknown architecture for compiler-rt: " ++ x)
+
+  common_cFlags = [
+    "-Wno-missing-prototypes",
+    "-Wno-missing-declarations",
+    "-Wno-strict-prototypes",
+    "-Wno-old-style-definition",
+    "-Wno-redundant-decls"
+    ]
+
+  arch_cFlags arch = case arch of "x86_64"  -> [ ]
+                                  "k1om"    -> [ ]
+                                  "x86_32"  -> [ ]
+                                  "armv5"   -> [ "-D__ARM_EABI__" ]
+                                  "xscale"  -> [ "-D__ARM_EABI__" ]
+                                  "armv7"   -> [ "-D__ARM_EABI__" ]
+                                  "armv7-m" -> [ "-D__ARM_EABI__" ]
+                                  "armv8"   -> [ ]
+
+in [
+    build library {
+        target = "compiler-rt",
+        addCFlags = common_cFlags ++ (arch_cFlags arch),
+        cFiles = builtins_generic ++ builtins_c_arch arch,
+        assemblyFiles = builtins_asm_arch arch,
+        addLibraries = libDeps [
+            "m"
+        ],
+        architectures = [
+            arch
+        ]
+    } | arch <- allArchitectures
+]
diff --git a/lib/compiler-rt/test/builtins/Unit/Hakefile b/lib/compiler-rt/test/builtins/Unit/Hakefile
new file mode 100644 (file)
index 0000000..2eab132
--- /dev/null
@@ -0,0 +1,218 @@
+--------------------------------------------------------------------------
+-- Copyright (c) 2016, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Universitaetstrasse 4, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for /lib/compiler-rt
+--
+--------------------------------------------------------------------------
+
+let
+  builtins_unittest_files = [
+    "absvdi2_test.c",
+    "absvsi2_test.c",
+    "absvti2_test.c",
+    "adddf3vfp_test.c",
+    "addsf3vfp_test.c",
+    "addtf3_test.c",
+    "addvdi3_test.c",
+    "addvsi3_test.c",
+    "addvti3_test.c",
+    "ashldi3_test.c",
+    "ashlti3_test.c",
+    "ashrdi3_test.c",
+    "ashrti3_test.c",
+    "bswapdi2_test.c",
+    "bswapsi2_test.c",
+    -- "clear_cache_test.c", -- requires mprotect
+    "clzdi2_test.c",
+    "clzsi2_test.c",
+    "clzti2_test.c",
+    "cmpdi2_test.c",
+    "cmpti2_test.c",
+    "comparedf2_test.c",
+    "comparesf2_test.c",
+    "ctzdi2_test.c",
+    "ctzsi2_test.c",
+    "ctzti2_test.c",
+    "divdc3_test.c",
+    "divdf3vfp_test.c",
+    "divdi3_test.c",
+    "divmodsi4_test.c",
+    "divsc3_test.c",
+    "divsf3vfp_test.c",
+    "divsi3_test.c",
+    -- "divtc3_test.c",
+    "divtf3_test.c",
+    "divti3_test.c",
+    "divxc3_test.c",
+    -- "enable_execute_stack_test.c", -- requires mprotect
+    "eqdf2vfp_test.c",
+    "eqsf2vfp_test.c",
+    "eqtf2_test.c",
+    "extebdsfdf2vfp_test.c",
+    "extenddftf2_test.c",
+    -- "extendhfsf2_test.c", -- requires __fp16 type
+    "extendsftf2_test.c",
+    "ffsdi2_test.c",
+    "ffsti2_test.c",
+    "fixdfdi_test.c",
+    "fixdfsivfp_test.c",
+    "fixdfti_test.c",
+    "fixsfdi_test.c",
+    "fixsfsivfp_test.c",
+    "fixsfti_test.c",
+    "fixtfdi_test.c",
+    "fixtfsi_test.c",
+    "fixtfti_test.c",
+    "fixunsdfdi_test.c",
+    "fixunsdfsi_test.c",
+    "fixunsdfsivfp_test.c",
+    "fixunsdfti_test.c",
+    "fixunssfdi_test.c",
+    "fixunssfsi_test.c",
+    "fixunssfsivfp_test.c",
+    "fixunssfti_test.c",
+    "fixunstfdi_test.c",
+    "fixunstfsi_test.c",
+    "fixunstfti_test.c",
+    "fixunsxfdi_test.c",
+    "fixunsxfsi_test.c",
+    "fixunsxfti_test.c",
+    "fixxfdi_test.c",
+    "fixxfti_test.c",
+    "floatdidf_test.c",
+    "floatdisf_test.c",
+    "floatditf_test.c",
+    "floatdixf_test.c",
+    "floatsidfvfp_test.c",
+    "floatsisfvfp_test.c",
+    "floatsitf_test.c",
+    "floattidf_test.c",
+    "floattisf_test.c",
+    "floattixf_test.c",
+    "floatundidf_test.c",
+    "floatundisf_test.c",
+    "floatunditf_test.c",
+    "floatundixf_test.c",
+    "floatunsitf_test.c",
+    "floatunssidfvfp_test.c",
+    "floatunssisfvfp_test.c",
+    "floatuntidf_test.c",
+    "floatuntisf_test.c",
+    "floatuntixf_test.c",
+    "gcc_personality_test.c",
+    "gedf2vfp_test.c",
+    "gesf2vfp_test.c",
+    "getf2_test.c",
+    "gtdf2vfp_test.c",
+    "gtsf2vfp_test.c",
+    "gttf2_test.c",
+    "ledf2vfp_test.c",
+    "lesf2vfp_test.c",
+    "letf2_test.c",
+    "lshrdi3_test.c",
+    "lshrti3_test.c",
+    "ltdf2vfp_test.c",
+    "ltsf2vfp_test.c",
+    "lttf2_test.c",
+    "moddi3_test.c",
+    "modsi3_test.c",
+    "modti3_test.c",
+    "muldc3_test.c",
+    "muldf3vfp_test.c",
+    "muldi3_test.c",
+    "mulodi4_test.c",
+    "mulosi4_test.c",
+    "muloti4_test.c",
+    "mulsc3_test.c",
+    "mulsf3vfp_test.c",
+    "multc3_test.c",
+    "multf3_test.c",
+    "multi3_test.c",
+    "mulvdi3_test.c",
+    "mulvsi3_test.c",
+    "mulvti3_test.c",
+    "mulxc3_test.c",
+    "nedf2vfp_test.c",
+    "negdf2vfp_test.c",
+    "negdi2_test.c",
+    "negsf2vfp_test.c",
+    "negti2_test.c",
+    "negvdi2_test.c",
+    "negvsi2_test.c",
+    "negvti2_test.c",
+    "nesf2vfp_test.c",
+    "netf2_test.c",
+    "paritydi2_test.c",
+    "paritysi2_test.c",
+    "parityti2_test.c",
+    "popcountdi2_test.c",
+    "popcountsi2_test.c",
+    "popcountti2_test.c",
+    "powidf2_test.c",
+    "powisf2_test.c",
+    "powitf2_test.c",
+    "powixf2_test.c",
+    "subdf3vfp_test.c",
+    "subsf3vfp_test.c",
+    "subtf3_test.c",
+    "subvdi3_test.c",
+    "subvsi3_test.c",
+    "subvti3_test.c",
+    -- "trampoline_setup_test.c", -- GCC extension, not supported on BF
+    -- "truncdfhf2_test.c",
+    "truncdfsf2_test.c",
+    "truncdfsf2vfp_test.c",
+    -- "truncsfhf2_test.c",
+    "trunctfdf2_test.c",
+    "trunctfsf2_test.c",
+    "ucmpdi2_test.c",
+    "ucmpti2_test.c",
+    "udivdi3_test.c",
+    "udivmoddi4_test.c",
+    "udivmodsi4_test.c",
+    "udivmodti4_test.c",
+    "udivsi3_test.c",
+    "udivti3_test.c",
+    "umoddi3_test.c",
+    "umodsi3_test.c",
+    "umodti3_test.c",
+    "unorddf2vfp_test.c",
+    "unordsf2vfp_test.c",
+    "unordtf2_test.c" ]
+
+  common_cFlags = [
+    "-Wno-missing-prototypes",
+    "-Wno-missing-declarations",
+    "-Wno-strict-prototypes",
+    "-Wno-old-style-definition",
+    "-Wno-redundant-decls"
+    ]
+
+  arch_cFlags arch = case arch of "x86_64"  -> [ ]
+                                  "k1om"    -> [ ]
+                                  "x86_32"  -> [ ]
+                                  "armv5"   -> [ "-D__ARM_EABI__" ]
+                                  "xscale"  -> [ "-D__ARM_EABI__" ]
+                                  "armv7"   -> [ "-D__ARM_EABI__" ]
+                                  "armv7-m" -> [ "-D__ARM_EABI__" ]
+                                  "armv8"   -> [ ]
+
+  builtins_unittest_dir = "test/builtins/Unit/"
+
+in [ build application {
+        target = "compiler-rt/" ++ builtins_unittest_dir ++ (take ((length f) - 2) f),
+        cFiles = [ f ],
+        addCFlags = common_cFlags,
+        addLibraries = libDeps [
+            "compiler-rt",
+            "m"
+        ],
+        addIncludes = [
+            "/lib/compiler-rt/lib/builtins/"
+        ]
+    } | f <- builtins_unittest_files ]
index 07dd5d3..e5dd454 100644 (file)
 
 let gmp_url = "https://gmplib.org/download/gmp/gmp-6.1.0.tar.bz2"
     gmp_archive = "gmp-6.1.0.tar.bz2"
-    gmp_dir = "gmp-6.1.0"
-
-    -- We need to have absolute directories in here because gmp's make
-    -- descends into sub directories. With relative include path it
-    -- would not find its headers.
-
-    untree x = case x of Str s -> s
-                         NoDep SrcTree arch dir -> "$(ABSSRCDIR)/" ++ dir
-                         NoDep InstallTree arch dir -> "$(ABSINSTALLDIR)/" ++ dir
-                         NoDep BuildTree arch dir -> "$(ABSBUILDDIR)/" ++ dir
-                         In InstallTree arch dir -> "$(ABSBUILDDIR)/" ++ arch ++ dir
-    untrees x = map untree x
 
     toDep x = case x of In treeref arch dir -> Dep treeref arch dir
                         e -> ErrorMsg ("unknown type " ++ (show e))
 
-    stringtrees x = Data.List.intercalate " " (untrees x)
-
-    extractFlags = filter (not . Data.List.isPrefixOf "-W")
+    extractFlags x = case x of Str s -> (not . Data.List.isPrefixOf "-W") s
 
     quoteStr [] = []
     quoteStr (h:t) = if h == '"' then "\\\"" ++ quoteStr t else h : quoteStr t
 
-    extraLink arch = [
-        In InstallTree arch "/lib/crt0.o",
-        In InstallTree arch "/lib/crtbegin.o",
-        In InstallTree arch "/lib/libposixcompat.a"
-        ]
+    extraLink arch =
+        [ In InstallTree arch "/lib/crt0.o",
+          In InstallTree arch "/lib/crtbegin.o",
+          In InstallTree arch "/lib/libposixcompat.a" ]
+
+    -- We need to have absolute directories in here because gmp's make
+    -- descends into sub directories. With relative include path it
+    -- would not find its headers.
 
-    commonLinkFlags arch = (Data.List.intercalate " " (
-            [
-                "-nostdlib",
-                "-L$(ABSBUILDDIR)/" ++ arch ++ "/lib/"
-            ]
-            ++
-            [ "-Wl,--start-group" ]
-            ++
-            (untrees (optLibs (options arch)))
-            ++
-            (untrees (extraLink arch))
-            ++
-            [
-                "-Wl,--end-group",
+    commonLinkFlags arch =
+        [ Str "-nostdlib",  NStr "-L", makeAbs $ NoDep BuildTree arch "/lib/" ]
+        ++ [ Str "-Wl,--start-group" ]
+        ++ (map makeAbs (optLibs (options arch)))
+        ++ (map makeAbs (extraLink arch))
+        ++ [
+            Str "-Wl,--end-group",
 -- Enable the following flags for ld debugging
---                "-Wl,-verbose=2",
---                "-Wl,-t",
---                "-Wl,--no-demangle",
-                "-Wl,--warn-unresolved-symbols",
-                "-Wl,--allow-multiple-definition"
-             ]
-        ))
+--            Str "-Wl,-verbose=2",
+--            Str "-Wl,-t",
+--            Str "-Wl,--no-demangle",
+            Str "-Wl,--warn-unresolved-symbols",
+            Str "-Wl,--allow-multiple-definition"
+        ]
 
-    compileCFLAGS arch = Data.List.intercalate " " (untrees Config.defines
-                ++
-                (extractFlags (untrees (optFlags (options arch))))
-                ++
-                [ "-I" ++ x | x <- untrees (optIncludes (options arch)) ]
-                )
+    compileCFLAGS arch =
+        Config.defines
+        ++ (filter extractFlags (optFlags (options arch)))
+        ++ concat [ [Str "-I",  makeAbs x ] | x <- optIncludes (options arch) ]
 
-    configureCFLAGS arch = "CFLAGS=\""
-            ++ (Data.List.intercalate " " [
-                compileCFLAGS arch,
-                commonLinkFlags arch
-                ]
-            ) ++ "\""
+    configureCFLAGS arch =
+        [ NStr "CFLAGS=\"" ]
+        ++ (compileCFLAGS arch)
+        ++ (commonLinkFlags arch)
+        ++ [ Str "\"" ]
 
-    envCFLAGS arch = "CFLAGS=\"" ++ (compileCFLAGS arch) ++ "\""
+    envCFLAGS arch =
+        [ NStr "CFLAGS=\""]
+        ++ (compileCFLAGS arch)
+        ++ [ Str "\"" ]
 
-    envCC arch = "CC=" ++ (RuleDefs.compiler $ options arch)
+    envCC arch = [ NStr "CC=" , Str (RuleDefs.compiler $ options arch) ]
 
     convertArch arch = case arch of
         "x86_64"  -> "x86_64-unknown-none"
@@ -93,20 +74,15 @@ let gmp_url = "https://gmplib.org/download/gmp/gmp-6.1.0.tar.bz2"
         "armv8"   -> "armv8-unknown-noneeabi"
         _         -> error "unknown arch " ++ arch
 
-    envLDFLAGS arch = "LDFLAGS=\""
-        ++
-        (commonLinkFlags arch)
-        ++
-        "\""
+    envLDFLAGS arch =
+        [ NStr "LDFLAGS=\"" ]
+        ++ (commonLinkFlags arch)
+        ++ [Str "\"" ]
 
-in [
+in [ ] ++ (getExternalDependency gmp_url gmp_archive) ++
     -- wget the file
     -- outputs to $BUILDDIR/lib/gmp
-    Rule ( [ Str "wget",
-        Str "-O",
-        Out "" gmp_archive,
-        Str gmp_url ] )
-  ] ++ concat [ [
+    concat [ [
     -- untar into arch/lib/gmp
     Rule ( [
         Str "tar",
@@ -135,13 +111,14 @@ in [
         -- sh will choke
         NStr ";\\", NL,
         Str "./configure",
-        NStr "\\", NL,
+        NStr "\\", NL
 -- It seems we don't need this.
 --        Str $ envLDFLAGS arch,
---        NStr "\\", NL,
-        Str $ envCC arch,
-        NStr "\\", NL,
-        Str $ configureCFLAGS arch,
+--        NStr "\\", NL
+        ] ++ (envCC arch)
+        ++ [
+        NStr "\\", NL
+        ] ++ (configureCFLAGS arch) ++ [
         NStr "\\", NL,
         Str "--build=x86_64-pc-linux-gnu",
         NStr "--host=",
@@ -149,7 +126,6 @@ in [
         -- Todo: This might depend on the architecture we're compiling for
         Str "--enable-assembly=no",
         Str "--disable-shared",
-        Str "--prefix=$(ABSINSTALLDIR)",
         Dep BuildTree arch "configure",
         NL,
         -- Remove all link groups from Makefiles CFLAGS. Otherwise libtool is
index b255e4a..9d1308c 100644 (file)
@@ -751,7 +751,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
 
     if (write(l.ofd,prompt,l.plen) == -1) return -1;
     while(1) {
-        char c;
+        int c;
         int nread;
         char seq[3];
 
index 4d0d258..e9f6163 100644 (file)
@@ -16,7 +16,8 @@
                   flounderBindings = [ "pci" ],
                   flounderExtraBindings = [ ("pci", ["rpcclient"]) ],
                   flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
-                  architectures = [ "x86_64", "x86_32" ]
+                  architectures = [ "x86_64", "x86_32" ],
+                  addLibraries = libDeps [ "acpi_client" ]
                 },
   
   -- XXX: This library is a bit weird right now.
index b22c311..a6350f7 100644 (file)
 #include <stdio.h>
 #include <barrelfish/barrelfish.h>
 #include <pci/mem.h>
-
-#if 0
-#define PCI_DEBUG(x...) printf("pci_client: " x)
-#else
-#define PCI_DEBUG(x...) ((void)0)
-#endif
+#include <pci/pci_client_debug.h>
 
 errval_t map_device(struct device_mem *mem)
 {
@@ -25,7 +20,7 @@ errval_t map_device(struct device_mem *mem)
         return SYS_ERR_OK; // XXX
     }
 
-    PCI_DEBUG("map_device: %lu\n", mem->bytes);
+    PCI_CLIENT_DEBUG("map_device: %lu\n", mem->bytes);
 
     size_t offset = 0;
     size_t cap_size = mem->bytes / mem->nr_caps;
@@ -39,14 +34,14 @@ errval_t map_device(struct device_mem *mem)
     }
 
     for (int i = 0; i < mem->nr_caps; i++) {
-        PCI_DEBUG("mem: map in cap nr %d\n", i);
+        PCI_CLIENT_DEBUG("mem: map in cap nr %d\n", i);
         err = mem->memobj->f.fill(mem->memobj, offset, mem->frame_cap[i],
                                   cap_size);
         if (err_is_fail(err)) {
             DEBUG_ERR(err, "memobj->f.fill failed");
             return err_push(err, LIB_ERR_MEMOBJ_FILL);
         }
-        PCI_DEBUG("offset = %lu\n", offset);
+        PCI_CLIENT_DEBUG("offset = %lu\n", offset);
         err = mem->memobj->f.pagefault(mem->memobj, mem->vregion, offset, 0);
         if (err_is_fail(err)) {
             DEBUG_ERR(err, "memobj->f.pagefault failed");
index 461eec6..bab725f 100644 (file)
 #include <barrelfish/dispatch.h>
 #include <barrelfish/inthandler.h>
 #include <pci/pci.h>
+#include <pci/pci_client_debug.h>
 #include <if/pci_defs.h>
 #include <if/pci_rpcclient_defs.h>
+#include <acpi_client/acpi_client.h>
 
 #define INVALID_VECTOR ((uint32_t)-1)
 
@@ -77,34 +79,14 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
                                          interrupt_handler_fn reloc_handler,
                                          void *reloc_handler_arg)
 {
-    uint32_t vector = INVALID_VECTOR;
     pci_caps_per_bar_t *caps_per_bar = NULL;
     uint8_t nbars;
     errval_t err, msgerr;
 
-    if (handler != NULL && reloc_handler != NULL) {
-        // register movable interrupt
-        err = inthandler_setup_movable(handler, handler_arg, reloc_handler,
-                reloc_handler_arg, &vector);
-        if (err_is_fail(err)) {
-            return err;
-        }
-
-        assert(vector != INVALID_VECTOR);
-    } else if (handler != NULL) {
-        // register non-movable interrupt
-        err = inthandler_setup(handler, handler_arg, &vector);
-        if (err_is_fail(err)) {
-            return err;
-        }
-        //printf("pci_client.c: got vector %"PRIu32"\n", vector);
-        assert(vector != INVALID_VECTOR);
-    }
-
     err = pci_client->vtbl.
         init_pci_device(pci_client, class, subclass, prog_if, vendor,
-                        device, bus, dev, fun, disp_get_core_id(), vector,
-                        &msgerr, &nbars, &caps_per_bar);
+                        device, bus, dev, fun, &msgerr,
+                        &nbars, &caps_per_bar);
     if (err_is_fail(err)) {
         return err;
     } else if (err_is_fail(msgerr)) {
@@ -112,6 +94,65 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
         return msgerr;
     }
 
+    struct capref irq_src_cap;
+
+    // Get vector 0 of the device.
+    // For backward compatibility with function interface.
+    err = pci_client->vtbl.get_irq_cap(pci_client, 0, &msgerr, &irq_src_cap);
+    if (err_is_fail(err) || err_is_fail(msgerr)) {
+        if (err_is_ok(err)) {
+            err = msgerr;
+        }
+        DEBUG_ERR(err, "requesting cap for IRQ 0 of device");
+        goto out;
+    }
+
+    uint32_t gsi = INVALID_VECTOR;
+    err = invoke_irqsrc_get_vector(irq_src_cap, &gsi);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "Could not lookup GSI vector");
+        return err;
+    }
+    PCI_CLIENT_DEBUG("Got irqsrc cap, gsi: %"PRIu32"\n", gsi);
+
+    // Get irq_dest_cap from monitor
+    struct capref irq_dest_cap;
+    err = alloc_dest_irq_cap(&irq_dest_cap);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err, "Could not allocate dest irq cap");
+        goto out;
+    }
+    uint32_t irq_dest_vec = INVALID_VECTOR;
+    err = invoke_irqdest_get_vector(irq_dest_cap, &irq_dest_vec);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "Could not lookup irq vector");
+        return err;
+    }
+    PCI_CLIENT_DEBUG("Got dest cap, vector: %"PRIu32"\n", irq_dest_vec);
+
+
+    // Setup routing
+    // TODO: Instead of getting the vectors of each cap and set up routing,
+    // pass both to a routing service and let the service handle the setup.
+    struct acpi_rpc_client* cl = get_acpi_rpc_client();
+    errval_t ret_error;
+    err = cl->vtbl.enable_and_route_interrupt(cl, gsi, disp_get_core_id(), irq_dest_vec, &ret_error);
+    assert(err_is_ok(err));
+    if (err_is_fail(ret_error)) {
+        DEBUG_ERR(ret_error, "failed to route interrupt %d -> %d\n", gsi, irq_dest_vec);
+        return err_push(ret_error, PCI_ERR_ROUTING_IRQ);
+    }
+
+    // Connect endpoint to handler
+    if(handler != NULL){
+        err = inthandler_setup_movable_cap(irq_dest_cap, handler, handler_arg,
+                reloc_handler, reloc_handler_arg);
+        if (err_is_fail(err)) {
+            return err;
+        }
+    }
+
+
     assert(nbars > 0); // otherwise we should have received an error!
 
     // FIXME: leak
@@ -133,7 +174,7 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
             struct capref cap;
             uint8_t type;
 
-            err = pci_client->vtbl.get_cap(pci_client, nb, nc, &msgerr, &cap,
+            err = pci_client->vtbl.get_bar_cap(pci_client, nb, nc, &msgerr, &cap,
                                            &type, &bar->bar_nr);
             if (err_is_fail(err) || err_is_fail(msgerr)) {
                 if (err_is_ok(err)) {
@@ -324,6 +365,11 @@ errval_t pci_client_connect(void)
     iref_t iref;
     errval_t err, err2 = SYS_ERR_OK;
 
+    err = connect_to_acpi();
+    if(err_is_fail(err)){
+        return err;
+    }
+
     /* Connect to the pci server */
     err = nameservice_blocking_lookup("pci", &iref);
     if (err_is_fail(err)) {
index 9932214..aed565e 100644 (file)
@@ -105,6 +105,6 @@ in
         flounderExtraBindings = [ ("octopus", [ "rpcclient" ]) ],
         flounderTHCStubs = [ "octopus" ],
         addLibraries = libDeps [ "vfs_noblockdev",  "term_server", "octopus" ],
-        architectures = [ "x86_32", "k1om", "armv7" , "armv8" ]
+        architectures = [ "x86_32", "k1om", "armv7", "armv7-m", "armv8" ]
     }
 ]
index a97078e..8c46144 100644 (file)
@@ -517,7 +517,7 @@ uint64_t thc_seq_read(thc_seq_t *seq) {
 
 uint64_t thc_seq_ticket(thc_seq_t *seq) {
 #ifdef _MSC_VER
-    C_ASSERT(sizeof(LONGLONG) == sizeof(seq->n));\r
+    C_ASSERT(sizeof(LONGLONG) == sizeof(seq->n));
     return InterlockedIncrement64(reinterpret_cast<volatile LONGLONG*>(&seq->n)) - 1;
 #else
   uint64_t result;
@@ -527,7 +527,6 @@ uint64_t thc_seq_ticket(thc_seq_t *seq) {
       break;
     }
   } while(1);
-  assert((result >= 0) && "URK!  Sequencer wrapped");
   return result;
 #endif
 }
index 777c224..b934b8b 100644 (file)
@@ -941,7 +941,7 @@ errval_t virtio_virtqueue_desc_enqueue(struct virtqueue *vq,
 
     uint16_t needed = num_rd + num_wr;
 
-    if (needed != bl->length || needed < 0) {
+    if (needed != bl->length) {
         return VIRTIO_ERR_SIZE_INVALID;
     }
 
index 32b8646..a7aa7f4 100644 (file)
@@ -214,7 +214,7 @@ errval_t virtio_vq_host_alloc(struct virtqueue_host ***vq,
                               struct virtqueue_setup *setup,
                               uint16_t vq_num)
 {
-    if (vq_num < 0 || vq == NULL) {
+    if (vq == NULL) {
         return VIRTIO_ERR_ARG_INVALID;
     }
 
index 14051a2..43127e2 100644 (file)
@@ -64,7 +64,8 @@ class HakeBuildBase(Build):
             "thumb_toolspec": "Nothing",
             "armeb_toolspec": "Nothing",
             "x86_toolspec": "Nothing",
-            "k1om_toolspec": "Nothing"
+            "k1om_toolspec": "Nothing",
+            "cache_dir": "\"%s\"" % os.path.expanduser("~/.cache/barrelfish/")
         }
         return default_config
 
index f0debfb..deeb5dd 100755 (executable)
@@ -50,6 +50,40 @@ def run_test(build, machine, test, path):
         debug.verbose('harness: cleanup test')
         test.cleanup(machine)
 
+def process_output(test, path):
+    """Process raw.txt and return array of output lines that begins with grubs
+    output, avoids having encoding issues when generating other report files"""
+
+    raw_file_name = os.path.join(path, RAW_FILE_NAME)
+
+    if os.path.exists(raw_file_name):
+        idx = 0
+        with open(raw_file_name, 'r') as rf:
+            lines = rf.readlines()
+            for idx, line in enumerate(lines):
+                if line.strip() == "root (nd)":
+                    break
+
+        return [ unicode(l, errors='replace') for l in lines[idx:] ]
+
+    # file did not exist
+    return ["could not open %s to process test output" % raw_file_name]
+
+def extract_errors(test, path):
+    raw_file_name = os.path.join(path, RAW_FILE_NAME)
+    debug.verbose('open %s for raw input' % raw_file_name)
+    raw_file = open(raw_file_name, 'r')
+
+    try:
+        results = test.process_data(path, raw_file)
+    finally:
+        raw_file.close()
+
+    try:
+        return results.errors
+    except:
+        return None
+
 
 def process_results(test, path):
     # open raw file for input processing
index 3c08fe1..a825483 100644 (file)
@@ -11,21 +11,21 @@ machines = dict({
     'nos4'   : {'ncores'      : 4,
                 'machine_name' : 'nos4',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 2,
                 'perfcount_type': 'amd0f',
                 'tickrate'    : 2800},
     'nos5'   : {'ncores'      : 4,
                 'machine_name' : 'nos5',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 2,
                 'perfcount_type': 'amd0f',
                 'tickrate'    : 2800},
     'nos6'   : {'ncores'      : 4,
                 'machine_name' : 'nos6',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 2,
                 'perfcount_type': 'amd0f',
                 'tickrate'    : 2800},
@@ -33,14 +33,14 @@ machines = dict({
     'sbrinz1': {'ncores'      : 16,
                 'machine_name' : 'sbrinz1',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 4,
                 'perfcount_type': 'amd10',
                 'tickrate'    : 2500},
     'sbrinz2': {'ncores'      : 16,
                 'machine_name' : 'sbrinz2',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 4,
                 'perfcount_type': 'amd10',
                 'tickrate'    : 2500},
@@ -48,7 +48,7 @@ machines = dict({
     'gruyere': {'ncores'      : 32,
                 'machine_name' : 'gruyere',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 4,
                 'perfcount_type': 'amd10',
                 'tickrate'    : 2000},
@@ -56,14 +56,14 @@ machines = dict({
     'ziger1':  {'ncores'      : 24,
                 'machine_name' : 'ziger1',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 6,
                 'perfcount_type': 'amd10',
                 'tickrate'    : 2400.367},
     'ziger2':  {'ncores'      : 24,
                 'machine_name' : 'ziger2',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 6,
                 'perfcount_type': 'amd10',
                 'tickrate'    : 2400.367},
@@ -71,7 +71,7 @@ machines = dict({
     'tomme1':  {'ncores'      : 16,
                 'machine_name' : 'tomme1',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 8,
                 'perfcount_type': 'intel',
                 'tickrate'    : 2270,
@@ -80,7 +80,7 @@ machines = dict({
     'tomme2':  {'ncores'      : 16,
                 'machine_name' : 'tomme2',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 8,
                 'perfcount_type': 'intel',
                 'tickrate'    : 2270,
@@ -90,7 +90,7 @@ machines = dict({
     'vacherin':{'ncores'      : 4,
                 'machine_name' : 'vacherin',
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket': 4,
                 'perfcount_type': 'intel',
                 'tickrate'    : 3400},
@@ -98,7 +98,7 @@ machines = dict({
     'appenzeller': {'ncores'      : 48,
                     'machine_name' : 'appenzeller',
                     'bootarch' : 'x86_64',
-                    'buildarchs' : ['x86_64', 'x86_32'],
+                    'buildarchs' : ['x86_64'],
                     'cores_per_socket': 12,
                     'perfcount_type': 'amd10',
                     'tickrate'    : 2200,
@@ -107,7 +107,7 @@ machines = dict({
     'gottardo': {'ncores'      : 32,
                  'machine_name' : 'gottardo',
                  'bootarch' : 'x86_64',
-                 'buildarchs' : ['x86_64', 'x86_32'],
+                 'buildarchs' : ['x86_64'],
                  'cores_per_socket': 16,
                  'perfcount_type': 'intel',
                  'tickrate'    : 1870,
@@ -116,7 +116,7 @@ machines = dict({
     'babybel1': {'ncores'          : 20,
                 'machine_name'    : 'babybel1',
                 'bootarch'        : 'x86_64',
-                'buildarchs'      : ['x86_64', 'x86_32', 'k1om'],
+                'buildarchs'      : ['x86_64', 'k1om'],
                 'cores_per_socket': 10,
                 'perfcount_type'  : 'intel',
                 'tickrate'        : 2500,
@@ -129,7 +129,7 @@ machines = dict({
     'babybel2': {'ncores'          : 20,
                 'machine_name'    : 'babybel2',
                 'bootarch'        : 'x86_64',
-                'buildarchs'      : ['x86_64', 'x86_32', 'k1om'],
+                'buildarchs'      : ['x86_64', 'k1om'],
                 'cores_per_socket': 10,
                 'perfcount_type'  : 'intel',
                 'tickrate'        : 2500,
@@ -142,7 +142,7 @@ machines = dict({
     'babybel3': {'ncores'          : 20,
                 'machine_name'    : 'babybel3',
                 'bootarch'        : 'x86_64',
-                'buildarchs'      : ['x86_64', 'x86_32', 'k1om'],
+                'buildarchs'      : ['x86_64', 'k1om'],
                 'cores_per_socket': 10,
                 'perfcount_type'  : 'intel',
                 'tickrate'        : 2500,
@@ -155,7 +155,7 @@ machines = dict({
     'babybel4': {'ncores'          : 20,
                 'machine_name'    : 'babybel4',
                 'bootarch'        : 'x86_64',
-                'buildarchs'      : ['x86_64', 'x86_32', 'k1om'],
+                'buildarchs'      : ['x86_64', 'k1om'],
                 'cores_per_socket': 10,
                 'perfcount_type'  : 'intel',
                 'tickrate'        : 2500,
@@ -401,7 +401,7 @@ machines = dict({
                 'ncores' : 4,
                 'machine_name' : ('brie%s' % b),
                 'bootarch' : 'x86_64',
-                'buildarchs' : ['x86_64', 'x86_32'],
+                'buildarchs' : ['x86_64'],
                 'cores_per_socket' : 2,
                 'tickrate' : 2193,
                 'perfcount_type': 'amd0f',
index 2ae3e6c..015dd03 100644 (file)
@@ -32,6 +32,20 @@ class PassFailResult(ResultsBase):
         return self.passfail
 
 
+class PassFailMultiResult(ResultsBase):
+    def __init__(self, name, errors=[]):
+        self.errors = errors
+        self.name = name
+
+    def passed(self):
+        return len(self.errors) == 0
+
+    def to_file(self, fh):
+        if len(self.errors) > 0:
+            fh.write('%d error(s) in %s\n' % (len(self.errors), self.name))
+            for error in self.errors:
+                fh.write(error)
+
 class RowResults(ResultsBase):
     """Results class that maintains numeric values grouped by rows.
     """
index 4dda5c5..7dd41c6 100755 (executable)
@@ -31,6 +31,11 @@ import machines
 from tests.common import TimeoutError
 from socket import gethostname
 
+try:
+    from junit_xml import TestSuite, TestCase
+    have_junit_xml = True
+except:
+    have_junit_xml = False
 
 def list_all():
     print 'Build types:\t', ', '.join([b.name for b in builds.all_builds])
@@ -58,6 +63,9 @@ def parse_args():
                  metavar='TEST', help='tests/benchmarks to run')
     g.add_option('-c', '--comment', dest='comment',
                  help='comment to store with all collected data')
+    g.add_option('-x', '--xml', dest='xml', action='store_true',
+                 default=False,
+                 help='output summary of tests in Junit XML format')
     p.add_option_group(g)
 
     g = optparse.OptionGroup(p, 'Debugging options')
@@ -92,6 +100,10 @@ def parse_args():
             and os.access(options.resultsdir, os.W_OK)):
         p.error('invalid results directory %s' % options.resultsdir)
 
+    if options.xml and not have_junit_xml:
+        p.error('--xml requires junit-xml.\n'
+                'Please install junit-xml through pip or easy_install')
+
     # resolve and instantiate all builds
     def _lookup(spec, classes):
         spec = spec.lower()
@@ -156,6 +168,14 @@ def make_results_dir(options, build, machine, test):
     os.makedirs(path)
     return path
 
+def make_run_dir(options, build, machine):
+    # Create a unique directory for the output from this test
+    timestamp = datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
+    dirname = '-'.join([build.name, machine.name, timestamp])
+    path = os.path.join(options.resultsdir, str(datetime.datetime.now().year), dirname)
+    debug.verbose('create result directory %s' % path)
+    os.makedirs(path)
+    return path
 
 def write_description(options, checkout, build, machine, test, path):
     debug.verbose('write description file')
@@ -175,6 +195,60 @@ def write_description(options, checkout, build, machine, test, path):
         with open(os.path.join(path, 'changes.patch'), 'w') as f:
             f.write(diff)
 
+def write_errorcase(build, machine, test, path, msg, start_ts, end_ts):
+    delta = end_ts - start_ts
+    tc = { 'name': test.name,
+           'time_elapsed': delta.total_seconds(),
+           'class': machine.name,
+           'stdout': ''.join(harness.process_output(test, path)),
+           'stderr': "",
+           'passed': False
+    }
+    if have_junit_xml:
+        ju_tc = TestCase(
+                tc['name'],
+                tc['class'],
+                tc['time_elapsed'],
+                tc['stdout'],
+                )
+        ju_tc.add_error_info(message=msg)
+        return ju_tc
+    else:
+        return tc
+
+def write_testcase(build, machine, test, path, passed,
+        start_ts, end_ts):
+    delta = end_ts - start_ts
+    tc = { 'name': test.name,
+           'class': machine.name,
+           'time_elapsed': delta.total_seconds(),
+           'stdout': ''.join(harness.process_output(test, path)),
+           'stderr': "",
+           'passed': passed
+    }
+    if have_junit_xml:
+        ju_tc = TestCase(
+                tc['name'],
+                tc['class'],
+                tc['time_elapsed'],
+                tc['stdout'],
+                )
+        if not passed:
+            errors = harness.extract_errors(test, path)
+            errorstr = 'Failed'
+            if errors is not None:
+                errorstr = ''.join([ unicode(l, errors='replace') for l in errors])
+            ju_tc.add_failure_info(message=errorstr)
+        return ju_tc
+    else:
+        return tc
+
+def write_xml_report(testcases, path):
+    assert(have_junit_xml)
+    debug.log("producing junit-xml report")
+    ts = TestSuite('harness suite', testcases)
+    with open(os.path.join(path, 'report.xml'), 'w') as f:
+        TestSuite.to_file(f, [ts], prettyprint=False)
 
 def main(options):
     retval = True  # everything was OK
@@ -186,6 +260,8 @@ def main(options):
         buildarchs |= set(m.get_buildarchs())
     buildarchs = list(buildarchs)
 
+    testcases = []
+
     for build in options.builds:
         debug.log('starting build: %s' % build.name)
         build.configure(co, buildarchs)
@@ -195,6 +271,7 @@ def main(options):
                           % (test.name, machine.name, os.getcwd()))
                 path = make_results_dir(options, build, machine, test)
                 write_description(options, co, build, machine, test, path)
+                start_timestamp = datetime.datetime.now()
                 try:
                     harness.run_test(build, machine, test, path)
                 except TimeoutError:
@@ -203,9 +280,15 @@ def main(options):
                     if options.keepgoing:
                         msg += ' (attempting to continue)'
                     debug.error(msg)
+                    end_timestamp = datetime.datetime.now()
+                    testcases.append(write_errorcase(build, machine, test, path,
+                        msg, start_timestamp, end_timestamp)
+                        )
                     if options.keepgoing:
                         continue
                     else:
+                        if options.xml:
+                            write_xml_report(testcases, path)
                         return retval
                 except Exception:
                     retval = False
@@ -213,12 +296,19 @@ def main(options):
                     if options.keepgoing:
                         msg += ' (attempting to continue):'
                     debug.error(msg)
+                    end_timestamp = datetime.datetime.now()
+                    testcases.append(write_errorcase(build, machine, test, path,
+                        msg, start_timestamp, end_timestamp)
+                        )
                     if options.keepgoing:
                         traceback.print_exc()
                         continue
                     else:
+                        if options.xml:
+                            write_xml_report(testcases, path)
                         raise
 
+                end_timestamp = datetime.datetime.now()
                 debug.log('test complete, processing results')
                 try:
                     passed = harness.process_results(test, path)
@@ -232,9 +322,19 @@ def main(options):
                     if options.keepgoing:
                         traceback.print_exc()
                     else:
+                        if options.xml:
+                            write_xml_report(testcases, path)
                         raise
                 if not passed:
                     retval = False
+                testcases.append(
+                        write_testcase(build, machine, test, path, passed,
+                            start_timestamp, end_timestamp))
+
+    # produce JUnit style xml report if requested
+    if options.xml:
+        path = make_run_dir(options, build, machine)
+        write_xml_report(testcases, path)
 
     debug.log('all done!')
     return retval
index 942a100..3a529c4 100644 (file)
@@ -7,10 +7,9 @@
 # ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 ##########################################################################
 
-import re
 import tests
 from common import TestCommon
-from results import PassFailResult
+from results import PassFailMultiResult
 
 class CompilerRTBuiltinsAbstract(TestCommon):
 
@@ -19,210 +18,224 @@ class CompilerRTBuiltinsAbstract(TestCommon):
 
     def process_data(self, testdir, rawiter):
         # the test passed if no error occurred
-        passed = True
+        errors = []
         for line in rawiter:
             if "error in" in line:
-                passed = False
-        return PassFailResult(passed)
+                errors.append(line)
 
-@tests.add_test
-class CompilerRTBuiltins1(CompilerRTBuiltinsAbstract):
-    '''runs compiler-rt1 builins unit tests'''
-    name = "compiler-rt1"
+        return PassFailMultiResult(self.name, errors)
 
-    def get_modules(self, build, machine):
-        modules = super(CompilerRTBuiltins1, self).get_modules(build, machine)
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/absvdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/absvsi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/absvti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/adddf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/addsf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/addtf3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/addvdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/addvsi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/addvti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ashldi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ashlti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ashrdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ashrti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/bswapdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/bswapsi2_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/clear_cache_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/clzdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/clzsi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/clzti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/cmpdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/cmpti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/comparedf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/comparesf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ctzdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ctzsi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ctzti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divdc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divdf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divmodsi4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divsc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divsf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divsi3_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divtc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divtf3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/divxc3_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/enable_execute_stack_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/eqdf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/eqsf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/eqtf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/extenddftf2_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/extendhfsf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/extendsftf2_test")
-        modules.add_module("usleeptest", [ "5" ])
-        return modules
+# list of tests to run for compiler-rt
+all_tests = [
+        "$BUILD/compiler-rt/test/builtins/Unit/absvdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/absvsi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/absvti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/adddf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/addsf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/addtf3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/addvdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/addvsi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/addvti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ashldi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ashlti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ashrdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ashrti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/bswapdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/bswapsi2_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/clear_cache_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/clzdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/clzsi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/clzti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/cmpdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/cmpti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/comparedf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/comparesf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ctzdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ctzsi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ctzti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divdc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divdf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divmodsi4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divsc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divsf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divsi3_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/divtc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divtf3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/divxc3_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/enable_execute_stack_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/eqdf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/eqsf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/eqtf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/extebdsfdf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/extenddftf2_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/extendhfsf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/extendsftf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ffsdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ffsti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixdfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixdfsivfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixdfti_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixsfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixsfsivfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixsfti_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixtfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixtfsi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixtfti_test",
+        # this errors
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsdfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsdfsi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsdfti_test",
+        # this errors
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunssfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunssfsi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunssfsivfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunssfti_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunstfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunstfsi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunstfti_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsxfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsxfsi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixunsxfti_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixxfdi_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/fixxfti_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatdidf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatdisf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatditf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatdixf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatsidfvfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatsisfvfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatsitf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floattidf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floattisf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floattixf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatundidf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatundisf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatunditf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatundixf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatunsitf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatunssidfvfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatunssisfvfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatuntidf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatuntisf_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/floatuntixf_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/gcc_personality_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/gedf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/gesf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/getf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/gtdf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/gtsf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/gttf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ledf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/lesf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/letf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/lshrdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/lshrti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ltdf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ltsf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/lttf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/moddi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/modsi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/modti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/muldc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/muldf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/muldi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulodi4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulosi4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/muloti4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulsc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulsf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/multc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/multf3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/multi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulvdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulvsi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulvti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/mulxc3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/nedf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negdf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negsf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negvdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negvsi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/negvti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/nesf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/netf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/paritydi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/paritysi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/parityti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/popcountdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/popcountsi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/popcountti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/powidf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/powisf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/powitf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/powixf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/subdf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/subsf3vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/subtf3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/subvdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/subvsi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/subvti3_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/trampoline_setup_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/truncdfhf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/truncdfsf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test",
+#       "$BUILD/compiler-rt/test/builtins/Unit/truncsfhf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/trunctfdf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/trunctfsf2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ucmpdi2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/ucmpti2_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/udivdi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/udivmoddi4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/udivmodsi4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/udivmodti4_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/udivsi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/udivti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/umoddi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/umodsi3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/umodti3_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/unorddf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/unordsf2vfp_test",
+        "$BUILD/compiler-rt/test/builtins/Unit/unordtf2_test",
+]
 
-@tests.add_test
-class CompilerRTBuiltins2(CompilerRTBuiltinsAbstract):
-    '''runs compiler-rt2 builins unit tests'''
-    name = "compiler-rt2"
+def get_modules_tpl(ts, self, build, machine):
+    '''Function template for get_modules() for each compiler-rt test case'''
+    modules = super(CompilerRTBuiltinsAbstract, self).get_modules(build, machine)
+    for m in ts:
+        modules.add_module(m)
+    modules.add_module("usleeptest", [ "5" ])
+    return modules
 
-    def get_modules(self, build, machine):
-        modules = super(CompilerRTBuiltins2, self).get_modules(build, machine)
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ffsdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ffsti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixdfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixdfsivfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixdfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixsfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixsfsivfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixsfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixtfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixtfsi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixtfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsdfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsdfsi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsdfsivfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsdfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunssfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunssfsi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunssfsivfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunssfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunstfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunstfsi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunstfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsxfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsxfsi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixunsxfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixxfdi_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/fixxfti_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatdidf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatdisf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatditf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatdixf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatsidfvfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatsisfvfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatsitf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floattidf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floattisf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floattixf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatundidf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatundisf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatunditf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatundixf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatunsitf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatunssidfvfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatunssisfvfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatuntidf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatuntisf_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/floatuntixf_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/gcc_personality_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/gedf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/gesf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/getf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/gtdf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/gtsf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/gttf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ledf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/lesf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/letf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/lshrdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/lshrti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ltdf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ltsf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/lttf2_test")
-        modules.add_module("usleeptest", [ "5" ])
-        return modules
+def chunker(seq, size):
+    '''Helper function: this takes a sequence `seq` and splits it up into
+    `size`-sized chunks, except for the last chunk which is just the <= size
+    long remainder of the sequence'''
+    return (seq[pos:pos+size] for pos in xrange(0, len(seq), size))
 
-@tests.add_test
-class CompilerRTBuiltins3(CompilerRTBuiltinsAbstract):
-    '''runs compiler-rt3 builins unit tests'''
-    name = "compiler-rt3"
-
-    def get_modules(self, build, machine):
-        modules = super(CompilerRTBuiltins3, self).get_modules(build, machine)
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/moddi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/modsi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/modti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/muldc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/muldf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/muldi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulodi4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulosi4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/muloti4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulsc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulsf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/multc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/multf3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/multi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulvdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulvsi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulvti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/mulxc3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/nedf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negdf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negsf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negvdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negvsi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/negvti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/nesf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/netf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/paritydi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/paritysi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/parityti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/popcountdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/popcountsi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/popcountti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/powidf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/powisf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/powitf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/powixf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/subdf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/subsf3vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/subtf3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/subvdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/subvsi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/subvti3_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/trampoline_setup_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/truncdfhf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/truncdfsf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/truncdfsf2vfp_test")
-#        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/truncsfhf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/trunctfdf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/trunctfsf2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ucmpdi2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/ucmpti2_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/udivdi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/udivmoddi4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/udivmodsi4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/udivmodti4_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/udivsi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/udivti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/umoddi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/umodsi3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/umodti3_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/unorddf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/unordsf2vfp_test")
-        modules.add_module("$BUILD/compiler-rt/test/builtins/Unit/unordtf2_test")
-        modules.add_module("usleeptest", [ "5" ])
-        return modules
+# generate test-cases with <=CHUNK_SIZE compiler-rt tests each
+CHUNK_SIZE=35
+# array just to keep the class objects somewhere
+compiler_rt_tests_classes = []
+for i, ts in enumerate(chunker(all_tests, CHUNK_SIZE)):
+    # append new class to our array
+    compiler_rt_tests_classes.append(
+        # this is essentially the decorator @tests.add_test
+        tests.add_test(
+            # type is the (built-in) base-class for python classes, here we
+            # construct classes by calling its constructor
+            # signature of type constructor:
+            #   type(classname, baseclass tuple, dict with methods/attributes)
+            type('CompilerRTBuiltins%d' % (i+1),
+                 (CompilerRTBuiltinsAbstract,),
+                 { 'name': 'compiler-rt%d' % (i+1),
+                    # partially bind the get_modules() template to select the
+                    # right set of tests. Note the ts=ts in the lambda
+                    # arguments, this prevents python's default late-binding
+                    # for closure arguments.
+                     'get_modules':
+                         lambda s, b, m, ts=ts: get_modules_tpl(ts, s, b, m)})))
index 17e5331..8d53bf8 100755 (executable)
@@ -165,7 +165,7 @@ run_latex
 if [ -n "$HAS_BIB" ]; then (bibtex $AUX_FILE_WITHOUT_AUX && test -r $BBL_FILE)  || exit; echo run_latex; fi
 if [ -n "$HAS_GLO" ]; then (makeglossaries -s $IST_FILE $GLO_FILE && makeglossaries -s $IST_FILE $ACN_FILE && test -r $GLO_FILE)  || exit; echo run_latex; fi
 if [ -e "$TOC_FILE" -o -e "$BBL_FILE" -o -e "$VER_FILE" -o -e "$GLO_FILE" -o -e "$ACN_FILE" ]; then run_latex; fi
-while egrep -e 'LaTeX Warning.*Rerun' "$LOG_FILE"; do run_latex; done
+while egrep -e '^LaTeX Warning.*Rerun|^\(.*\).*Rerun' "$LOG_FILE"; do run_latex; done
 rm -f "$AUX_FILE" "$HST_FILE" "$LOG_FILE" "$TOC_FILE" "$BBL_FILE"
 rm -f "$BLG_FILE" "$VER_FILE" "$OUT_FILE" "$GDE_FILE"
 rm -f "$GLO_FILE" "$ACN_FILE" "$IST_FILE"
index aae8fca..62b346e 100644 (file)
@@ -334,7 +334,7 @@ static void get_irq_routing(ACPI_HANDLE handle, uint8_t bus)
         }
 
         assert(device < PCI_NDEVICES);
-        assert(prt->Pin >= 0 && prt->Pin < PCI_NINTPINS);
+        assert(prt->Pin < PCI_NINTPINS);
 
         char *esource = calloc(strlen(prt->Source) * 2, 1);
         for(int i = 0, j = 0; i < strlen(prt->Source) + 1; i++, j++) {
index f6e55a5..9c2c925 100644 (file)
@@ -969,6 +969,7 @@ AcpiOsInstallInterruptHandler (
 
     uint32_t vector;
     errval_t e = inthandler_setup(interrupt_wrapper, ic, &vector);
+    ACPI_DEBUG("Allocated local vec %"PRIu32"\n", vector);
     if (err_is_fail(e)) {
         DEBUG_ERR(e, "failed to setup handler function/vector");
         return AE_ERROR;
index 32caf78..bde74e7 100644 (file)
@@ -49,7 +49,7 @@ static void rx_list_call(struct ahci_mgmt_binding *b)
 {
     AHCID_DEBUG("got list call\n");
     uint8_t port;
-    uint8_t current_num_ports = (num_ports == -1 ? 0 : num_ports);
+    uint8_t current_num_ports = (num_ports == (uint8_t)-1 ? 0 : num_ports);
     uint8_t next_port = 0;
     uint8_t *port_ids = malloc(current_num_ports);
     for (port = 0; port < current_num_ports; port++) {
index 84ef5b2..cbe095d 100644 (file)
@@ -136,7 +136,7 @@ static inline int e10k_queue_add_txbuf_ctx(e10k_queue_t* q, uint64_t phys,
     e10k_q_tdesc_adv_rd_ifcs_insert(d, 1);
     e10k_q_tdesc_adv_rd_eop_insert(d, last);
 
-    if (ctx != -1U) {
+    if (ctx != (uint8_t)-1) {
         e10k_q_tdesc_adv_rd_idx_insert(d, ctx);
         e10k_q_tdesc_adv_rd_cc_insert(d, 1);
         e10k_q_tdesc_adv_rd_ixsm_insert(d, ixsm);
index 39a6583..8dbda00 100644 (file)
@@ -301,6 +301,8 @@ static errval_t connect_cb(void *st, struct timer_binding *b)
         return LIB_ERR_MALLOC_FAIL;
     }
 
+    memset(client, 0, sizeof(struct timer_client));
+
     // Store this per-client closure
     b->st = client;
     client->binding = b;
index 7946e0a..c4a4c90 100644 (file)
@@ -96,7 +96,7 @@ int main(int argc, char *argv[])
             portbase = (uint16_t) x;
         } else if (strncmp(argv[i], "irq=", sizeof("irq=") - 1) == 0) {
              unsigned long x = strtoul(argv[i] + sizeof("irq=") - 1, NULL, 0);
-             if (irq == 0 || irq > 255) {
+             if (irq == 0) {
                 fprintf(stderr, "Error: invalid IRQ %lu\n", x);
                 goto usage;
             }
index 903c2e4..9915831 100644 (file)
@@ -417,14 +417,20 @@ efx_mac_hash_set(
        EFX_ZERO_OWORD(epp->ep_multicst_hash[0]);
        for (idx = 0; idx < 128; idx++) {
                if (bucket[idx] != 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
                        EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], idx);
+#pragma GCC diagnostic pop
        }
 
        /* Set the upper 128 bits of the hash */
        EFX_ZERO_OWORD(epp->ep_multicst_hash[1]);
        for (idx = 0; idx < 128; idx++) {
                if (bucket[idx + 128] != 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
                        EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], idx);
+#pragma GCC diagnostic pop
        }
 
        if ((rc = emop->emo_reconfigure(enp)) != 0)
index e82dcd7..f3ee707 100644 (file)
@@ -80,7 +80,7 @@ struct usb_keyboard_led {
  */
 struct usb_keyboard_data {
     union usb_keyboard_modifiers modifiers;  ///< the activated modifiers
-    uint8_t keycode[USB_KEYBOARD_KEYCODES];  ///> the extracted keycode
+    int32_t keycode[USB_KEYBOARD_KEYCODES];  ///> the raw extracted keycode (can be error)
 };
 
 
index 915d986..a30a770 100644 (file)
@@ -34,7 +34,7 @@ struct usb_xfer;
  */\r
 struct usb_memory_block {\r
     usb_paddr_t phys_addr;\r
-    uint32_t size;\r
+    ssize_t size;\r
     void *buffer;\r
 };\r
 \r
index 9d86ab8..a3e4ded 100644 (file)
@@ -20,7 +20,6 @@
 #include <if/octopus_defs.h>
 #include <if/octopus_rpcclient_defs.h>
 #include <if/octopus_thc.h>
-#include <if/monitor_defs.h>
 
 #include "xeon_phi_internal.h"
 #include "domain.h"
index f76694c..e7c0c2f 100644 (file)
 #   define SIZEOF_LONG 4
 #   define SIZEOF_CHAR_P 4
 #   define SIZEOF_LONG_P 4
+#elif defined(__aarch64__)
+#   define SIZEOF_INT 4
+#   define SIZEOF_LONG 8
+#   define SIZEOF_CHAR_P 8
+#   define SIZEOF_LONG_P 8
 #else
 #   error Unknown architecture
 #endif
index 2ef897f..c1d2466 100644 (file)
@@ -231,10 +231,9 @@ invoke_monitor_remote_cap_retype(capaddr_t rootcap_addr, uint8_t rootcap_vbits,
     uint8_t invoke_bits = get_cap_valid_bits(cap_kernel);
     capaddr_t invoke_cptr = get_cap_addr(cap_kernel) >> (CPTR_BITS - invoke_bits);
 
-    assert(newtype <= 0xffff);
+    assert(newtype <= ObjType_Num);
     assert(objbits <= 0xff);
     assert(bits <= 0xff);
-    assert(rootcap_vbits <= 0xff);
 
     struct remote_retype_syscall_overflow rootcap_struct = {
         .rootcap_addr = rootcap_addr,
index 62efe8d..4cda179 100644 (file)
@@ -361,6 +361,35 @@ static void get_io_cap(struct monitor_blocking_binding *b)
     }
 }
 
+static void get_irq_dest_cap(struct monitor_blocking_binding *b)
+{
+    errval_t err;
+    //TODO get real cap
+
+    struct capref dest_cap;
+    slot_alloc(&dest_cap);
+    err = invoke_irqtable_alloc_dest_cap(cap_irq, dest_cap);
+    if(err_is_fail(err)){
+        DEBUG_ERR(err,"x");
+        USER_PANIC_ERR(err, "could not allocate dest cap!");
+    }
+
+
+    err = b->tx_vtbl.get_irq_dest_cap_response(b, NOP_CONT, dest_cap,
+            SYS_ERR_OK);
+    if (err_is_fail(err)) {
+        if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
+            err = b->register_send(b, get_default_waitset(),
+                                   MKCONT((void (*)(void *))get_io_cap, b));
+            if (err_is_fail(err)) {
+                USER_PANIC_ERR(err, "register_send failed");
+            }
+        }
+
+        USER_PANIC_ERR(err, "sending get_io_cap_response failed");
+    }
+}
+
 
 static void get_bootinfo(struct monitor_blocking_binding *b)
 {
@@ -514,6 +543,7 @@ static struct monitor_blocking_rx_vtbl rx_vtbl = {
     .get_bootinfo_call = get_bootinfo,
     .get_phyaddr_cap_call = get_phyaddr_cap,
     .get_io_cap_call = get_io_cap,
+    .get_irq_dest_cap_call = get_irq_dest_cap,
 
     .remote_cap_retype_call  = remote_cap_retype,
     .remote_cap_delete_call  = remote_cap_delete,
index 45dbf8b..3224951 100644 (file)
@@ -29,7 +29,6 @@
 #include <dev/pci_sr_iov_cap_dev.h>
 
 #include "pci.h"
-#include "driver_mapping.h"
 #include "ht_config.h"
 #include <dev/ht_config_dev.h>
 #include "pci_debug.h"
@@ -60,10 +59,6 @@ query_bars(pci_hdr0_t devhdr,
            struct pci_address addr,
            bool pci2pci_bridge);
 
-static uint32_t
-setup_interrupt(uint32_t bus,
-                uint32_t dev,
-                uint32_t fun);
 static void
 enable_busmaster(uint8_t bus,
                  uint8_t dev,
@@ -138,7 +133,7 @@ int pci_get_nr_caps_for_bar(uint8_t bus,
     return (dev_caps[bus][dev][fun][idx].nr_caps);
 }
 
-struct capref pci_get_cap_for_device(uint8_t bus,
+struct capref pci_get_bar_cap_for_device(uint8_t bus,
                                      uint8_t dev,
                                      uint8_t fun,
                                      uint8_t idx,
@@ -146,7 +141,7 @@ struct capref pci_get_cap_for_device(uint8_t bus,
 {
     return (dev_caps[bus][dev][fun][idx].frame_cap[cap_nr]);
 }
-uint8_t pci_get_cap_type_for_device(uint8_t bus,
+uint8_t pci_get_bar_cap_type_for_device(uint8_t bus,
                                     uint8_t dev,
                                     uint8_t fun,
                                     uint8_t idx)
@@ -260,10 +255,7 @@ static errval_t assign_complete_io_range(uint8_t idx,
     return SYS_ERR_OK;
 }
 
-errval_t device_init(bool enable_irq,
-                     uint8_t coreid,
-                     int vector,
-                     uint32_t class_code,
+errval_t device_init(uint32_t class_code,
                      uint32_t sub_class,
                      uint32_t prog_if,
                      uint32_t vendor_id,
@@ -271,6 +263,7 @@ errval_t device_init(bool enable_irq,
                      uint32_t *bus,
                      uint32_t *dev,
                      uint32_t *fun,
+                     bool *pcie,
                      int *nr_allocated_bars)
 {
     *nr_allocated_bars = 0;
@@ -279,7 +272,6 @@ errval_t device_init(bool enable_irq,
     char s_bus[10], s_dev[10], s_fun[10], s_vendor_id[10], s_device_id[10];
     char s_class_code[10], s_sub_class[10], s_prog_if[10];
     char s_pcie[5];
-    bool pcie;
     int error_code;
     int bar_nr;
     pciaddr_t bar_base, bar_high;
@@ -363,9 +355,9 @@ errval_t device_init(bool enable_irq,
         return err_push(err, PCI_ERR_DEVICE_INIT);
     }
     if (strncmp(s_pcie, "pcie", strlen("pcie")) == 0) {
-        pcie = true;
+        *pcie = true;
     } else {
-        pcie = false;
+        *pcie = false;
     }
 
     PCI_DEBUG("device_init(): Found device at %u:%u:%u\n", *bus, *dev, *fun);
@@ -416,24 +408,9 @@ errval_t device_init(bool enable_irq,
 //end of badness
 
     PCI_DEBUG("device_init(): Allocated caps for %d BARs\n", *nr_allocated_bars);
-    if (enable_irq) {
-        int irq = setup_interrupt(*bus, *dev, *fun);
-        PCI_DEBUG("pci: init_device_handler_irq: init interrupt.\n");
-        PCI_DEBUG("pci: irq = %u, core = %hhu, vector = %u\n", irq, coreid,
-                  vector);
-        struct acpi_rpc_client* cl = get_acpi_rpc_client();
-        errval_t ret_error;
-        err = cl->vtbl.enable_and_route_interrupt(cl, irq, coreid, vector,
-                                                  &ret_error);
-        assert(err_is_ok(err));
-        assert(err_is_ok(ret_error));  // FIXME
-//        printf("IRQ for this device is %d\n", irq);
-                        //DEBUG_ERR(err, "enable_and_route_interrupt");
-        pci_enable_interrupt_for_device(*bus, *dev, *fun, pcie);
-    }
 
     PCI_DEBUG("enable busmaster for device (%u, %u, %u)...\n", *bus, *dev, *fun);
-    enable_busmaster(*bus, *dev, *fun, pcie);
+    enable_busmaster(*bus, *dev, *fun, *pcie);
 
     return SYS_ERR_OK;
 }
@@ -539,7 +516,7 @@ errval_t device_reregister_interrupt(uint8_t coreid, int vector,
                 *bus, *dev, *fun);
 //get the implemented BARs for the found device
 
-    int irq = setup_interrupt(*bus, *dev, *fun);
+    int irq = pci_setup_interrupt(*bus, *dev, *fun);
     PCI_DEBUG("pci: init_device_handler_irq: init interrupt.\n");
     PCI_DEBUG("pci: irq = %u, core = %hhu, vector = %u\n",
             irq, coreid, vector);
@@ -800,8 +777,7 @@ static void assign_bus_numbers(struct pci_address parentaddr,
 
                     // Walk capabilities list
                     while (cap_ptr != 0) {
-                        assert(cap_ptr % 4 == 0 && cap_ptr >= 0x40
-                               && cap_ptr < 0x100);
+                        assert(cap_ptr % 4 == 0 && cap_ptr >= 0x40);
                         uint32_t capword = pci_read_conf_header(&addr,
                                                                 cap_ptr / 4);
 
@@ -1698,9 +1674,9 @@ void pci_program_bridges(void)
     }
 }
 
-static uint32_t setup_interrupt(uint32_t bus,
-                                uint32_t dev,
-                                uint32_t fun)
+uint32_t pci_setup_interrupt(uint32_t bus,
+                         uint32_t dev,
+                         uint32_t fun)
 {
     char str[256], ldev[128];
 
index 8c3851b..635c076 100644 (file)
@@ -55,11 +55,22 @@ void pci_add_root(struct pci_address addr, uint8_t maxchild, char* handle);
 void pci_program_bridges(void);
 void pci_init(void);
 void pci_init_datastructures(void);
-errval_t device_init(bool enable_irq, uint8_t coreid, int vector,
-                     uint32_t class_code, uint32_t sub_class, uint32_t prog_if,
-                     uint32_t vendor_id, uint32_t device_id,
-                     uint32_t *bus, uint32_t *dev,uint32_t *fun,
+
+errval_t device_init(uint32_t class_code,
+                     uint32_t sub_class,
+                     uint32_t prog_if,
+                     uint32_t vendor_id,
+                     uint32_t device_id,
+                     uint32_t *bus,
+                     uint32_t *dev,
+                     uint32_t *fun,
+                     bool *pcie,
                      int *nr_allocated_bars);
+
+
+uint32_t pci_setup_interrupt(uint32_t bus,
+                uint32_t dev,
+                uint32_t fun);
 errval_t device_reregister_interrupt(uint8_t coreid, int vector,
                  uint32_t class_code, uint32_t sub_class, uint32_t prog_if,
                  uint32_t vendor_id, uint32_t device_id, uint32_t *bus,
@@ -67,9 +78,9 @@ errval_t device_reregister_interrupt(uint8_t coreid, int vector,
 int pci_bar_to_caps_index(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t BAR);
 int pci_get_bar_nr_for_index(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t idx);
 int pci_get_nr_caps_for_bar(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t index);
-struct capref pci_get_cap_for_device(uint8_t bus, uint8_t dev, uint8_t fun,
+struct capref pci_get_bar_cap_for_device(uint8_t bus, uint8_t dev, uint8_t fun,
                                      uint8_t index, int cap_nr);
-uint8_t pci_get_cap_type_for_device(uint8_t bus, uint8_t dev, uint8_t fun,
+uint8_t pci_get_bar_cap_type_for_device(uint8_t bus, uint8_t dev, uint8_t fun,
                                     uint8_t index);
 void pci_enable_interrupt_for_device(uint32_t bus, uint32_t dev, uint32_t fun,
                                     bool pcie);
index 3b91c79..77dd732 100644 (file)
@@ -144,7 +144,7 @@ errval_t pci_msix_enable(struct pci_address *addr, uint16_t *count)
         assert(bar_index >= 0);
         assert(pci_get_nr_caps_for_bar(addr->bus, addr->device, addr->function,
                                         bar_index) == 1);
-        tablecap = pci_get_cap_for_device(addr->bus, addr->device, addr->function,
+        tablecap = pci_get_bar_cap_for_device(addr->bus, addr->device, addr->function,
                                           bar_index, 0);
         invoke_frame_identify(tablecap, &frameid);
         err = vspace_map_one_frame_attr(&virt, frameid.bytes, tablecap,
index 40829f6..c243d63 100644 (file)
  * XXX: this assumes only one driver per client */
 struct client_state {
 //    struct device_mem *bar_info;
+    uint8_t initialized;
     int nr_allocated_bars;
     uint32_t nr_caps_bar[PCI_NBARS];
     uint32_t bus;
     uint32_t dev;
     uint32_t fun;
+    bool pcie;
     void *cont_st;
 };
 
@@ -56,16 +58,14 @@ static void init_pci_device_handler(struct pci_binding *b,
                                     uint32_t class_code, uint32_t sub_class,
                                     uint32_t prog_if, uint32_t vendor_id,
                                     uint32_t device_id,
-                                    uint32_t bus, uint32_t dev, uint32_t fun,
-                                    coreid_t coreid, uint32_t vector)
+                                    uint32_t bus, uint32_t dev, uint32_t fun)
 {
-    bool enable_irq = (vector != (uint32_t)-1);
     struct client_state *cc = (struct client_state *) b->st;
     errval_t err;
 
-    err = device_init(enable_irq, coreid, vector,
-                      class_code, sub_class, prog_if, vendor_id, device_id,
-                      &bus, &dev, &fun, &(cc->nr_allocated_bars));
+
+    err = device_init(class_code, sub_class, prog_if, vendor_id, device_id,
+                      &bus, &dev, &fun, &(cc->pcie), &(cc->nr_allocated_bars));
 
     cc->bus = bus;
     cc->dev = dev;
@@ -78,6 +78,7 @@ static void init_pci_device_handler(struct pci_binding *b,
     if (err_is_fail(err)) {
         err = b->tx_vtbl.init_pci_device_response(b, NOP_CONT, err, 0,
                                                   cc->nr_caps_bar);
+
     } else {
         err = b->tx_vtbl.init_pci_device_response(b, NOP_CONT, err,
                                                   cc->nr_allocated_bars,
@@ -86,6 +87,18 @@ static void init_pci_device_handler(struct pci_binding *b,
     assert(err_is_ok(err));
 }
 
+static void irq_enable_handler(struct pci_binding *b)
+{
+    struct client_state *cc = (struct client_state *) b->st;
+    if(!cc->initialized){
+        b->tx_vtbl.irq_enable_response(b, NOP_CONT, PCI_ERR_DEVICE_NOT_INIT);
+        return;
+    }
+
+    pci_enable_interrupt_for_device(cc->bus, cc->dev, cc->fun, cc->pcie);
+    b->tx_vtbl.irq_enable_response(b, NOP_CONT, SYS_ERR_OK);
+}
+
 static void init_legacy_device_handler(struct pci_binding *b,
                                        uint16_t iomin, uint16_t iomax,
                                        uint8_t irq, coreid_t coreid,
@@ -94,7 +107,7 @@ static void init_legacy_device_handler(struct pci_binding *b,
     struct capref iocap = NULL_CAP;
     errval_t e = SYS_ERR_OK;
 
-    PCI_DEBUG("pci: init_legacy_device_handler: called.\n");
+    PCI_DEBUG("pci: init_legacy_device_handler: called. irq:%"PRIu8", coreid:%"PRIuCOREID", vector:%"PRIu32"\n", irq, coreid, vector);
 
     /* TODO: make sure nobody else has claimed iomin-iomax range */
 
@@ -138,17 +151,17 @@ reply:
     PCI_DEBUG("pci: init_legacy_device_handler: terminated.\n");
 }
 
-static void get_cap_response_resend(void *arg);
+static void get_bar_cap_response_resend(void *arg);
 
-static void get_cap_response_cont(struct pci_binding *b, errval_t err,
+static void get_bar_cap_response_cont(struct pci_binding *b, errval_t err,
                                   struct capref cap, uint8_t type, uint8_t bar_nr)
 {
     errval_t e;
-    e = b->tx_vtbl.get_cap_response(b, NOP_CONT, err, cap, type, bar_nr);
+    e = b->tx_vtbl.get_bar_cap_response(b, NOP_CONT, err, cap, type, bar_nr);
     if(err_is_fail(e)) {
         if(err_no(e) == FLOUNDER_ERR_TX_BUSY) {
             struct client_state *st = b->st;
-            struct pci_get_cap_response__args *me = malloc(sizeof(*me));
+            struct pci_get_bar_cap_response__args *me = malloc(sizeof(*me));
             assert(me != NULL);
             me->err = err;
             me->cap = cap;
@@ -157,24 +170,47 @@ static void get_cap_response_cont(struct pci_binding *b, errval_t err,
             st->cont_st = me;
 
             e = b->register_send(b, get_default_waitset(),
-                                 MKCONT(get_cap_response_resend, b));
+                                 MKCONT(get_bar_cap_response_resend, b));
             assert(err_is_ok(e));
         } else {
-            USER_PANIC_ERR(e, "get_cap_response");
+            USER_PANIC_ERR(e, "get_bar_cap_response");
         }
     }
 }
 
-static void get_cap_response_resend(void *arg)
+static void get_bar_cap_response_resend(void *arg)
 {
     struct pci_binding *b = arg;
     struct client_state *st = b->st;
-    struct pci_get_cap_response__args *a = st->cont_st;
-    get_cap_response_cont(b, a->err, a->cap, a->type, a->bar_nr);
+    struct pci_get_bar_cap_response__args *a = st->cont_st;
+    get_bar_cap_response_cont(b, a->err, a->cap, a->type, a->bar_nr);
     free(a);
 }
 
-static void get_cap_handler(struct pci_binding *b, uint32_t idx,
+static void get_irq_cap_handler(struct pci_binding *b, uint16_t idx){
+    // TODO: This method works only for non legacy devices
+    // and supports only one interrupt per device at the moment
+    assert(idx == 0);
+    errval_t err;
+    struct capref cap;
+    slot_alloc(&cap);
+
+    struct client_state *st = b->st;
+
+    // TODO: This should be part of the routing step
+    int irq = pci_setup_interrupt(st->bus, st->dev, st->fun);
+    PCI_DEBUG("pci: init_device_handler_irq: init interrupt.\n");
+    PCI_DEBUG("pci: irq = %u, core = %hhu, vector = %u\n", irq, coreid,
+                      vector);
+
+    pci_enable_interrupt_for_device(st->bus, st->dev, st->fun, st->pcie);
+
+
+    err = sys_debug_create_irq_src_cap(cap, irq);
+    b->tx_vtbl.get_irq_cap_response(b, NOP_CONT, err, cap);
+}
+
+static void get_bar_cap_handler(struct pci_binding *b, uint32_t idx,
                             uint32_t cap_nr)
 {
     struct client_state *st = b->st;
@@ -182,13 +218,13 @@ static void get_cap_handler(struct pci_binding *b, uint32_t idx,
     errval_t e;
 
     if (idx >= st->nr_allocated_bars) {
-        e = b->tx_vtbl.get_cap_response(b, NOP_CONT, PCI_ERR_WRONG_INDEX,
+        e = b->tx_vtbl.get_bar_cap_response(b, NOP_CONT, PCI_ERR_WRONG_INDEX,
                                         NULL_CAP, 0, 0);
         assert(err_is_ok(e));
     } else {
-        struct capref cap = pci_get_cap_for_device(st->bus, st->dev,
+        struct capref cap = pci_get_bar_cap_for_device(st->bus, st->dev,
                                                    st->fun, idx, cap_nr);
-        uint8_t type = pci_get_cap_type_for_device(st->bus, st->dev,
+        uint8_t type = pci_get_bar_cap_type_for_device(st->bus, st->dev,
                                                    st->fun, idx);
         uint8_t bar_nr = pci_get_bar_nr_for_index(st->bus, st->dev,
                                                    st->fun, idx);
@@ -204,7 +240,7 @@ XXX: I/O-Cap??
         }
 */
 
-        get_cap_response_cont(b, SYS_ERR_OK, cap, type, bar_nr);
+        get_bar_cap_response_cont(b, SYS_ERR_OK, cap, type, bar_nr);
     }
 }
 /*
@@ -340,11 +376,13 @@ static void msix_vector_init_handler(struct pci_binding *b, uint16_t idx,
 struct pci_rx_vtbl pci_rx_vtbl = {
     .init_pci_device_call = init_pci_device_handler,
     .init_legacy_device_call = init_legacy_device_handler,
-    .get_cap_call = get_cap_handler,
+    .get_bar_cap_call = get_bar_cap_handler,
+    .get_irq_cap_call = get_irq_cap_handler,
     .reregister_interrupt_call = reregister_interrupt_handler,
     //.get_vbe_bios_cap_call = get_vbe_bios_cap,
     .read_conf_header_call = read_conf_header_handler,
     .write_conf_header_call = write_conf_header_handler,
+    .irq_enable_call = irq_enable_handler,
 
     .msix_enable_call = msix_enable_handler,
     .msix_enable_addr_call = msix_enable_addr_handler,
index 504b184..7735fbc 100644 (file)
@@ -83,7 +83,7 @@ static void read_eclipse_queue(int qid, struct skb_writer* w)
         w->length += res;
     } while ((res != 0) && w->length < MAX_QUERY_LENGTH);
 
-    if (w->length >= 0 && w->length < MAX_QUERY_LENGTH) {
+    if (w->length < MAX_QUERY_LENGTH) {
         w->buffer[w->length] = '\0';
     }
     else {