Skip to content

Commit

Permalink
init commit for imx31-new-qemu support
Browse files Browse the repository at this point in the history
  • Loading branch information
Gao Xin authored and lsf37 committed May 19, 2015
1 parent f5afc2d commit 8664ae4
Show file tree
Hide file tree
Showing 11 changed files with 845 additions and 933 deletions.
3 changes: 2 additions & 1 deletion haskell/SEL4.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Library
exposed-modules: SEL4
SEL4.Machine.Target

build-depends: mtl, base, array, containers
build-depends: mtl==2.1.3.1, base, array, containers
if flag(FFI)
-- be fixed.
build-depends: unix
Expand All @@ -42,6 +42,7 @@ Library
SEL4.API.Types.Universal
SEL4.API.Invocation
SEL4.Kernel
SEL4.Kernel.BootInfo
SEL4.Kernel.VSpace
SEL4.Kernel.CSpace
SEL4.Kernel.Init
Expand Down
6 changes: 6 additions & 0 deletions haskell/src/SEL4/API/Failures.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ The procedure for handling faults is defined in \autoref{sec:kernel.faulthandler
> userExceptionErrorCode :: Word }
> deriving Show

\subsection{Kernel Init Failure}

Data type InitFailure can be thrown during SysInit

> data InitFailure = InitFailure

\subsection{System Call Errors}

The following data type defines the set of errors that can be returned from a kernel object method call.
Expand Down
112 changes: 35 additions & 77 deletions haskell/src/SEL4/API/Types.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ We use the C preprocessor to select a target architecture. Also, this file makes
> import SEL4.Machine

> import Data.Bits
> import Data.Word(Word8)
> import Data.Word(Word8 , Word32)

\end{impdetails}

Expand Down Expand Up @@ -203,86 +203,44 @@ The top-level structure is "BootInfo", which contains an IPC buffer pointer,
information about the initial untyped capabilities, and an array of virtual
address space regions.

> data BootInfo = BootInfo {
> biIPCBuffer :: VPtr,
> -- insert (length biRegions) here
> biRegions :: [BootRegion] }
> deriving Show

> wordsFromBootInfo :: BootInfo -> [Word]
> wordsFromBootInfo bi = [
> fromVPtr $ biIPCBuffer bi,
> fromIntegral $ length $ biRegions bi ]
> ++ (concat $ map wordsFromBootRegion $ biRegions bi)

Each region descriptor has start and end pointers (with the latter pointing to
the last address in the region, rather than the first address after it), a
type, and some data whose use depends on the type.

> data BootRegion = BootRegion {
> brBase :: CPtr,
> brEnd :: CPtr,
> brType :: BootRegionType,
> brData :: Word }
> deriving Show

> wordsFromBootRegion :: BootRegion -> [Word]
> wordsFromBootRegion br = [
> fromCPtr $ brBase br,
> fromCPtr $ brEnd br,
> fromIntegral $ fromEnum $ brType br,
> brData br ]

The boot regions are of various types, and are used for three separate purposes: describing what \emph{can} appear in a specific region of the address space, describing what \emph{is} in the initial task's address space, and describing the structure of the capability table. Regions with different purposes may overlap as noted below.

> data BootRegionType

\begin{description}

\item[Empty] regions are not used by capabilities or virtual memory mappings in the initial task's address space.

> = BREmpty

\item[RootTask] regions contain the root task's mapped text or data, backed by one or more page-sized frames.

> | BRRootTask

\item[CapsOnly] regions cannot be used for virtual memory mappings, but are still usable for capabilities. This may be, for example, because the kernel maps its own data at these addresses, or because the hardware MMU does not implement addressing of the region. This may overlap any region other than "BRRootTask".

> | BRCapsOnly

\item[NodeL1] appears once, and represents the area covered by the initial thread's root page table node. The data word contains the radix of the node.

> | BRNodeL1

\item[NodeL2] regions represent second-level nodes in the initial capability table. Again, the data word contains the radix of the node. They all occur within the "BRNodeL1" region.

> | BRNodeL2

Regions of any of the types below only appear in "BRNodeL2" regions.

\item[FreeSlots] regions contain empty capability slots accessible in the root task's CSpace, which may be used to bootstrap the system's capability management. The data word gives the CSpace depth required by the Retype call to locate the CNode containing the slots.

> | BRFreeSlots

\item[InitCaps] is the region containing the root task's six guaranteed initial capabilities; it always appears exactly once with a base address of zero. Address 0 contains a null capability (which should not be replaced with a valid one). It is followed by the initial thread's TCB, CSpace root, VSpace root, and reply endpoint, and then .

> | BRInitCaps

\item[SmallBlocks] regions are filled with untyped memory objects of a single size, generally the platform's standard page size. The minimum number of page-sized untyped blocks that will be provided to the root task by the kernel is fixed at compile time. The data word contains the block size, in address bits.

