1139749Simp% 2116491Sharti% Copyright 2014, General Dynamics C4 Systems 3116491Sharti% 4116491Sharti% This software may be distributed and modified according to the terms of 5116491Sharti% the GNU General Public License version 2. Note that NO WARRANTY is provided. 6116491Sharti% See "LICENSE_GPLv2.txt" for details. 7116491Sharti% 8116491Sharti% @TAG(GD_GPL) 9116491Sharti% 10116491Sharti 11116491ShartiThis module defines the instances of "PSpaceStorable" objects. 12116491Sharti 13116491Sharti\begin{impdetails} 14116491Sharti 15116491ShartiThis module uses the C preprocessor to select a target architecture. 16116491Sharti 17116491Sharti> {-# LANGUAGE CPP #-} 18116491Sharti 19116491Sharti\end{impdetails} 20116491Sharti 21116491Sharti> module SEL4.Object.Instances where 22116491Sharti 23116491Sharti\begin{impdetails} 24116491Sharti 25116491Sharti> import SEL4.API.Types 26116491Sharti> import SEL4.Machine 27116491Sharti> import SEL4.Object.Structures 28116491Sharti> import SEL4.Model.PSpace 29116491Sharti> import SEL4.Model.StateData 30116491Sharti> import SEL4.Object.Instances.TARGET() 31116491Sharti> import SEL4.Config 32116491Sharti 33116491Sharti> import Data.Bits 34116519Sharti 35116519Sharti\end{impdetails} 36116519Sharti 37116491Sharti\subsection{Type Class Instances} 38116491Sharti 39116491ShartiThe following are the instances of "Storable" for the four main types of kernel object: synchronous IPC endpoints, notification objects, thread control blocks, and capability table entries. 40116491Sharti 41116491Sharti\subsubsection{Synchronous IPC Endpoint} 42116491Sharti 43116491Sharti> instance PSpaceStorable Endpoint where 44116491Sharti> makeObject = IdleEP 45116491Sharti> injectKO = KOEndpoint 46116491Sharti> projectKO o = case o of 47116491Sharti> KOEndpoint e -> return e 48116491Sharti> _ -> typeError "Endpoint" o 49116491Sharti 50116491Sharti\subsubsection{Notification objects} 51116491Sharti 52116491Sharti> instance PSpaceStorable Notification where 53116491Sharti> makeObject = NTFN IdleNtfn Nothing 54116491Sharti> injectKO = KONotification 55116491Sharti> projectKO o = case o of 56116491Sharti> KONotification e -> return e 57116491Sharti> _ -> typeError "Notification" o 58116491Sharti 59116491Sharti\subsubsection{Capability Table Entry} 60116491Sharti 61116491Sharti> instance PSpaceStorable CTE where 62116491Sharti> makeObject = CTE { 63116491Sharti> cteCap = NullCap, 64116491Sharti> cteMDBNode = nullMDBNode } 65116491Sharti> injectKO = KOCTE 66116491Sharti> projectKO o = case o of 67116491Sharti> KOCTE e -> return e 68116491Sharti> _ -> typeError "CTE" o 69116491Sharti 70119280Simp\begin{impdetails} 71119280SimpAs mentioned in the documentation for the type class "PSpaceStorable", there is one kernel object which needs its own definitions for "loadObject" and "storeObject"; it is the capability table entry. The reason for this is that thread control blocks contain capability table entries for the root of the capability and page tables; the capability copy and revocation functions need to access those "CTE"s while unaware that they are actually inside a "TCB". So the "CTE" versions of "loadObject" and "storeObject" must be able to handle accesses to "TCB"s as well. 72116491Sharti\end{impdetails} 73116491Sharti 74116491Sharti> loadObject ptr ptr' next obj = case obj of 75116491Sharti> KOCTE cte -> do 76116491Sharti> unless (ptr == ptr') $ fail "no CTE found in pspace at address" 77116491Sharti> alignCheck ptr (objBits cte) 78116491Sharti> sizeCheck ptr next (objBits cte) 79116491Sharti> return cte 80116491Sharti> KOTCB tcb -> do 81116491Sharti> alignCheck ptr' (objBits tcb) 82116491Sharti> sizeCheck ptr' next (objBits tcb) 83116491Sharti> offsetReturn (ptr - ptr') tcb 84116491Sharti> _ -> typeError "CTE" obj 85116491Sharti> where 86116491Sharti> toOffset slot = slot `shiftL` objBits (undefined :: CTE) 87116491Sharti> offsetReturn x tcb 88116491Sharti> | x == toOffset tcbVTableSlot = return $ tcbVTable tcb 89116491Sharti> | x == toOffset tcbCTableSlot = return $ tcbCTable tcb 90116491Sharti> | x == toOffset tcbReplySlot = return $ tcbReply tcb 91116491Sharti> | x == toOffset tcbCallerSlot = return $ tcbCaller tcb 92116491Sharti> | x == toOffset tcbIPCBufferSlot = 93116491Sharti> return $ tcbIPCBufferFrame tcb 94116491Sharti> | otherwise = fail "incorrect CTE offset into TCB" 95116491Sharti 96116491Sharti> updateObject cte oldObj ptr ptr' next = case oldObj of 97116491Sharti> KOCTE _ -> do 98116491Sharti> unless (ptr == ptr') $ fail "no CTE found in pspace at address" 99116491Sharti> alignCheck ptr (objBits cte) 100116491Sharti> sizeCheck ptr next (objBits cte) 101116491Sharti> return (KOCTE cte) 102116491Sharti> KOTCB tcb -> do 103116491Sharti> alignCheck ptr' (objBits tcb) 104116491Sharti> sizeCheck ptr' next (objBits tcb) 105116491Sharti> offsetAdjust (ptr - ptr') tcb 106116491Sharti> _ -> typeError "CTE" oldObj 107116491Sharti> where 108116491Sharti> toOffset slot = slot `shiftL` objBits (undefined :: CTE) 109116491Sharti> offsetAdjust x tcb 110116491Sharti> | x == toOffset tcbVTableSlot 111116491Sharti> = return $ KOTCB (tcb {tcbVTable = cte}) 112116491Sharti> | x == toOffset tcbCTableSlot 113116491Sharti> = return $ KOTCB (tcb {tcbCTable = cte}) 114116491Sharti> | x == toOffset tcbReplySlot 115116491Sharti> = return $ KOTCB (tcb { tcbReply = cte }) 116116491Sharti> | x == toOffset tcbCallerSlot 117116491Sharti> = return $ KOTCB (tcb { tcbCaller = cte }) 118116491Sharti> | x == toOffset tcbIPCBufferSlot 119148887Srwatson> = return $ KOTCB (tcb { tcbIPCBufferFrame = cte }) 120116491Sharti> | otherwise = fail "incorrect CTE offset into TCB" 121116491Sharti 122116491Sharti\subsubsection{Thread Control Block} 123116491Sharti 124116491ShartiThe value of "objBits" in this instance is an estimate; the value used in real implementations may vary and may be architecture-dependent. 125116491ShartiBy default, new threads are unable to change the security domains of other threads. They are later placed in the correct security domain by "createObject". 126116491Sharti 127116491Sharti> instance PSpaceStorable TCB 128116491Sharti> where 129116491Sharti> makeObject = Thread { 130116491Sharti> tcbCTable = makeObject, 131116491Sharti> tcbVTable = makeObject, 132116491Sharti> tcbReply = makeObject, 133116491Sharti> tcbCaller = makeObject, 134116491Sharti> tcbIPCBufferFrame = makeObject, 135116491Sharti> tcbDomain = minBound, 136116491Sharti> tcbState = Inactive, 137116491Sharti> tcbMCP = minBound, 138116491Sharti> tcbPriority = minBound, 139116491Sharti> tcbQueued = False, 140116491Sharti> tcbFault = Nothing, 141116491Sharti> tcbTimeSlice = timeSlice, 142116491Sharti> tcbFaultHandler = CPtr 0, 143116491Sharti> tcbIPCBuffer = VPtr 0, 144116491Sharti> tcbBoundNotification = Nothing, 145116491Sharti> tcbArch = newArchTCB } 146116491Sharti> injectKO = KOTCB 147116491Sharti> projectKO o = case o of 148116491Sharti> KOTCB tcb -> return tcb 149116491Sharti> _ -> typeError "TCB" o 150116491Sharti 151116491Sharti\subsubsection{User Data} 152116491Sharti 153116491Sharti> instance PSpaceStorable UserData where 154116491Sharti> makeObject = UserData 155116491Sharti> injectKO _ = KOUserData 156116491Sharti> projectKO o = case o of 157116491Sharti> KOUserData -> return UserData 158116491Sharti> _ -> typeError "UserData" o 159116491Sharti 160116491Sharti> instance PSpaceStorable UserDataDevice where 161116491Sharti> makeObject = UserDataDevice 162118598Sharti> injectKO _ = KOUserDataDevice 163116491Sharti> projectKO o = case o of 164116491Sharti> KOUserDataDevice -> return UserDataDevice 165116491Sharti> _ -> typeError "UserDataDevice" o 166116491Sharti 167116491Sharti 168116491Sharti 169116491Sharti