Mercurial > hg > Papers > 2020 > tobaru-master
diff slide/CbCXv6.md @ 19:98cee2f6c919
slide
author | tobaru |
---|---|
date | Sat, 08 Feb 2020 15:06:50 +0900 |
parents | afc36230cf4f |
children | 6d84ce92ff35 |
line wrap: on
line diff
--- a/slide/CbCXv6.md Fri Feb 07 20:06:13 2020 +0900 +++ b/slide/CbCXv6.md Sat Feb 08 15:06:50 2020 +0900 @@ -62,6 +62,7 @@ ![](https://i.imgur.com/etfQund.png) + --- # Data Gear の継続 @@ -279,13 +280,409 @@ 1. OS の信頼性の保証 2. CbC による Gears OS の開発 3. Xv6 -4. CbCXv6 での Paging** +4. CbCXv6 での Paging 5. **CbC インターフェース** 6. 評価 7. まとめ --- +# CbC インターフェースの導入 +- 継続の記述が煩雑になる + - Code Gear がどの Data Gear の番号に対応するか指定する必要がある + - ノーマルレベルとメタレベルで Data Gear の見え方が異なるため調整する必要がある +- ->インターフェースの導入 + + +--- + +# CbC インターフェース +- インターフェースは Data Gear に対しての操作を行う Code Gear +- 実装は別で定義し、呼び出す +- インターフェースによって機能を置き換えることができる + +--- + +# インターフェースの定義 +- Data Gear と Data Gear に対して操作を行う Code Gear の集合を表現する **Meta Data Gear** + +--- + +# インターフェースのソースコード +- vm.c をインターフェースで書き換えた vm.h のコードの説明をしていく + + +--- + + +# 実装名の定義 +- typedef struct の直後に実装名(vm)を書く + + +``` c +typedef struct vm<Type,Impl> { +``` + +--- + +# Data Gear の定義 +- 2行目から19行目で引数の Data Gear を定義している + + +``` c +typedef struct vm<Type,Impl> { + union Data* vm; + uint low; + uint hi; + struct proc* p; +.... +``` + +--- + +# Code Gear の定義 +- Code Gear は __Code CodeGear名(引数); で記述する +- 第1引数の Impl* vm が Code Gear の型になる +- 初期化された Data Gear が それぞれの Code Gear の引数として扱われる +- 例)定義された uinit が kpt_freerange の Code Gear の第1引数と対応している + + +``` c + __code init_vmm(Impl* vm, __code next(...)); + __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...)); + __code kpt_alloc(Impl* vm ,__code next(...)); + __code switchuvm(Impl* vm ,struct proc* p, __code next(...)); + __code init_inituvm(Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + __code loaduvm(Impl* vm,pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)); + __code allocuvm(Impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...)); + +.... + +``` + +--- + + +# next(...) +- __code next(...) は条件分岐によって複数の継続先が設定される +- それぞれの Code Gear の引数の1つに設定する +``` c + __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...)); +.... + __code next(...); +} vm; +``` + +--- + +# インターフェースの実装 +- インターフェースの実装は別ファイルで定義する(vm_impl.cbc) +- ヘッダーファイルの呼び出しは #include ではなく #interface で呼び出す + +``` c +#include "../../context.h" +#interface "vm.h" + +``` + + +--- + +# create_impl +- create_imple の関数内で vm の型を定義し、vm->CodeGear名 で対応させていく +- 実装を Code Gear で記述していく。 + + +``` c + +vm* createvm_impl(struct Context* cbc_context) { + struct vm* vm = new vm(); +.... + vm->void_ret = C_vm_void_ret; + vm->init_vmm = C_init_vmmvm_impl; + vm->kpt_freerange = C_kpt_freerangevm_impl; + vm->kpt_alloc = C_kpt_allocvm_impl; +... +__code init_vmmvm_impl(struct vm_impl* vm,__code next(...)) { + initlock(&kpt_mem.lock, "vm"); + kpt_mem.freelist = NULL; + + goto next(...); +} +``` + +--- + +# private +- CbC は信頼性を保証するためにそれぞれの Code Gear を細かくする必要があるので、for文やif文がある場合はさらに実装を分ける +- Code Gear は基本的にインターフェースで指定された Code Gear 内からのみ継続さ れるため、Java の private メソッドのように扱われる。 +- 実際に vm.c の loaduvm の実装を分けた記述を説明する + + +``` c +int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) +{ + uint i, pa, n; + pte_t *pte; + + if ((uint) addr % PTE_SZ != 0) { + panic("loaduvm: addr must be page aligned"); + } + + for (i = 0; i < sz; i += PTE_SZ) { + if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) { + panic("loaduvm: address should exist"); + } + + pa = PTE_ADDR(*pte); + + if (sz - i < PTE_SZ) { + n = sz - i; + } else { + n = PTE_SZ; + } + + if (readi(ip, p2v(pa), offset + i, n) != n) { + return -1; + } + } + + return 0; +} +``` + +--- + +# goto private +- vm と同じ create_impl 内で vm_impl を定義し、private で実装する Code Gear を定義する +- loaduvmvm_impl で goto によって private に遷移する + + +``` c +vm* createvm_impl(struct Context* cbc_context) { +... + struct vm_impl* vm_impl = new vm_impl(); +... + vm_impl->loaduvm_ptesize_check = C_loaduvm_ptesize_checkvm_impl; +.... + vm->loaduvm = C_loaduvmvm_impl; +.... +} + +__code loaduvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)) { + Gearef(cbc_context, vm_impl)->pgdir = pgdir; + Gearef(cbc_context, vm_impl)->addr = addr; + Gearef(cbc_context, vm_impl)->ip = ip; + Gearef(cbc_context, vm_impl)->offset = offset; + Gearef(cbc_context, vm_impl)->sz = sz; + Gearef(cbc_context, vm_impl)->next = next; + + goto loaduvm_ptesize_checkvm_impl(vm, next(...)); +} +``` +--- + +# private のヘッダー +- private 側のヘッダーファイルも vm_impl と同じように用意する + +``` c +typedef struct vm_impl<Impl, Isa> impl vm{ +... + __code loaduvm_ptesize_check(Type* vm_impl, uint i, pte_t* pte, uint sz, +__code next(int ret, ...)); +``` + +--- + +# private の記述 + + +``` c +#interface "vm_impl.h" + +__code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) { + char* addr = vm_impl->addr; + + if ((uint) addr %PTE_SZ != 0) { + // goto panic + } + + goto loaduvm_loopvm_impl(vm_impl, next(ret, ...)); +} +``` + +- vm.cではここから for だが CbC は if文の中と外にgoto を用意して実装する + +![](https://i.imgur.com/ByA7GVJ.png) + +```c +__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) { + uint i = vm_impl->i; + uint sz = vm_impl->sz; + + if (i < sz) { + goto loaduvm_check_pgdir(vm_impl, next(ret, ...)); + } + + goto loaduvm_exit(vm_impl, next(ret, ...)); +} + + +__code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(int ret, ...)) { + pte_t* pte = vm_impl->pte; + pde_t* pgdir = vm_impl->pgdir; + uint i = vm_impl->i; + char* addr = vm_impl->addr; + uint pa = vm_impl->pa; + + if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) { + // goto panic + } + pa = PTE_ADDR(*pte); + + vm_impl->pte = pte; + vm_impl->pgdir = pgdir; + vm_impl->addr = addr; + vm_impl->pa = pa; + + goto loaduvm_check_PTE_SZ(vm_impl, next(ret, ...)); +} + +__code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(int ret, ...)) { + uint sz = vm_impl->sz; + uint i = vm_impl->i; + uint n = vm_impl->n; + struct inode* ip = vm_impl->ip; + uint pa = vm_impl->pa; + uint offset = vm_impl->offset; + + if (sz - i < PTE_SZ) { + n = sz - i; + } else { + n = PTE_SZ; + } + + if (readi(ip, p2v(pa), offset + i, n) != n) { + ret = -1; + goto next(ret, ...); + } + + vm_impl->n = n; + + goto loaduvm_loopvm_impl(vm_impl, next(ret, ...)); +} + +__code loaduvm_exit(struct vm_impl* vm_impl, __code next(int ret, ...)) { + ret = 0; + goto next(ret, ...); +} +``` +``` c + +int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) +{ + uint i, pa, n; + pte_t *pte; + + if ((uint) addr % PTE_SZ != 0) { + panic("loaduvm: addr must be page aligned"); + } + + for (i = 0; i < sz; i += PTE_SZ) { + if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) { + panic("loaduvm: address should exist"); + } + + pa = PTE_ADDR(*pte); + + if (sz - i < PTE_SZ) { + n = sz - i; + } else { + n = PTE_SZ; + } + + if (readi(ip, p2v(pa), offset + i, n) != n) { + return -1; + } + } + + return 0; +} +``` + + +# インターフェースの呼び出し +- 定義したインターフェースの呼び出しについて説明する +- CbC の場合 goto による 遷移を行うので、関数呼び出しのように goto 以降のコードを実行できない +- 例) goto すると戻ってこれないため それ以降が実行されなくなる。 + +``` c +void userinit(void) +{ + struct proc* p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + initContext(&p->cbc_context); + + initproc = p; + + if((p->pgdir = kpt_alloc()) == NULL) { + panic("userinit: out of memory?"); + } + + goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + p->sz = PTE_SZ; + + // craft the trapframe as if + memset(p->tf, 0, sizeof(*p->tf)); +~ +``` + +# 呼び出しの解決 +- 最初の命令は next で戻ってこれるので、dummy の関数を用意してそこで実行する + +``` c +void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[]) +{ + // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + +} + + + +__ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip + + struct vm* vm = createvm_impl(cbc_context); + // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret); + Gearef(cbc_context, vm)->vm = (union Data*) vm; + Gearef(cbc_context, vm)->pgdir = pgdir; + Gearef(cbc_context, vm)->init = init; + Gearef(cbc_context, vm)->sz = sz ; + Gearef(cbc_context, vm)->next = C_vm_void_ret ; + goto meta(cbc_context, vm->init_inituvm); +} + + +void userinit(void) +{ + struct proc* p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + initContext(&p->cbc_context); + + initproc = p; + + if((p->pgdir = kpt_alloc()) == NULL) { + panic("userinit: out of memory?"); + } + + dummy(p, _binary_initcode_start, _binary_initcode_size); +~ + +```