> | BRSmallBlocks

\item[LargeBlocks] regions are filled with untyped memory objects of varying sizes. The kernel provides large blocks for any physical memory not already covered by other memory regions. The blocks are in order from smallest to largest, with at most one of each size; the sizes present have the corresponding bits in the region's data word set. In spite of the name, some of these blocks may have sizes less than one page. There may be multiple large block regions.
> newtype Region = Region { fromRegion :: (PPtr Word, PPtr Word) }
> deriving (Show, Eq)

> | BRLargeBlocks
> ptrFromPAddrRegion :: (PAddr, PAddr) -> Region
> ptrFromPAddrRegion (start, end) = Region (ptrFromPAddr start, ptrFromPAddr end)

\item[DeviceCaps] regions each contain the capabilities required to access one hardware device. The meaning of the data word is implementation-defined.
> newtype SlotRegion = SlotRegion (Word, Word)
> deriving (Show, Eq)

> | BRDeviceCaps
> data BIDeviceRegion = BIDeviceRegion {
> bidrBasePAddr :: PAddr,
> bidrFrameSizeBits :: Word32,
> bidrFrameCaps :: SlotRegion }
> deriving (Show, Eq)

\end{description}
> data BIFrameData = BIFrameData {
> bifNodeID :: Word32, --Word?
> bifNumNodes :: Word32, --Int?
> bifNumIOPTLevels :: Word32, --Int?
> bifIPCBufVPtr :: VPtr,
> bifNullCaps :: [Word],
> bifSharedFrameCaps :: [Word],
> bifUIFrameCaps :: [Word],
> bifUIPTCaps :: [Word],
> bifUntypedObjCaps :: [Word],
> bifUntypedObjPAddrs :: [PAddr],
> bifUntypedObjSizeBits :: [Word8], --combine these into one list?
> bifITCNodeSizeBits :: Word8,
> bifNumDeviceRegions :: Word32,
> bifDeviceRegions :: [BIDeviceRegion] }
> deriving (Show, Eq)

> deriving (Show, Enum)
> data InitData = InitData {
> initFreeMemory :: [Region], -- Filled in initFreemem
> initSlotPosCur :: Word, --Word?
> initSlotPosMax :: Word, -- Filled in makeRootCNode ?
> initBootInfo :: BIFrameData,
> initBootInfoFrame :: PAddr } --PAddr?
> deriving (Show, Eq)


186 changes: 186 additions & 0 deletions haskell/src/SEL4/Kernel/BootInfo.lhs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
% @LICENSE(OKL_CORE)

This module contains functions that maintaining the bootinfo structure for init-thread .

> module SEL4.Kernel.BootInfo where

\begin{impdetails}

> import Data.Bits
> import Control.Monad.State

> import SEL4.API.Types
> import SEL4.Object.Structures
> import SEL4.Machine

> import SEL4.Model.StateData

