Mercurial > hg > Papers > 2020 > tobaru-master
changeset 27:a62d736db44e
stub and description loop
author | tobaru |
---|---|
date | Sun, 09 Feb 2020 15:29:56 +0900 |
parents | ee9435951c31 |
children | 53302e350642 |
files | paper/GearsOS.tex paper/cbc_interface.tex paper/master_paper.pdf paper/master_paper.synctex.gz paper/src/dummy paper/src/stub_loaduvm paper/src/vm_impl_private.cbc |
diffstat | 7 files changed, 137 insertions(+), 127 deletions(-) [+] |
line wrap: on
line diff
--- a/paper/GearsOS.tex Sun Feb 09 14:12:59 2020 +0900 +++ b/paper/GearsOS.tex Sun Feb 09 15:29:56 2020 +0900 @@ -32,7 +32,7 @@ メタ計算は Meta Code Gear と Meta Data Gear を用いる。 この2つはノーマルレベルからメタレベルの変換する時に使われる。 -メタレベルの変換は Perl スクリプトで実装している。 +メタレベルの変換は Perl スクリプトによる cmake で実装している。 Gears OS での Meta Code Gear は Code Gear の直前、 直後に挿入され、メタ計算を実行する。 それぞれの Code Gear, Meta Code Gear の継続には入力される Data Gear(Input Data Gear) と出力されるData Gear(Output Data Gear)が存在する。 Code Gear 間の継続はノーマルレベルでは 図 \ref{fig:codegear} のように見えるが、メタレベルでの Code Gear は図 \ref{fig:meta_cg_dg} の下のように継続を行っている。
--- a/paper/cbc_interface.tex Sun Feb 09 14:12:59 2020 +0900 +++ b/paper/cbc_interface.tex Sun Feb 09 15:29:56 2020 +0900 @@ -53,7 +53,6 @@ % 引数の Data Gear はその Code Gear の Input Data Gear になり、引数の Code Gear の中の引 数が Output Data Gear になる。Code Gear の第一引数には Interface を実装した Data Gear を渡す。これは、Code Gear の操作の対象となる Data Gear を設定し ており、後述する継続構文では引数として記述を行わない。 -\section{インターフェースの実装} インターフェースは Data Gear に対しての Code Gear とその Code Gear で扱われている Data Gear の集合を抽象化した Meta Data Gear で、vm.c に対応する実装は別で定義する。 @@ -82,7 +81,7 @@ -\section{インターフェース内の private メソッド} +\section{インターフェースの実装} インターフェースで定義した Code Gear 以外の Code Gaer も記述することができる。 この Code Gear は基本的にインターフェースで指定された Code Gear 内からのみ継続されるため、 Java の private メソッドのように扱われる。 @@ -165,10 +164,10 @@ vm\_impl.cbc の Code Gear であるloaduvmvm\_impl から goto で loaduvm\_ptesize\_checkvm\_impl に遷移する。 vm.c での最初の if 文までの処理を 1つの Code Gear として loaduvm\_ptesize\_checkvm\_impl に記述する。(3行目~11行目) - +\section{CbC のループ処理} CbC では goto での状態遷移によって実装するので loop は if 文を使って実装する。 -遷移図を \ref{fig:cbc_for_private} で示す。 +遷移図を 図 \ref{fig:cbc_for_private} で示す。 \begin{figure}[ht] \begin{center} @@ -179,131 +178,35 @@ \end{figure} -\begin{lstlisting}[frame=lrbt,label=impl_vm_loaduvm,caption={\footnotesize privateでの loaduvm の実装}] -#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, ...)); -} - -__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, ...)); -} - +\lstinputlisting[frame=lrbt,label=impl_vm_loaduvm,caption={\footnotesize loaduvm の実装の記述}]{./src/vm_impl_private.cbc} -static pte_t* walkpgdir (pde_t *pgdir, const void *va, int alloc) -{ - pde_t *pde; - pte_t *pgtab; - - // pgdir points to the page directory, get the page direcotry entry (pde) - pde = &pgdir[PDE_IDX(va)]; - - if (*pde & PE_TYPES) { - pgtab = (pte_t*) p2v(PT_ADDR(*pde)); - - } else { - if (!alloc || (pgtab = (pte_t*) kpt_alloc()) == 0) { - return 0; - } - - // Make sure all those PTE_P bits are zero. - memset(pgtab, 0, PT_SZ); - - // The permissions here are overly generous, but they can - // be further restricted by the permissions in the page table - // entries, if necessary. - *pde = v2p(pgtab) | UPDE_TYPE; - } - - return &pgtab[PTE_IDX(va)]; -} +for文から末尾再起の変換について +図 \ref{fig:cbc_for_private} のように loaduvm\_loopvm\_impl のif 文で ループの条件を書いて goto させ、loaduvm\_check\_PTE\_SZ で満たしてなければ loaduvm\_loopvm\_impl に goto することでループを実装している。 -__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, ...)); -} +static なものはまだ書き直していないが後々実装する -__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, ...); -} - -\end{lstlisting} - -for文から末尾再起の変換について +\section{Meta Code Gear の記述} +cmake によって生成されたメタ部分の記述について説明する。 +ファイルはビルドディレクトリ以下の /CMakeFiles/kernel.dir/c/ に生成される。 -static なものに関しては後々実装する +ノーマルレベルの Code Gear と ノーマルレベルの Code Gear 名 の後ろに \_stub が付いた Meta Code Gearが対応する。 +例として loaduvm の生成された Code Gear と Meta Code Gear をソースコード \ref{loaduvm_stub} に示す。 + +\lstinputlisting[frame=lrbt,label=loaduvm_stub,caption={\footnotesize loaduvm のメタ部分の記述}]{./src/stub_loaduvm} + \section{インターフェースの呼び出し} 定義したインターフェースの呼び出し方について説明する。 CbC の場合 goto による遷移を行うので、関数呼び出しのように goto 以降のコードを実行できない。 -例として、ソースコード \ref{cbc_goto} の16行目のように goto によってインターフェースで定義した命令を行うと、戻ってこれないため17行目以降が実行されなくなる。 - \lstinputlisting[frame=lrbt,label=cbc_goto,caption={\footnotesize cbc インターフェースのgoto}]{./src/failure_example_userinit} -\lstinputlisting[frame=lrbt,label=dummy,caption={\footnotesize dummy を使った呼び出し}]{./src/dummy} -14行目から18行目の引数の設定に Gearef を使っているが、本来は CMake で生成しその部分には何も書かない。 -18行目の C\_vm\_void\_ret は return するための enum コードであり、これを使って関数呼び出しのように振る舞う。 +例として、ソースコード \ref{cbc_goto} の16行目のように goto によってインターフェースで定義した命令を行うと、戻ってこれないため17行目以降が実行されなくなる。 -1行目から6行目までの関数と cbc\_init\_vmm\_dummy の Code Gear はまとめて記述することも可能である。 - - - +\lstinputlisting[frame=lrbt,label=dummy,caption={\footnotesize dummy を使った呼び出し}]{./src/dummy} +7行目から11行目の引数の設定に Gearef を使っているが、本来は CMake で生成しその部分には何も書かない。 +11行目の C\_vm\_void\_ret は return するための enum コードであり、これを使って関数呼び出しのように振る舞う。
--- a/paper/src/dummy Sun Feb 09 14:12:59 2020 +0900 +++ b/paper/src/dummy Sun Feb 09 15:29:56 2020 +0900 @@ -1,13 +1,6 @@ -void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[]) +void cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz) { // 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); @@ -19,7 +12,6 @@ goto meta(cbc_context, vm->init_inituvm); } - void userinit(void) { struct proc* p; @@ -34,4 +26,8 @@ panic("userinit: out of memory?"); } - dummy(p, _binary_initcode_start, _binary_initcode_size); + cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + + p->sz = PTE_SZ; +.... +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/src/stub_loaduvm Sun Feb 09 15:29:56 2020 +0900 @@ -0,0 +1,21 @@ +__code loaduvmvm_impl(struct Context *cbc_context,struct vm_impl* vm, pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, enum 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 meta(cbc_context, C_loaduvm_ptesize_checkvm_impl); +} + +__code loaduvmvm_impl_stub(struct Context* cbc_context) { + vm_impl* vm = (vm_impl*)GearImpl(cbc_context, vm, vm); + pde_t* pgdir = Gearef(cbc_context, vm)->pgdir; + char* addr = Gearef(cbc_context, vm)->addr; + inode* ip = Gearef(cbc_context, vm)->ip; + uint offset = Gearef(cbc_context, vm)->offset; + uint sz = Gearef(cbc_context, vm)->sz; + enum Code next = Gearef(cbc_context, vm)->next; + goto loaduvmvm_impl(cbc_context, vm, pgdir, addr, ip, offset, sz, next); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/src/vm_impl_private.cbc Sun Feb 09 15:29:56 2020 +0900 @@ -0,0 +1,90 @@ +#interface "vm_impl.h" + +__code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl,char* addr, __code next(int ret, ...)) { + if ((uint) addr %PTE_SZ != 0) { + char* msg = "addr % PTE_SZ != 0"; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + + goto loaduvm_loopvm_impl(vm_impl, next(ret, ...)); +} + +__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, uint i, uint sz,__code next(int ret, ...)) { + if (i < sz) { + goto loaduvm_check_pgdir(vm_impl, next(ret, ...)); + } + + goto loaduvm_exit(vm_impl, next(ret, ...)); +} + + +static pte_t* walkpgdir (pde_t *pgdir, const void *va, int alloc) +{ + pde_t *pde; + pte_t *pgtab; + + // pgdir points to the page directory, get the page direcotry entry (pde) + pde = &pgdir[PDE_IDX(va)]; + + if (*pde & PE_TYPES) { + pgtab = (pte_t*) p2v(PT_ADDR(*pde)); + + } else { + if (!alloc || (pgtab = (pte_t*) kpt_alloc()) == 0) { + return 0; + } + + // Make sure all those PTE_P bits are zero. + memset(pgtab, 0, PT_SZ); + + // The permissions here are overly generous, but they can + // be further restricted by the permissions in the page table + // entries, if necessary. + *pde = v2p(pgtab) | UPDE_TYPE; + } + + return &pgtab[PTE_IDX(va)]; +} + + +__code loaduvm_check_pgdir(struct vm_impl* vm_impl, pte_t* pte, pde_t* pgdir, uint i, char* addr, uint pa, __code next(int ret, ...)) { + if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) { + char* msg = "pte != walkpgdir..."; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); + } + pa = PTE_ADDR(*pte); + + Gearef(cbc_context, vm_impl)->pte = pte; + Gearef(cbc_context, vm_impl)->pgdir = pgdir; + Gearef(cbc_context, vm_impl)->addr = addr; + Gearef(cbc_context, vm_impl)->pa = pa; + + goto loaduvm_check_PTE_SZ(vm_impl, next(ret, ...)); +} + +__code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, uint sz, uint i, uint n, struct inode* ip, uint pa, uint offset, __code next(int ret, ...)) { + + 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, ...); + } + + Gearef(cbc_context, 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, ...); +}