18
|
1 # CbCインターフェースによる CbCXv6 の書き換え
|
|
2 - 並列信頼研
|
|
3 - 桃原 優
|
|
4
|
|
5 ---
|
|
6
|
21
|
7 # 概要
|
|
8 - OS の信頼性を保証したい
|
|
9 - メタレベルを記述できる CbC で OS の開発
|
|
10 - インターフェースの導入
|
|
11 - 煩雑な記述の解消
|
|
12 - Agdaによる証明のため
|
18
|
13
|
|
14 ---
|
|
15
|
|
16 # OS の信頼性の重要性
|
|
17 - OS のバグは日常生活に支障をきたす
|
|
18 - パスワードなしで root にアクセスできるバグ
|
|
19 - 日付設定でコンピュータが壊れる
|
|
20 - -> OS自体に信頼性が求められる
|
|
21
|
|
22 ---
|
|
23
|
21
|
24 # OS の検証
|
18
|
25
|
|
26 - 全てのOSのコードに対して検証を行うのは困難
|
|
27 - 複雑な機能が多い
|
|
28 - 短期間のアップデート
|
|
29
|
|
30 - ユーザーが検証を行うこともできない
|
|
31 - 資源管理はOSが行なってる
|
|
32 - そもそも資源管理が複雑
|
|
33 - アクセスされたり書き換えられるリスク
|
|
34
|
|
35 ---
|
|
36
|
|
37 # メタレベルとノーマルレベル
|
|
38 - ノーマルレベル
|
|
39 - ユーザーがプログラミング言語によって記述する部分の処理
|
|
40 - メタレベル
|
|
41 - ユーザーが記述しないOS 側の処理
|
|
42 - CPU
|
|
43 - メモリ
|
|
44
|
|
45 ---
|
|
46
|
|
47 # Continuation based C
|
|
48 - ノーマルレベルとメタレベルの処理を同じ言語で行えるようにした言語(以下CbC)
|
|
49 - Code Gear
|
|
50 - 基本的な処理の単位
|
|
51 - Data Gear
|
|
52 - データの単位
|
|
53
|
|
54 ---
|
|
55
|
|
56 # goto による継続
|
|
57
|
|
58 - Code Gear の処理の間を goto によって遷移していく
|
|
59
|
|
60 ![](https://i.imgur.com/etfQund.png)
|
|
61
|
19
|
62
|
18
|
63 ---
|
|
64
|
|
65 # Data Gear の継続
|
|
66 - goto の際に Data Gear も継続される
|
|
67
|
|
68 ![](https://i.imgur.com/3E0DGWA.png)
|
|
69
|
|
70 ---
|
|
71
|
|
72 # Meta Code Gear
|
|
73 - 実際にはノーマルレベルの間にメタレベルの処理がある
|
|
74 - Meta Level では Data Gear の見え方は変わる(Meta Data Gear)
|
21
|
75 - 書き換えやアクセスを防ぐため
|
18
|
76
|
|
77 ![](https://i.imgur.com/vy0NxrG.png)
|
|
78
|
|
79 ---
|
|
80
|
|
81 # 状態遷移モデル
|
|
82 - goto の遷移によって状態遷移モデルに落とし込める
|
|
83 - Code Gear に対しての入力に対して期待される出力がされているかで検査して**信頼性を保証する**
|
|
84
|
|
85 ----
|
|
86
|
|
87 # Agda による検証
|
|
88 - モデル検査
|
|
89 - 定理証明支援系である Agda を用いる。
|
|
90 - Agda
|
21
|
91 - Hoare Logic という検証手法を扱える。
|
18
|
92
|
|
93 ---
|
|
94
|
21
|
95 # Hoare Logic
|
18
|
96 - 検証手法
|
|
97 - 事前条件を使ってある関数を実行して事後条件を満たすことを確認する
|
|
98 - CbCと相性がいい
|
|
99 - 継続に事前条件(Input Data Gear)と事後条件(Output Data Gear)を持たせることができる
|
|
100
|
|
101 ---
|
|
102
|
|
103 # Geas OS
|
|
104 - CbC を使って信頼性の保証と拡張性を持たせる Gears OS の開発を行なっている
|
|
105 - Xv6 という OS を参考に書き換えをしている
|
|
106
|
|
107 ---
|
|
108
|
|
109 # メモリ管理
|
|
110 - OS の信頼性の1つであるメモリ管理部分を CbC で書き換える
|
|
111 - Page のバリデーションチェック
|
|
112 - サンドボックスによるエクセプション
|
|
113
|
|
114 ---
|
|
115
|
|
116 # インターフェース
|
|
117 - 書き換えを防ぐために見える Data Gear に違いが生じる
|
|
118 - -> Gears OS のノーマルレベルからメタレベルの記述が記述が煩雑になるためインターフェースを導入
|
21
|
119 - インターフェースによる他のメリット
|
18
|
120 - 煩雑な記述の解消
|
|
121 - 機能の入れ替え
|
|
122 - Agda による証明
|
|
123
|
|
124 ---
|
|
125
|
|
126 # CbC による Gears OS の開発
|
|
127
|
|
128 ---
|
|
129
|
|
130 # Context
|
21
|
131 - Meta Data Gear
|
|
132 - Code Gear
|
|
133 - Data Gear のリスト
|
|
134 - Data Gear を確保するメモリ空間
|
|
135 - スレッドやプロセスに対応
|
|
136 - ノーマルレベルに必要な処理のみ Code Gear に渡す
|
|
137 - Meta Code Gear は Perlスクリプトで自動生成
|
|
138 - 継続先を変えることで機能を置き換えることも可能
|
18
|
139
|
|
140 ---
|
|
141
|
|
142 # Xv6
|
|
143 - MIT の講義用教材として作られたOS
|
|
144 - 企画課される前のCで書かれたUNIX V6 を書き換えた
|
|
145 - 1万行程の軽量なOS
|
|
146 - Linuxだと数千万行
|
|
147 - Xv6 を参考に CbC で書き直すことで Gears OS を実装する
|
|
148
|
|
149 ---
|
|
150
|
|
151 # カーネル空間
|
|
152 - OS の中核となるプログラムで Meta Level に相当する
|
|
153 - Xv6 ではカーネルとユーザープログラムは分離されている
|
|
154 - ユーザープログラムはカーネルに直接アクセスできない。
|
|
155 - 書き換えやアクセスを防ぐため
|
|
156 - 呼び出す場合は system call
|
|
157
|
|
158 ---
|
|
159
|
|
160 # カーネルが提供するもの
|
|
161 - プロセス管理
|
|
162 - メモリ管理
|
|
163 - ファイル管理
|
|
164 - I/O, read, write
|
|
165
|
|
166
|
|
167 ---
|
|
168
|
|
169 # カーネルの保護機構
|
|
170 - CPUのハードウェア保護機構を持っている
|
|
171 - ユーザー空間で実行されているプロセスが自身のメモリのみアクセスできるように保護
|
|
172 - system call
|
|
173 - ハードウェアが一時的に特権レベルをあげ、カーネルのプログラムが実行される
|
|
174
|
|
175 ---
|
|
176
|
|
177 # system call
|
|
178 - system call 呼び出し
|
|
179 - トラップ の発生
|
|
180 - ユーザープログラムの中断
|
|
181 - 処理がカーネルに切り替わる
|
|
182
|
|
183 ---
|
|
184
|
|
185 # Xv6-rpi
|
|
186 - Xv6 は Arm のバイナリを出力するので様々なハードウェアで動かすことができる
|
|
187 - Raspberry Pi
|
|
188 - 携帯電話
|
21
|
189 - 実際にRaspberry Pi で動かすために xv6-rpi を用意して動作しているか確認中
|
|
190 - CbCxv6 とは別のプロジェクト
|
18
|
191
|
|
192 ---
|
|
193
|
|
194 # CbCXv6 での Paging
|
|
195 - OS の信頼性の1つであるメモリ管理部分の書き換えについて説明
|
|
196
|
|
197 ---
|
|
198
|
|
199 # 実メモリの直接操作
|
|
200 - 実メモリを直接扱うと様々な問題が生じる
|
|
201 - ユーザープログラムで空いているメモリ番地を探す必要
|
|
202 - フラグメンテーションが起こる
|
|
203 - メモリ間に扱うには小さな隙間ができる
|
|
204
|
|
205 ---
|
|
206
|
|
207 # Paging
|
|
208 - メモリ管理の手法
|
|
209 - Page と呼ばれる固定長のブロックに分割して、メモリとスワップ領域で Page を入れ替えて管理
|
|
210 - 仮想メモリとして扱うことでフラグメンテーションの解消と空き番地を探す必要がなくなる
|
|
211
|
|
212 ---
|
|
213
|
|
214 # Pagingの図
|
|
215 - 必要?
|
21
|
216 ![](https://i.imgur.com/ZNxOsNf.png)
|
|
217
|
18
|
218
|
|
219 ---
|
|
220
|
|
221 # メタレベルでの Paging の操作
|
|
222 - Page Table に相当するデータを Input Data Gear で受け取って変更した後、Context にある Meta Data Gear に goto で遷移してアクセス
|
|
223 - メタレベルで処理することで本来カーネル側の処理である Page Table を操作できる
|
|
224
|
|
225 ---
|
|
226
|
|
227 # Paging の信頼性
|
|
228 - Input Data Gear に対しての Output Data Gear をバリデーションチェックすることで他のプロセスから書き換えられることを防ぐ
|
|
229 - サンドボックス
|
|
230 - 他のプロセスから書き換えられた時にエクセプションを飛ばす
|
|
231
|
|
232 ---
|
|
233
|
|
234 # Paging の書き換え
|
|
235 - Xv6 では実メモリから仮想メモリの変換をvm.cで行なっている。
|
|
236 - 次の章で書き換えについて説明する
|
|
237
|
|
238
|
|
239
|
|
240 ---
|
|
241
|
19
|
242 # CbC インターフェースの導入
|
|
243 - 継続の記述が煩雑になる
|
|
244 - Code Gear がどの Data Gear の番号に対応するか指定する必要がある
|
|
245 - ノーマルレベルとメタレベルで Data Gear の見え方が異なるため調整する必要がある
|
|
246 - ->インターフェースの導入
|
|
247
|
|
248
|
|
249 ---
|
|
250
|
|
251 # CbC インターフェース
|
|
252 - インターフェースは Data Gear に対しての操作を行う Code Gear
|
|
253 - 実装は別で定義し、呼び出す
|
|
254 - インターフェースによって機能を置き換えることができる
|
|
255
|
|
256 ---
|
|
257
|
|
258 # インターフェースの定義
|
|
259 - Data Gear と Data Gear に対して操作を行う Code Gear の集合を表現する **Meta Data Gear**
|
|
260
|
|
261 ---
|
|
262
|
|
263 # インターフェースのソースコード
|
|
264 - vm.c をインターフェースで書き換えた vm.h のコードの説明をしていく
|
|
265
|
|
266
|
|
267 ---
|
|
268
|
|
269
|
|
270 # 実装名の定義
|
|
271 - typedef struct の直後に実装名(vm)を書く
|
|
272
|
|
273
|
|
274 ``` c
|
|
275 typedef struct vm<Type,Impl> {
|
|
276 ```
|
|
277
|
|
278 ---
|
|
279
|
|
280 # Code Gear の定義
|
|
281 - Code Gear は __Code CodeGear名(引数); で記述する
|
|
282 - 第1引数の Impl* vm が Code Gear の型になる
|
|
283 - 初期化された Data Gear が それぞれの Code Gear の引数として扱われる
|
|
284 - 例)定義された uinit が kpt_freerange の Code Gear の第1引数と対応している
|
|
285
|
|
286
|
|
287 ``` c
|
21
|
288 typedef struct vm<Type,Impl> {
|
19
|
289 __code init_vmm(Impl* vm, __code next(...));
|
|
290 __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...));
|
|
291 __code kpt_alloc(Impl* vm ,__code next(...));
|
|
292 __code switchuvm(Impl* vm ,struct proc* p, __code next(...));
|
|
293 __code init_inituvm(Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...));
|
|
294 __code loaduvm(Impl* vm,pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...));
|
|
295 __code allocuvm(Impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...));
|
|
296
|
|
297 ```
|
|
298
|
|
299 ---
|
|
300
|
|
301
|
|
302 # next(...)
|
|
303 - __code next(...) は条件分岐によって複数の継続先が設定される
|
|
304 - それぞれの Code Gear の引数の1つに設定する
|
|
305 ``` c
|
|
306 __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...));
|
|
307 ....
|
|
308 __code next(...);
|
|
309 } vm;
|
|
310 ```
|
|
311
|
|
312 ---
|
|
313
|
|
314 # インターフェースの実装
|
|
315 - インターフェースの実装は別ファイルで定義する(vm_impl.cbc)
|
|
316 - ヘッダーファイルの呼び出しは #include ではなく #interface で呼び出す
|
|
317
|
|
318 ``` c
|
|
319 #include "../../context.h"
|
|
320 #interface "vm.h"
|
|
321
|
|
322 ```
|
|
323
|
|
324
|
|
325 ---
|
|
326
|
|
327 # create_impl
|
|
328 - create_imple の関数内で vm の型を定義し、vm->CodeGear名 で対応させていく
|
|
329 - 実装を Code Gear で記述していく。
|
|
330
|
|
331
|
|
332 ``` c
|
|
333
|
|
334 vm* createvm_impl(struct Context* cbc_context) {
|
|
335 struct vm* vm = new vm();
|
|
336 ....
|
|
337 vm->void_ret = C_vm_void_ret;
|
|
338 vm->init_vmm = C_init_vmmvm_impl;
|
|
339 vm->kpt_freerange = C_kpt_freerangevm_impl;
|
|
340 vm->kpt_alloc = C_kpt_allocvm_impl;
|
|
341 ...
|
|
342 __code init_vmmvm_impl(struct vm_impl* vm,__code next(...)) {
|
|
343 initlock(&kpt_mem.lock, "vm");
|
|
344 kpt_mem.freelist = NULL;
|
|
345
|
|
346 goto next(...);
|
|
347 }
|
|
348 ```
|
|
349
|
|
350 ---
|
|
351
|
|
352 # private
|
|
353 - CbC は信頼性を保証するためにそれぞれの Code Gear を細かくする必要があるので、for文やif文がある場合はさらに実装を分ける
|
|
354 - Code Gear は基本的にインターフェースで指定された Code Gear 内からのみ継続さ れるため、Java の private メソッドのように扱われる。
|
|
355 - 実際に vm.c の loaduvm の実装を分けた記述を説明する
|
|
356
|
|
357
|
|
358 ``` c
|
|
359 int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
|
|
360 {
|
|
361 uint i, pa, n;
|
|
362 pte_t *pte;
|
|
363
|
|
364 if ((uint) addr % PTE_SZ != 0) {
|
|
365 panic("loaduvm: addr must be page aligned");
|
|
366 }
|
|
367
|
|
368 for (i = 0; i < sz; i += PTE_SZ) {
|
|
369 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
|
|
370 panic("loaduvm: address should exist");
|
|
371 }
|
|
372
|
|
373 pa = PTE_ADDR(*pte);
|
|
374
|
|
375 if (sz - i < PTE_SZ) {
|
|
376 n = sz - i;
|
|
377 } else {
|
|
378 n = PTE_SZ;
|
|
379 }
|
|
380
|
|
381 if (readi(ip, p2v(pa), offset + i, n) != n) {
|
|
382 return -1;
|
|
383 }
|
|
384 }
|
|
385
|
|
386 return 0;
|
|
387 }
|
|
388 ```
|
|
389
|
|
390 ---
|
|
391
|
|
392 # goto private
|
|
393 - vm と同じ create_impl 内で vm_impl を定義し、private で実装する Code Gear を定義する
|
|
394 - loaduvmvm_impl で goto によって private に遷移する
|
|
395
|
|
396
|
|
397 ``` c
|
|
398 vm* createvm_impl(struct Context* cbc_context) {
|
|
399 ...
|
|
400 struct vm_impl* vm_impl = new vm_impl();
|
|
401 ...
|
|
402 vm_impl->loaduvm_ptesize_check = C_loaduvm_ptesize_checkvm_impl;
|
|
403 ....
|
|
404 vm->loaduvm = C_loaduvmvm_impl;
|
|
405 ....
|
|
406 }
|
|
407
|
|
408 __code loaduvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)) {
|
|
409 Gearef(cbc_context, vm_impl)->pgdir = pgdir;
|
|
410 Gearef(cbc_context, vm_impl)->addr = addr;
|
|
411 Gearef(cbc_context, vm_impl)->ip = ip;
|
|
412 Gearef(cbc_context, vm_impl)->offset = offset;
|
|
413 Gearef(cbc_context, vm_impl)->sz = sz;
|
|
414 Gearef(cbc_context, vm_impl)->next = next;
|
|
415
|
|
416 goto loaduvm_ptesize_checkvm_impl(vm, next(...));
|
|
417 }
|
|
418 ```
|
|
419 ---
|
|
420
|
|
421 # private のヘッダー
|
|
422 - private 側のヘッダーファイルも vm_impl と同じように用意する
|
|
423
|
|
424 ``` c
|
|
425 typedef struct vm_impl<Impl, Isa> impl vm{
|
|
426 ...
|
|
427 __code loaduvm_ptesize_check(Type* vm_impl, uint i, pte_t* pte, uint sz,
|
|
428 __code next(int ret, ...));
|
|
429 ```
|
|
430
|
|
431 ---
|
|
432
|
|
433 # private の記述
|
|
434
|
|
435 ``` c
|
|
436 #interface "vm_impl.h"
|
|
437
|
|
438 __code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
439 char* addr = vm_impl->addr;
|
|
440
|
|
441 if ((uint) addr %PTE_SZ != 0) {
|
|
442 // goto panic
|
|
443 }
|
|
444
|
|
445 goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
|
|
446 }
|
|
447 ```
|
|
448
|
|
449 - vm.cではここから for だが CbC は if文の中と外にgoto を用意して実装する
|
|
450
|
|
451 ![](https://i.imgur.com/ByA7GVJ.png)
|
|
452
|
|
453 ```c
|
|
454 __code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
455 uint i = vm_impl->i;
|
|
456 uint sz = vm_impl->sz;
|
|
457
|
|
458 if (i < sz) {
|
|
459 goto loaduvm_check_pgdir(vm_impl, next(ret, ...));
|
|
460 }
|
|
461
|
|
462 goto loaduvm_exit(vm_impl, next(ret, ...));
|
|
463 }
|
|
464
|
|
465
|
|
466 __code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
467 pte_t* pte = vm_impl->pte;
|
|
468 pde_t* pgdir = vm_impl->pgdir;
|
|
469 uint i = vm_impl->i;
|
|
470 char* addr = vm_impl->addr;
|
|
471 uint pa = vm_impl->pa;
|
|
472
|
|
473 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
|
|
474 // goto panic
|
|
475 }
|
|
476 pa = PTE_ADDR(*pte);
|
|
477
|
|
478 vm_impl->pte = pte;
|
|
479 vm_impl->pgdir = pgdir;
|
|
480 vm_impl->addr = addr;
|
|
481 vm_impl->pa = pa;
|
|
482
|
|
483 goto loaduvm_check_PTE_SZ(vm_impl, next(ret, ...));
|
|
484 }
|
|
485
|
|
486 __code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
487 uint sz = vm_impl->sz;
|
|
488 uint i = vm_impl->i;
|
|
489 uint n = vm_impl->n;
|
|
490 struct inode* ip = vm_impl->ip;
|
|
491 uint pa = vm_impl->pa;
|
|
492 uint offset = vm_impl->offset;
|
|
493
|
|
494 if (sz - i < PTE_SZ) {
|
|
495 n = sz - i;
|
|
496 } else {
|
|
497 n = PTE_SZ;
|
|
498 }
|
|
499
|
|
500 if (readi(ip, p2v(pa), offset + i, n) != n) {
|
|
501 ret = -1;
|
|
502 goto next(ret, ...);
|
|
503 }
|
|
504
|
|
505 vm_impl->n = n;
|
|
506
|
|
507 goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
|
|
508 }
|
|
509
|
|
510 __code loaduvm_exit(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
511 ret = 0;
|
|
512 goto next(ret, ...);
|
|
513 }
|
|
514 ```
|
18
|
515
|
|
516
|
|
517
|
19
|
518 ``` c
|
|
519
|
|
520 int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
|
|
521 {
|
|
522 uint i, pa, n;
|
|
523 pte_t *pte;
|
|
524
|
|
525 if ((uint) addr % PTE_SZ != 0) {
|
|
526 panic("loaduvm: addr must be page aligned");
|
|
527 }
|
|
528
|
|
529 for (i = 0; i < sz; i += PTE_SZ) {
|
|
530 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
|
|
531 panic("loaduvm: address should exist");
|
|
532 }
|
|
533
|
|
534 pa = PTE_ADDR(*pte);
|
|
535
|
|
536 if (sz - i < PTE_SZ) {
|
|
537 n = sz - i;
|
|
538 } else {
|
|
539 n = PTE_SZ;
|
|
540 }
|
|
541
|
|
542 if (readi(ip, p2v(pa), offset + i, n) != n) {
|
|
543 return -1;
|
|
544 }
|
|
545 }
|
|
546
|
|
547 return 0;
|
|
548 }
|
|
549 ```
|
|
550
|
|
551
|
|
552 # インターフェースの呼び出し
|
|
553 - 定義したインターフェースの呼び出しについて説明する
|
|
554 - CbC の場合 goto による 遷移を行うので、関数呼び出しのように goto 以降のコードを実行できない
|
|
555 - 例) goto すると戻ってこれないため それ以降が実行されなくなる。
|
|
556
|
|
557 ``` c
|
|
558 void userinit(void)
|
|
559 {
|
|
560 struct proc* p;
|
|
561 extern char _binary_initcode_start[], _binary_initcode_size[];
|
|
562
|
|
563 p = allocproc();
|
|
564 initContext(&p->cbc_context);
|
|
565
|
|
566 initproc = p;
|
|
567
|
|
568 if((p->pgdir = kpt_alloc()) == NULL) {
|
|
569 panic("userinit: out of memory?");
|
|
570 }
|
|
571
|
|
572 goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
|
|
573 p->sz = PTE_SZ;
|
|
574
|
|
575 // craft the trapframe as if
|
|
576 memset(p->tf, 0, sizeof(*p->tf));
|
|
577 ~
|
|
578 ```
|
|
579
|
|
580 # 呼び出しの解決
|
|
581 - 最初の命令は next で戻ってこれるので、dummy の関数を用意してそこで実行する
|
|
582
|
|
583 ``` c
|
|
584 void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[])
|
|
585 {
|
|
586 // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
|
|
587 goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
|
|
588
|
|
589 }
|
|
590
|
|
591
|
|
592
|
|
593 __ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip
|
|
594
|
|
595 struct vm* vm = createvm_impl(cbc_context);
|
|
596 // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret);
|
|
597 Gearef(cbc_context, vm)->vm = (union Data*) vm;
|
|
598 Gearef(cbc_context, vm)->pgdir = pgdir;
|
|
599 Gearef(cbc_context, vm)->init = init;
|
|
600 Gearef(cbc_context, vm)->sz = sz ;
|
|
601 Gearef(cbc_context, vm)->next = C_vm_void_ret ;
|
|
602 goto meta(cbc_context, vm->init_inituvm);
|
|
603 }
|
|
604
|
|
605
|
|
606 void userinit(void)
|
|
607 {
|
|
608 struct proc* p;
|
|
609 extern char _binary_initcode_start[], _binary_initcode_size[];
|
|
610
|
|
611 p = allocproc();
|
|
612 initContext(&p->cbc_context);
|
|
613
|
|
614 initproc = p;
|
|
615
|
|
616 if((p->pgdir = kpt_alloc()) == NULL) {
|
|
617 panic("userinit: out of memory?");
|
|
618 }
|
|
619
|
21
|
620 dummy(p, _binary_initcode_start, _binary_initcode_size);
|
|
621 ```
|
19
|
622
|
21
|
623
|