> import {-# SOURCE #-} SEL4.Kernel.Init


\subsection{Constant}

> biCapNull :: Word
> biCapNull = 0

> itASID :: ASID
> itASID = 1

> biCapITTCB :: Word
> biCapITTCB = 1

> biCapITCNode :: Word
> biCapITCNode = 2

> biCapITPD :: Word
> biCapITPD = 3

> biCapIRQControl :: Word
> biCapIRQControl = 4

> biCapASIDControl :: Word
> biCapASIDControl = 5

> biCapITASIDPool :: Word
> biCapITASIDPool = 6

> biCapIOPort :: Word
> biCapIOPort = 7

> biCapIOSpace :: Word
> biCapIOSpace = 8

> biCapBIFrame :: Word
> biCapBIFrame = 9

> biCapITIPCBuf :: Word
> biCapITIPCBuf = 10

> biCapDynStart :: Word
> biCapDynStart = 11

> biFrameSizeBits :: Int
> biFrameSizeBits = pageBits

Warning: rootCNodeSizeBits should be rootCNodeSize + objBits (undefined::CTE)

> rootCNodeSizeBits :: Int
> rootCNodeSizeBits = 12 -- FIXME: duplication (maybe, check)



\subsection{Default Bootinfo}

> nopBIFrameData :: BIFrameData
> nopBIFrameData = BIFrameData {
> bifNodeID = 0, -- Initialized in createIPCBufferFrame
> bifNumNodes = 0, -- Initialized in createIPCBufferFrame
> bifNumIOPTLevels = 0, -- Initialized with 0 if fine
> bifIPCBufVPtr =0, -- Initialized in createIPCBufferFrame
> bifNullCaps = [],
> bifSharedFrameCaps = [], -- ARM no multikernel
> bifUIFrameCaps = [], -- Initialized in createFramesOfRegion
> bifUIPTCaps = [], -- Initialized in createITPDPTs
> bifUntypedObjCaps = [],
> bifUntypedObjPAddrs = [],
> bifUntypedObjSizeBits = [],
> bifITCNodeSizeBits = fromIntegral rootCNodeSizeBits, -- Initialized here is fine
> bifNumDeviceRegions = 0,
> bifDeviceRegions = []
> }


Functions for serialize BIFrameData into Memory

> data SerialData = SerialData {ptrCursor::PPtr Word,value::Word}
> type Serializer = StateT SerialData MachineMonad

> serializeStore :: Word -> Int -> Serializer ()
> serializeStore value intsize = do
> forM_ [0 .. intsize-1] $ \size -> do

Warning: For little endian system we should use this size instead of intsize - size - 1

> byte <- return $ (value `shiftR` (8 * (intsize - size -1))) .&. ((bit 8) - 1)
> serializeByte byte

> serializeByte :: Word -> Serializer ()
> serializeByte input = do
> ptr <- gets ptrCursor
> byte <- gets value
> value <- return $ input .|. ((fromIntegral byte) `shiftL` 8)
> if (ptr .&. 3) == 3
> then do
> lift $ storeWordVM ((ptr `shiftR` 2) `shiftL` 2) value
> modify (\st -> st {ptrCursor = ptr + 1, value = 0})
> else
> modify (\st -> st {ptrCursor = ptr + 1, value = value})

> paddingTo :: PPtr Word -> Serializer()
> paddingTo pptr = do
> ptr <- gets ptrCursor
> (flip mapM_) [ptr .. pptr-1] $ \_ -> (serializeByte 0)

> maxBIUntypedCaps :: Word
> maxBIUntypedCaps = 167

> maxBIDeviceRegions :: Word
> maxBIDeviceRegions = 200

> serialBIDeviceRegion :: BIDeviceRegion -> Serializer ()
> serialBIDeviceRegion biDeviceRegion = do
> serializeStore (fromPAddr $ bidrBasePAddr biDeviceRegion) 4
> serializeStore (fromIntegral $ bidrFrameSizeBits biDeviceRegion) 4
> slotRegion <- return $ bidrFrameCaps biDeviceRegion
> let (a,b) = case slotRegion of SlotRegion (a,b) -> (a,b)
> serializeStore a 4
> serializeStore b 4
> return ()

The function syncBIFrame is used as the last step in KernelInit.
It will write boot info back into the memory.

> syncBIFrame :: KernelInit ()
> syncBIFrame = do
> frameData <- gets $ initBootInfo
> frame <- gets $ initBootInfoFrame
> doKernelOp $ doMachineOp $ do
> (flip runStateT) (SerialData {ptrCursor = ptrFromPAddr $ frame,value = 0}) $ do
> serializeStore (fromIntegral (bifNodeID frameData)) 4
> serializeStore (fromIntegral (bifNumNodes frameData)) 4
> serializeStore (fromIntegral (bifNumIOPTLevels frameData)) 4
> serializeStore (fromIntegral $ fromVPtr $ (bifIPCBufVPtr frameData)) 4
> let serializeRange = \ls -> if ls == []
> then do
> serializeStore 0 4
> serializeStore 0 4
> else do
> serializeStore (head ls) 4
> serializeStore (last ls) 4
> serializeRange $ bifNullCaps frameData
> serializeRange $ bifSharedFrameCaps frameData
> serializeRange $ bifUIFrameCaps frameData
> serializeRange $ bifUIPTCaps frameData
> serializeRange $ bifUntypedObjCaps frameData

> ptr <- gets ptrCursor
> ptr <- return $ ptr + (PPtr $ maxBIUntypedCaps `shiftL` 2)
> untypedAddrs <- return $ bifUntypedObjPAddrs frameData
> (flip mapM_) untypedAddrs $ \addr -> do
> serializeStore (fromPAddr addr) 4
> paddingTo ptr
> ptr <- return $ ptr + (PPtr maxBIUntypedCaps)
> untypedSizeBits <- return $ bifUntypedObjSizeBits frameData
> (flip mapM_) untypedSizeBits $ \bits -> do
> serializeStore (fromIntegral bits) 1
> paddingTo ptr
> serializeStore (fromIntegral $ bifITCNodeSizeBits frameData) 1
> serializeStore (fromIntegral $ bifNumDeviceRegions frameData) 4
> (flip mapM_) (bifDeviceRegions frameData) $ \region -> do
> serialBIDeviceRegion region
> return ()

The KernelInit monad can fail - however, we do not care what type of failure occurred, only that a failure has happened.

> isAligned x n = x .&. mask n == 0

Loading

0 comments on commit 8664ae4

Please sign in to comment.