Mercurial > hg > Papers > 2020 > tobaru-master
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 ``` |