1 = Program Loading = 2 3 The provision of [[Paging|paging]] of file content leads to the possibility of 4 demand paging for programs, enabling them to be loaded into memory dynamically 5 and to have only the active portions of those programs resident. To achieve 6 this, programs must be appropriately initialised in new tasks, with a page 7 fault handler configured to provide program file content whenever a region of 8 the program payload is encountered that is not currently resident in memory. 9 10 <<TableOfContents(2,3)>> 11 12 == Program Initialisation == 13 14 To load and initialise a program, a new task must be created, defining a 15 separate address space for the program and allowing it to operate 16 independently of other programs. For a program to actually run, a thread of 17 execution must be created so that the program's instructions can be read and 18 processed. 19 20 == Internal Page Fault Handlers == 21 22 When satisfying page faults for a task, one approach involves situating the 23 page fault handler within the task itself, this managing the available memory 24 regions and employing receive windows when requesting memory pages. 25 26 The general arrangement involving such internal page fault handlers for a 27 program in a task is as follows: 28 29 ######## A graph showing the internal paging mechanism 30 31 {{{#!graphviz 32 #format svg 33 #transform notugly 34 digraph internal_paging { 35 node [fontsize="12.0",fontname="sans-serif",shape=box]; 36 edge [fontsize="12.0",fontname="sans-serif"]; 37 rankdir=LR; 38 39 TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"]; 40 41 subgraph { 42 rank=same; 43 44 InternalPager; 45 InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nsame task and\ndefines scope of\nfault resolution"]; 46 47 InternalPager -> InternalPager_note [dir=none,style=dotted]; 48 } 49 50 subgraph { 51 rank=same; 52 53 Regions [shape=record,label="Regions | 54 {<s> stack |<sd> stack-dataspace } | 55 {<d> data | <dd> data-dataspace } | 56 {<c> code |<cd> code-dataspace } |..."]; 57 58 ReceiveFlexpage [shape=note,label="Flexpage\n(receive window)"]; 59 60 Flexpage [shape=note]; 61 Flexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"]; 62 63 Flexpage -> Flexpage_note [dir=none,style=dotted]; 64 } 65 66 subgraph { 67 rank=same; 68 69 ResourceD [label="Resource\n(Pager)"]; 70 ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"]; 71 72 ResourceD -> ResourceD_note [dir=none,style=dotted]; 73 } 74 75 ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."]; 76 77 /* Page fault handling. */ 78 79 TaskMemory:d -> InternalPager [label="page fault"]; 80 81 InternalPager -> Regions:d [label="find region"]; 82 83 Regions:dd -> ResourceD [style=dashed]; 84 85 InternalPager -> ReceiveFlexpage [dir=none]; 86 ReceiveFlexpage -> ResourceD [label="map"]; 87 88 ResourceD -> ProgramFile:d [style=dashed]; 89 90 ResourceD -> Flexpage [dir=none]; 91 Flexpage -> InternalPager; 92 } 93 }}} 94 95 ######## 96 97 == External Page Fault Handlers == 98 99 Another approach is to employ an external page fault handler in the creating 100 task. When a page fault occurs, the external handler ensures that the 101 appropriate content has been brought into its own memory space. It then 102 returns a flexpage from the handler routine to resolve the fault. 103 104 ######## A graph showing the external paging mechanism 105 106 {{{#!graphviz 107 #format svg 108 #transform notugly 109 digraph external_paging { 110 node [fontsize="12.0",fontname="sans-serif",shape=box]; 111 edge [fontsize="12.0",fontname="sans-serif"]; 112 rankdir=LR; 113 114 TaskMemory [shape=record,label="Task Memory |<s> stack | ... |<d> data | ... |<c> code"]; 115 116 subgraph { 117 rank=same; 118 119 ExternalPager_note [shape=note,style=filled,fillcolor=gold,label="Resides in\nseparate task"]; 120 ExternalPager; 121 122 ExternalPager_note -> ExternalPager [dir=none,style=dotted]; 123 124 MappedFlexpage [shape=note,label="Flexpage\n(positioned)"]; 125 MappedFlexpage_note [shape=note,style=filled,fillcolor=gold,label="Satisfies\nmemory\naccess"]; 126 127 MappedFlexpage -> MappedFlexpage_note [dir=none,style=dotted]; 128 } 129 130 subgraph { 131 rank=same; 132 133 Regions [shape=record,label="Regions | 134 {<s> stack |<sd> stack-dataspace } | 135 {<d> data | <dd> data-dataspace } | 136 {<c> code |<cd> code-dataspace } |..."]; 137 138 L4Re [shape=ellipse,label="L4Re paging\nfunctionality"]; 139 L4Re_note [shape=note,style=filled,fillcolor=gold,label="Supports normal\naccess to file content"]; 140 141 L4Re -> L4Re_note [dir=none,style=dotted]; 142 143 Flexpage [shape=note]; 144 } 145 146 subgraph { 147 rank=same; 148 149 ResourceD [label="Resource\n(Pager)"]; 150 ResourceD_note [shape=note,style=filled,fillcolor=gold,label="Provides access\nto file content"]; 151 152 ResourceD -> ResourceD_note [dir=none,style=dotted]; 153 } 154 155 ProgramFile [shape=record,label="Program File | ... |<d> data |<c> code | ..."]; 156 157 /* Page fault handling. */ 158 159 TaskMemory:d -> ExternalPager [label="page fault"]; 160 161 ExternalPager -> Regions:d [label="find region"]; 162 163 Regions:dd -> ResourceD [style=dashed]; 164 165 ExternalPager -> L4Re; 166 L4Re -> ResourceD [label="map"]; 167 168 ResourceD -> ProgramFile:d [style=dashed]; 169 170 ResourceD -> Flexpage [dir=none]; 171 Flexpage -> ExternalPager; 172 173 ExternalPager -> MappedFlexpage [dir=none]; 174 MappedFlexpage -> TaskMemory:d; 175 } 176 }}} 177 178 ######## 179 180 This arrangement may be used to support a program deployed in a task. Since an 181 internal page fault handler is just another kind of program, this external 182 pager arrangement can be constrained to only supporting an internal page fault 183 handler deployed in a task. 184 185 == Configuring Programs == 186 187 To provide an internal page fault handler alongside an actual program to be 188 run, the following arrangement is used: 189 190 ######## A graph showing the configuration arrangement 191 192 {{{#!graphviz 193 #format svg 194 #transform notugly 195 digraph program_configuration { 196 node [fontsize="12.0",fontname="sans-serif",shape=box]; 197 edge [fontsize="12.0",fontname="sans-serif"]; 198 rankdir=LR; 199 200 subgraph { 201 rank=min; 202 203 CreatingTask_note [shape=note,style=filled,fillcolor=gold,label="Responsible for\ncreating the\nnew task"]; 204 CreatingTask [label="Creating task"]; 205 206 CreatingTask_note -> CreatingTask [dir=none,style=dotted]; 207 } 208 209 subgraph { 210 rank=max; 211 212 IPCGate_note [shape=note,style=filled,fillcolor=gold,label="Created for sharing\nbetween the tasks"]; 213 IPCGate [shape=octagon,label="IPC gate"]; 214 215 IPCGate_note -> IPCGate [dir=none,style=dotted]; 216 } 217 218 InitCaps [shape=record,label="<head> Initial capabilities | {<s> ENV_INTERNAL_PAGER_NAME |<c> capability }"]; 219 220 subgraph { 221 rank=same; 222 223 InternalPager; 224 InternalPager_note [shape=note,style=filled,fillcolor=gold,label="Starts and binds\nto IPC gate"]; 225 226 InternalPager -> InternalPager_note [dir=none,style=dotted]; 227 228 Program; 229 Program_note [shape=note,style=filled,fillcolor=gold,label="Starts and references\npager via IPC gate"]; 230 231 Program -> Program_note [dir=none,style=dotted]; 232 } 233 234 /* Create and transfer IPC gate for binding. */ 235 236 CreatingTask -> IPCGate [label="create"]; 237 CreatingTask -> InitCaps:head [label="define"]; 238 InitCaps:c -> IPCGate; 239 240 /* Thread initiation. */ 241 242 CreatingTask -> InternalPager [label="start"]; 243 InternalPager -> InitCaps:s [label="bind"]; 244 245 CreatingTask -> Program [label="start"]; 246 Program -> IPCGate -> InternalPager [style=dashed]; 247 } 248 }}} 249 250 ######## 251 252 The creating task performs the following operations: 253 254 1. Create an IPC gate for communication between the program and its pager. 255 256 1. Map the IPC gate into the created task to be accessible via a given 257 capability slot. 258 259 1. Define the IPC gate in the pager's initial capabilities using a 260 well-defined name, allowing the pager to look up the capability in its 261 environment. 262 263 1. Start the pager which itself obtains the IPC gate capability and binds to 264 it, making itself available as the pager for the program. 265 266 1. Set the pager of the program to the IPC gate as mapped within the task. 267 268 1. Start the program which is already configured to send page faults via the 269 IPC gate to the pager. 270 271 Upon starting, the program will encounter a page fault immediately, unless 272 some additional work was done to map memory pages into the task in advance. 273 The internal pager or page fault handler will attempt to resolve these faults 274 as they occur, being contacted by the kernel on the program's behalf.