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