comparison slide/CbCXv6.md @ 19:98cee2f6c919

slide
author tobaru
date Sat, 08 Feb 2020 15:06:50 +0900
parents afc36230cf4f
children 6d84ce92ff35
comparison
equal deleted inserted replaced
18:afc36230cf4f 19:98cee2f6c919
60 60
61 - Code Gear の処理の間を goto によって遷移していく 61 - Code Gear の処理の間を goto によって遷移していく
62 62
63 ![](https://i.imgur.com/etfQund.png) 63 ![](https://i.imgur.com/etfQund.png)
64 64
65
65 --- 66 ---
66 67
67 # Data Gear の継続 68 # Data Gear の継続
68 - goto の際に Data Gear も継続される 69 - goto の際に Data Gear も継続される
69 70
277 278
278 # 目次 279 # 目次
279 1. OS の信頼性の保証 280 1. OS の信頼性の保証
280 2. CbC による Gears OS の開発 281 2. CbC による Gears OS の開発
281 3. Xv6 282 3. Xv6
282 4. CbCXv6 での Paging** 283 4. CbCXv6 での Paging
283 5. **CbC インターフェース** 284 5. **CbC インターフェース**
284 6. 評価 285 6. 評価
285 7. まとめ  286 7. まとめ 
286 287
287 --- 288 ---
288 289
289 290 # CbC インターフェースの導入
290 291 - 継続の記述が煩雑になる
291 292 - Code Gear がどの Data Gear の番号に対応するか指定する必要がある
293 - ノーマルレベルとメタレベルで Data Gear の見え方が異なるため調整する必要がある
294 - ->インターフェースの導入
295
296
297 ---
298
299 # CbC インターフェース
300 - インターフェースは Data Gear に対しての操作を行う Code Gear
301 - 実装は別で定義し、呼び出す
302 - インターフェースによって機能を置き換えることができる
303
304 ---
305
306 # インターフェースの定義
307 - Data Gear と Data Gear に対して操作を行う Code Gear の集合を表現する **Meta Data Gear**
308
309 ---
310
311 # インターフェースのソースコード
312 - vm.c をインターフェースで書き換えた vm.h のコードの説明をしていく
313
314
315 ---
316
317
318 # 実装名の定義
319 - typedef struct の直後に実装名(vm)を書く
320
321
322 ``` c
323 typedef struct vm<Type,Impl> {
324 ```
325
326 ---
327
328 # Data Gear の定義
329 - 2行目から19行目で引数の Data Gear を定義している
330
331
332 ``` c
333 typedef struct vm<Type,Impl> {
334 union Data* vm;
335 uint low;
336 uint hi;
337 struct proc* p;
338 ....
339 ```
340
341 ---
342
343 # Code Gear の定義
344 - Code Gear は __Code CodeGear名(引数); で記述する
345 - 第1引数の Impl* vm が Code Gear の型になる
346 - 初期化された Data Gear が それぞれの Code Gear の引数として扱われる
347 - 例)定義された uinit が kpt_freerange の Code Gear の第1引数と対応している
348
349
350 ``` c
351 __code init_vmm(Impl* vm, __code next(...));
352 __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...));
353 __code kpt_alloc(Impl* vm ,__code next(...));
354 __code switchuvm(Impl* vm ,struct proc* p, __code next(...));
355 __code init_inituvm(Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...));
356 __code loaduvm(Impl* vm,pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...));
357 __code allocuvm(Impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...));
358
359 ....
360
361 ```
362
363 ---
364
365
366 # next(...)
367 - __code next(...) は条件分岐によって複数の継続先が設定される
368 - それぞれの Code Gear の引数の1つに設定する
369 ``` c
370 __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...));
371 ....
372 __code next(...);
373 } vm;
374 ```
375
376 ---
377
378 # インターフェースの実装
379 - インターフェースの実装は別ファイルで定義する(vm_impl.cbc)
380 - ヘッダーファイルの呼び出しは #include ではなく #interface で呼び出す
381
382 ``` c
383 #include "../../context.h"
384 #interface "vm.h"
385
386 ```
387
388
389 ---
390
391 # create_impl
392 - create_imple の関数内で vm の型を定義し、vm->CodeGear名 で対応させていく
393 - 実装を Code Gear で記述していく。
394
395
396 ``` c
397
398 vm* createvm_impl(struct Context* cbc_context) {
399 struct vm* vm = new vm();
400 ....
401 vm->void_ret = C_vm_void_ret;
402 vm->init_vmm = C_init_vmmvm_impl;
403 vm->kpt_freerange = C_kpt_freerangevm_impl;
404 vm->kpt_alloc = C_kpt_allocvm_impl;
405 ...
406 __code init_vmmvm_impl(struct vm_impl* vm,__code next(...)) {
407 initlock(&kpt_mem.lock, "vm");
408 kpt_mem.freelist = NULL;
409
410 goto next(...);
411 }
412 ```
413
414 ---
415
416 # private
417 - CbC は信頼性を保証するためにそれぞれの Code Gear を細かくする必要があるので、for文やif文がある場合はさらに実装を分ける
418 - Code Gear は基本的にインターフェースで指定された Code Gear 内からのみ継続さ れるため、Java の private メソッドのように扱われる。
419 - 実際に vm.c の loaduvm の実装を分けた記述を説明する
420
421
422 ``` c
423 int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
424 {
425 uint i, pa, n;
426 pte_t *pte;
427
428 if ((uint) addr % PTE_SZ != 0) {
429 panic("loaduvm: addr must be page aligned");
430 }
431
432 for (i = 0; i < sz; i += PTE_SZ) {
433 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
434 panic("loaduvm: address should exist");
435 }
436
437 pa = PTE_ADDR(*pte);
438
439 if (sz - i < PTE_SZ) {
440 n = sz - i;
441 } else {
442 n = PTE_SZ;
443 }
444
445 if (readi(ip, p2v(pa), offset + i, n) != n) {
446 return -1;
447 }
448 }
449
450 return 0;
451 }
452 ```
453
454 ---
455
456 # goto private
457 - vm と同じ create_impl 内で vm_impl を定義し、private で実装する Code Gear を定義する
458 - loaduvmvm_impl で goto によって private に遷移する
459
460
461 ``` c
462 vm* createvm_impl(struct Context* cbc_context) {
463 ...
464 struct vm_impl* vm_impl = new vm_impl();
465 ...
466 vm_impl->loaduvm_ptesize_check = C_loaduvm_ptesize_checkvm_impl;
467 ....
468 vm->loaduvm = C_loaduvmvm_impl;
469 ....
470 }
471
472 __code loaduvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)) {
473 Gearef(cbc_context, vm_impl)->pgdir = pgdir;
474 Gearef(cbc_context, vm_impl)->addr = addr;
475 Gearef(cbc_context, vm_impl)->ip = ip;
476 Gearef(cbc_context, vm_impl)->offset = offset;
477 Gearef(cbc_context, vm_impl)->sz = sz;
478 Gearef(cbc_context, vm_impl)->next = next;
479
480 goto loaduvm_ptesize_checkvm_impl(vm, next(...));
481 }
482 ```
483 ---
484
485 # private のヘッダー
486 - private 側のヘッダーファイルも vm_impl と同じように用意する
487
488 ``` c
489 typedef struct vm_impl<Impl, Isa> impl vm{
490 ...
491 __code loaduvm_ptesize_check(Type* vm_impl, uint i, pte_t* pte, uint sz,
492 __code next(int ret, ...));
493 ```
494
495 ---
496
497 # private の記述
498
499
500 ``` c
501 #interface "vm_impl.h"
502
503 __code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
504 char* addr = vm_impl->addr;
505
506 if ((uint) addr %PTE_SZ != 0) {
507 // goto panic
508 }
509
510 goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
511 }
512 ```
513
514 - vm.cではここから for だが CbC は if文の中と外にgoto を用意して実装する
515
516 ![](https://i.imgur.com/ByA7GVJ.png)
517
518 ```c
519 __code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
520 uint i = vm_impl->i;
521 uint sz = vm_impl->sz;
522
523 if (i < sz) {
524 goto loaduvm_check_pgdir(vm_impl, next(ret, ...));
525 }
526
527 goto loaduvm_exit(vm_impl, next(ret, ...));
528 }
529
530
531 __code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(int ret, ...)) {
532 pte_t* pte = vm_impl->pte;
533 pde_t* pgdir = vm_impl->pgdir;
534 uint i = vm_impl->i;
535 char* addr = vm_impl->addr;
536 uint pa = vm_impl->pa;
537
538 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
539 // goto panic
540 }
541 pa = PTE_ADDR(*pte);
542
543 vm_impl->pte = pte;
544 vm_impl->pgdir = pgdir;
545 vm_impl->addr = addr;
546 vm_impl->pa = pa;
547
548 goto loaduvm_check_PTE_SZ(vm_impl, next(ret, ...));
549 }
550
551 __code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(int ret, ...)) {
552 uint sz = vm_impl->sz;
553 uint i = vm_impl->i;
554 uint n = vm_impl->n;
555 struct inode* ip = vm_impl->ip;
556 uint pa = vm_impl->pa;
557 uint offset = vm_impl->offset;
558
559 if (sz - i < PTE_SZ) {
560 n = sz - i;
561 } else {
562 n = PTE_SZ;
563 }
564
565 if (readi(ip, p2v(pa), offset + i, n) != n) {
566 ret = -1;
567 goto next(ret, ...);
568 }
569
570 vm_impl->n = n;
571
572 goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
573 }
574
575 __code loaduvm_exit(struct vm_impl* vm_impl, __code next(int ret, ...)) {
576 ret = 0;
577 goto next(ret, ...);
578 }
579 ```
580
581
582
583 ``` c
584
585 int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
586 {
587 uint i, pa, n;
588 pte_t *pte;
589
590 if ((uint) addr % PTE_SZ != 0) {
591 panic("loaduvm: addr must be page aligned");
592 }
593
594 for (i = 0; i < sz; i += PTE_SZ) {
595 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
596 panic("loaduvm: address should exist");
597 }
598
599 pa = PTE_ADDR(*pte);
600
601 if (sz - i < PTE_SZ) {
602 n = sz - i;
603 } else {
604 n = PTE_SZ;
605 }
606
607 if (readi(ip, p2v(pa), offset + i, n) != n) {
608 return -1;
609 }
610 }
611
612 return 0;
613 }
614 ```
615
616
617 # インターフェースの呼び出し
618 - 定義したインターフェースの呼び出しについて説明する
619 - CbC の場合 goto による 遷移を行うので、関数呼び出しのように goto 以降のコードを実行できない
620 - 例) goto すると戻ってこれないため それ以降が実行されなくなる。
621
622 ``` c
623 void userinit(void)
624 {
625 struct proc* p;
626 extern char _binary_initcode_start[], _binary_initcode_size[];
627
628 p = allocproc();
629 initContext(&p->cbc_context);
630
631 initproc = p;
632
633 if((p->pgdir = kpt_alloc()) == NULL) {
634 panic("userinit: out of memory?");
635 }
636
637 goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
638 p->sz = PTE_SZ;
639
640 // craft the trapframe as if
641 memset(p->tf, 0, sizeof(*p->tf));
642 ~
643 ```
644
645 # 呼び出しの解決
646 - 最初の命令は next で戻ってこれるので、dummy の関数を用意してそこで実行する
647
648 ``` c
649 void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[])
650 {
651 // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
652 goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
653
654 }
655
656
657
658 __ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip
659
660 struct vm* vm = createvm_impl(cbc_context);
661 // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret);
662 Gearef(cbc_context, vm)->vm = (union Data*) vm;
663 Gearef(cbc_context, vm)->pgdir = pgdir;
664 Gearef(cbc_context, vm)->init = init;
665 Gearef(cbc_context, vm)->sz = sz ;
666 Gearef(cbc_context, vm)->next = C_vm_void_ret ;
667 goto meta(cbc_context, vm->init_inituvm);
668 }
669
670
671 void userinit(void)
672 {
673 struct proc* p;
674 extern char _binary_initcode_start[], _binary_initcode_size[];
675
676 p = allocproc();
677 initContext(&p->cbc_context);
678
679 initproc = p;
680
681 if((p->pgdir = kpt_alloc()) == NULL) {
682 panic("userinit: out of memory?");
683 }
684
685 dummy(p, _binary_initcode_start, _binary_initcode_size);
686 ~
687
688 ```