seL4/haskell/src/SEL4/Object/Structures/ARM.lhs
2014-07-19 10:48:49 +02:00

100 lines
3.2 KiB
Text

%
% Copyright 2014, General Dynamics C4 Systems
%
% This software may be distributed and modified according to the terms of
% the GNU General Public License version 2. Note that NO WARRANTY is provided.
% See "LICENSE_GPLv2.txt" for details.
%
% @TAG(GD_GPL)
%
This module contains the physical memory model's representations of the ARM-specific data structures, as well as a type representing a capability to an ARM-specific object.
\begin{impdetails}
This module makes use of the GHC extension allowing declaration of types with no constructors, so GHC language extensions are enabled.
> {-# LANGUAGE EmptyDataDecls, GeneralizedNewtypeDeriving #-}
\end{impdetails}
> module SEL4.Object.Structures.ARM where
\begin{impdetails}
> import SEL4.Machine.RegisterSet
> import SEL4.Machine.Hardware.ARM
> import Data.Array
> import Data.Word(Word32)
> import Data.Bits
\end{impdetails}
\subsection{Capabilities}
There are six ARM-specific capability types: the global ASID control capability, ASID pools, page tables, page directories, and pages.
> data ArchCapability
> = PageCap {
> capVPBasePtr :: PPtr Word,
> capVPRights :: VMRights,
> capVPSize :: VMPageSize,
> capVPMappedAddress :: Maybe (ASID, VPtr) }
> | PageTableCap {
> capPTBasePtr :: PPtr PTE,
> capPTMappedAddress :: Maybe (ASID, VPtr) }
> | PageDirectoryCap {
> capPDBasePtr :: PPtr PDE,
> capPDMappedASID :: Maybe ASID }
> | ASIDControlCap
> | ASIDPoolCap {
> capASIDPool :: PPtr ASIDPool,
> capASIDBase :: ASID }
> deriving (Eq, Show)
\subsection{Kernel Objects}
The ARM kernel stores one ARM-specific type of object in the PSpace: ASID pools, which are second level nodes in the global ASID table.
> data ArchKernelObject
> = KOASIDPool ASIDPool
> | KOPTE PTE
> | KOPDE PDE
> deriving Show
> archObjSize :: ArchKernelObject -> Int
> archObjSize a = case a of
> KOASIDPool _ -> pageBits
> KOPTE _ -> 2
> KOPDE _ -> 2
\subsection{ASID Pools}
An ASID pool is an array of pointers to page directories. This is used to implement virtual ASIDs on ARM; it is not accessed by the hardware.
> newtype ASIDPool = ASIDPool (Array ASID (Maybe (PPtr PDE)))
> deriving Show
An ASID is an unsigned word. Note that it is a \emph{virtual} address space identifier, and may not correspond to any hardware-defined identifier --- especially on ARMv5 and earlier, where the only identifier implemented in hardware is the 4-bit domain number.
> newtype ASID = ASID Word32
> deriving (Show, Eq, Ord, Enum, Real, Integral, Num, Bits, Ix, Bounded)
ASIDs are mapped to address space roots by a global two-level table. The actual ASID values are opaque to the user, as are the sizes of the levels of the tables; ASID allocation calls will simply return an error once the available ASIDs are exhausted.
> asidHighBits :: Int
> asidHighBits = 8
> asidLowBits :: Int
> asidLowBits = 10
> asidBits :: Int
> asidBits = asidHighBits + asidLowBits
> asidRange :: (ASID, ASID)
> asidRange = (0, (1 `shiftL` asidBits) - 1)
> asidHighBitsOf :: ASID -> ASID
> asidHighBitsOf asid = (asid `shiftR` asidLowBits) .&. mask asidHighBits