8
|
1 \chapter{CbC インターフェース}
|
|
2
|
|
3 構造図書く(今のcbcxv6と同じか確認してから)
|
|
4 \par
|
|
5
|
|
6
|
|
7 Gears OS では Meta Code Gear で Context から値を取り出し、ノーマルレベルの Code Gear に値を渡す。
|
|
8 しかし、Code Gaer がどの Data Gear の番号に対応するかを指定する必要があったり、 % ぱるすさんコード必要?
|
|
9 ノーマルレベルとメタレベルで見え方が異なる Data Gear を Meta Code Gear によって 調整する必要があったりと、 % みつきさん
|
|
10 メタレベルからノーマルレベルの継続の記述が煩雑になるため、Interface 化をしている。
|
|
11 Interface は Data Gear に対しての操作を行う Code Gear であり、実装は別で定義する。
|
|
12 % Interface で定義した Code Gear に
|
|
13
|
|
14
|
|
15 % Xv6 の書き換えは Interface を用いてモジュール化する。
|
|
16 そうすることで Gears OS の機能を置き換えることできるようになる。
|
|
17
|
|
18
|
|
19
|
|
20 \section{インターフェースの定義}
|
|
21 インターフェースはある Data Gear の定義と、
|
|
22 それに対する操作を行う Code Gear の集合を表現する Meta Data Gear である。
|
|
23 Context では全ての Code Gaer と Data Gear の集合を表現していることに対し、
|
|
24 インターフェースは一部の Code Gear と一部の Data Gear の集合を表現する。
|
|
25 \par
|
|
26 インターフェースを記述することによってノーマルレベルとメタレベルの分離が可能となる。
|
|
27
|
12
|
28 Paging のインターフェースを記述したコードを ソースコード \ref{interface} に示す。
|
8
|
29
|
|
30
|
12
|
31 \begin{lstlisting}[frame=lrbt,label=interface,caption={\footnotesize vm のインターフェースの定義(vm.h)}]
|
8
|
32 typedef struct vm<Type,Impl> {
|
|
33 union Data* vm;
|
|
34 uint low;
|
|
35 uint hi;
|
|
36 struct proc* p;
|
|
37 pde_t* pgdir;
|
|
38 char* init;
|
|
39 uint sz;
|
|
40 char* addr;
|
|
41 struct inode* ip;
|
|
42 uint offset;
|
|
43 uint oldsz;
|
|
44 uint newsz;
|
|
45 char* uva;
|
|
46 uint va;
|
|
47 void* pp;
|
|
48 uint len;
|
|
49 uint phy_low;
|
|
50 uint phy_hi;
|
|
51 __code init_vmm(Impl* vm, __code next(...));
|
|
52 __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...));
|
|
53 __code kpt_alloc(Impl* vm ,__code next(...));
|
|
54 __code switchuvm(Impl* vm ,struct proc* p, __code next(...));
|
|
55 __code init_inituvm(Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...));
|
|
56 __code loaduvm(Impl* vm,pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...));
|
|
57 __code allocuvm(Impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...));
|
|
58 __code clearpteu(Impl* vm, pde_t* pgdir, char* uva, __code next(...));
|
|
59 __code copyuvm(Impl* vm, pde_t* pgdir, uint sz, __code next(...));
|
|
60 __code uva2ka(Impl* vm, pde_t* pgdir, char* uva, __code next(...));
|
|
61 __code copyout(Impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...));
|
|
62 __code paging_int(Impl* vm, uint phy_low, uint phy_hi, __code next(...));
|
|
63 __code void_ret(Impl* vm);
|
|
64 __code next(...);
|
|
65 } vm;
|
|
66 \end{lstlisting}
|
|
67
|
12
|
68 1行目ので実装名を定義している。
|
|
69 typedef struct の直後に実装名(vm)を書く。
|
8
|
70 \par
|
|
71 2行目から19行目で引数の Data Gear 郡を定義している。
|
12
|
72 初期化された Data Gear がそれぞれの Code Gear の引数として扱われる。
|
8
|
73 例として、2行目で定義された vm が21行目から32行目までの引数と対応している。
|
|
74 \par
|
|
75 % インターフェースの Code Gear の goto による継続先は基本的に不定となっており、継続元から渡される。
|
12
|
76 Code Gear は\_\_code CodeGearName () で記述する。
|
|
77 第一引数である Impl* vm が Code Gear の型になる。
|
|
78 \par
|
8
|
79 \_\_code next(...) の引数 ... は複数の Input Data Gear を持つという意味である。
|
|
80 後述する実装によって条件分岐によって複数の継続先が設定されることがある。
|
|
81 \par
|
|
82 Code Gaer は 20行目から33行目のように "\_\_code [Code Gear名]([引数])"で定義する。
|
|
83 この引数が input Data Gear になる。
|
|
84
|
|
85
|
|
86 % 実装側に書く
|
|
87 % 引数の Data Gear はその Code Gear の Input Data Gear になり、引数の Code Gear の中の引 数が Output Data Gear になる。Code Gear の第一引数には Interface を実装した Data Gear を渡す。これは、Code Gear の操作の対象となる Data Gear を設定し ており、後述する継続構文では引数として記述を行わない。
|
|
88
|
|
89
|
|
90 \section{インターフェースの実装}
|
|
91 インターフェースは Data Gear に対しての Code Gear とその Code Gear で扱われている Data Gear の集合を抽象化した Meta Data Gear で、vm.c に対応する実装は別で定義する。
|
|
92 \par
|
12
|
93 インターフェースの実装についてソースコード \ref{impl_vm} で示す。
|
8
|
94
|
|
95
|
|
96 \begin{lstlisting}[frame=lrbt,label=impl_vm,caption={\footnotesize vm インターフェースの実装}]
|
|
97 #include "../../context.h"
|
|
98 #interface "vm.h"
|
|
99
|
|
100 vm* createvm_impl(struct Context* cbc_context) {
|
|
101 struct vm* vm = new vm();
|
|
102 struct vm_impl* vm_impl = new vm_impl();
|
|
103 vm->vm = (union Data*)vm_impl;
|
|
104 vm_impl->vm_impl = NULL;
|
|
105 vm_impl->i = 0;
|
|
106 vm_impl->pte = NULL;
|
|
107 vm_impl->sz = 0;
|
|
108 vm_impl->loaduvm_ptesize_check = C_loaduvm_ptesize_checkvm_impl;
|
|
109 vm_impl->loaduvm_loop = C_loaduvm_loopvm_impl;
|
|
110 vm_impl->allocuvm_check_newsz = C_allocuvm_check_newszvm_impl;
|
|
111 vm_impl->allocuvm_loop = C_allocuvm_loopvm_impl;
|
|
112 vm_impl->copyuvm_check_null = C_copyuvm_check_nullvm_impl;
|
|
113 vm_impl->copyuvm_loop = C_copyuvm_loopvm_impl;
|
|
114 vm_impl->uva2ka_check_pe_types = C_uva2ka_check_pe_types;
|
|
115 vm_impl->paging_intvm_impl = C_paging_intvmvm_impl;
|
|
116 vm_impl->copyout_loopvm_impl = C_copyout_loopvm_impl;
|
|
117 vm_impl->switchuvm_check_pgdirvm_impl = C_switchuvm_check_pgdirvm_impl;
|
|
118 vm_impl->init_inituvm_check_sz = C_init_inituvm_check_sz;
|
|
119 vm->void_ret = C_vm_void_ret;
|
|
120 vm->init_vmm = C_init_vmmvm_impl;
|
|
121 vm->kpt_freerange = C_kpt_freerangevm_impl;
|
|
122 vm->kpt_alloc = C_kpt_allocvm_impl;
|
|
123 vm->switchuvm = C_switchuvmvm_impl;
|
|
124 vm->init_inituvm = C_init_inituvmvm_impl;
|
|
125 vm->loaduvm = C_loaduvmvm_impl;
|
|
126 vm->allocuvm = C_allocuvmvm_impl;
|
|
127 vm->clearpteu = C_clearpteuvm_impl;
|
|
128 vm->copyuvm = C_copyuvmvm_impl;
|
|
129 vm->uva2ka = C_uva2kavm_impl;
|
|
130 vm->copyout = C_copyoutvm_impl;
|
|
131 vm->paging_int = C_paging_intvm_impl;
|
|
132 return vm;
|
|
133 }
|
|
134 extern struct {
|
|
135 struct spinlock lock;
|
|
136 struct run *freelist;
|
|
137 } kpt_mem;
|
|
138
|
|
139 __code init_vmmvm_impl(struct vm_impl* vm,__code next(...)) {
|
|
140 initlock(&kpt_mem.lock, "vm");
|
|
141 kpt_mem.freelist = NULL;
|
|
142
|
|
143 goto next(...);
|
|
144 }
|
|
145
|
|
146 extern struct run {
|
|
147 struct run *next;
|
|
148 };
|
|
149
|
|
150 static void _kpt_free (char *v)
|
|
151 {
|
|
152 struct run *r;
|
|
153
|
|
154 r = (struct run*) v;
|
|
155 r->next = kpt_mem.freelist;
|
|
156 kpt_mem.freelist = r;
|
|
157 }
|
|
158
|
|
159 __code kpt_freerangevm_impl(struct vm_impl* vm, uint low, uint hi, __code next(...)) {
|
|
160
|
|
161 if (low < hi) {
|
|
162 _kpt_free((char*)low);
|
|
163 goto kpt_freerangevm_impl(vm, low + PT_SZ, hi, next(...));
|
|
164
|
|
165 }
|
|
166 goto next(...);
|
|
167 }
|
|
168
|
|
169 __code kpt_allocvm_impl(struct vm_impl* vm, __code next(...)) {
|
|
170 acquire(&kpt_mem.lock);
|
|
171
|
|
172 goto kpt_alloc_check_impl(vm_impl, next(...));
|
|
173 }
|
|
174
|
|
175 typedef struct proc proc;
|
|
176 __code switchuvmvm_impl(struct vm_impl* vm , struct proc* p, __code next(...)) { //:skip
|
|
177
|
|
178 goto switchuvm_check_pgdirvm_impl(...);
|
|
179 }
|
|
180
|
|
181 __code init_inituvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)) {
|
|
182
|
|
183 Gearef(cbc_context, vm_impl)->pgdir = pgdir;
|
|
184 Gearef(cbc_context, vm_impl)->init = init;
|
|
185 Gearef(cbc_context, vm_impl)->sz = sz;
|
|
186 Gearef(cbc_context, vm_impl)->next = next;
|
|
187 goto init_inituvm_check_sz(vm, pgdir, init, sz, next(...));
|
|
188 }
|
|
189
|
|
190 __code loaduvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)) {
|
|
191 Gearef(cbc_context, vm_impl)->pgdir = pgdir;
|
|
192 Gearef(cbc_context, vm_impl)->addr = addr;
|
|
193 Gearef(cbc_context, vm_impl)->ip = ip;
|
|
194 Gearef(cbc_context, vm_impl)->offset = offset;
|
|
195 Gearef(cbc_context, vm_impl)->sz = sz;
|
|
196 Gearef(cbc_context, vm_impl)->next = next;
|
|
197
|
|
198 goto loaduvm_ptesize_checkvm_impl(vm, next(...));
|
|
199 }
|
|
200
|
|
201 __code allocuvmvm_impl(struct vm_impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...)) {
|
|
202
|
|
203 goto allocuvm_check_newszvm_impl(vm, pgdir, oldsz, newsz, next(...));
|
|
204 }
|
|
205
|
|
206 __code clearpteuvm_impl(struct vm_impl* vm, pde_t* pgdir, char* uva, __code next(...)) {
|
|
207
|
|
208 goto clearpteu_check_ptevm_impl(vm, pgdir, uva, next(...));
|
|
209 }
|
|
210
|
|
211 __code copyuvmvm_impl(struct vm_impl* vm, pde_t* pgdir, uint sz, __code next(...)) {
|
|
212
|
|
213 goto copyuvm_check_nullvm_impl(vm, pgdir, sz, __code next(...));
|
|
214 }
|
|
215
|
|
216 __code uva2kavm_impl(struct vm_impl* vm, pde_t* pgdir, char* uva, __code next(...)) {
|
|
217
|
|
218 goto uva2ka_check_pe_types(vm, pgdir, uva, next(...));
|
|
219 }
|
|
220
|
|
221 __code copyoutvm_impl(struct vm_impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...)) {
|
|
222
|
|
223 vm->buf = (char*) pp;
|
|
224
|
|
225 goto copyout_loopvm_impl(vm, pgdir, va, pp, len, va0, pa0, next(...));
|
|
226 }
|
|
227
|
|
228 __code paging_intvm_impl(struct vm_impl* vm, uint phy_low, uint phy_hi, __code next(...)) {
|
|
229
|
|
230 goto paging_intvmvm_impl(vm, phy_low, phy_hi, next(...));
|
|
231 }
|
|
232
|
|
233 __code vm_void_ret(struct vm_impl* vm) {
|
|
234 return;
|
|
235 }
|
|
236
|
12
|
237 \end{lstlisting}
|
8
|
238
|
12
|
239
|
|
240 2行目のようにインターフェースのヘッダーファイルは \#interface で呼び出す。
|
|
241 \par
|
|
242 create\_impl の関数内で、インターフェースを vm で定義し、23行目の vm-$>$void\_ret のようにそれぞれのインターフェースに対応させていく。
|
|
243 \par
|
|
244 CbCは1つ1つの関数の信頼性を保障させるために細かくする必要があるので、for文やif文がある場合はさらに実装を分ける。vm と同じように vm\_impl を定義し、遷移する関数名に対応させていく。分けた実装はさらに別で実装する(vm\_impl\_private.cbc)。
|
|
245
|
|
246
|
|
247 % インターフェースを呼び出す場合は、struct vm* vm = createvm_impl(cbc_context);
|
|
248 \par
|
|
249
|
|
250
|
|
251
|
|
252
|
|
253
|
|
254
|
8
|
255
|
|
256
|
|
257 \section{インターフェース内の private メソッド}
|
|
258 インターフェースで定義した Code Gear 以外の Code Gaer も記述することができる。
|
|
259 この Code Gear は基本的にインターフェースで指定された Code Gear 内からのみ継続されるため、
|
|
260 Java の private メソッドのように扱われる。
|
11
|
261 \par
|
12
|
262 インターフェースと同じようにヘッダーファイルをソースコード \ref{impl_vm_privateh} で定義する。
|
8
|
263
|
|
264
|
|
265 \begin{lstlisting}[frame=lrbt,label=impl_vm_privateh,caption={\footnotesize vm private のヘッダーファイル}]
|
|
266 typedef struct vm_impl<Impl, Isa> impl vm{
|
|
267 union Data* vm_impl;
|
|
268 uint i;
|
|
269 pte_t* pte;
|
|
270 uint sz;
|
|
271 pde_t* pgdir;
|
|
272 char* addr;
|
|
273 struct inode* ip;
|
|
274 uint offset;
|
|
275 uint pa;
|
|
276 uint n;
|
|
277 uint oldsz;
|
|
278 uint newsz;
|
|
279 uint a;
|
|
280 int ret;
|
|
281 char* mem;
|
|
282 char* uva;
|
|
283 pde_t* d;
|
|
284 uint ap;
|
|
285 uint phy_low;
|
|
286 uint phy_hi;
|
|
287 uint va;
|
|
288 void* pp;
|
|
289 uint len;
|
|
290 char* buf;
|
|
291 char* pa0;
|
|
292 uint va0;
|
|
293 proc_struct* p;
|
|
294 char* init;
|
|
295
|
|
296 __code kpt_alloc_check_impl(Type* vm_impl, __code next(...));
|
|
297 __code loaduvm_ptesize_check(Type* vm_impl, __code next(int ret, ...));
|
|
298 __code loaduvm_loop(Type* vm_impl, uint i, pte_t* pte, uint sz, __code next(int ret, ...));
|
|
299 __code allocuvm_check_newsz(Type* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, __code next(...));
|
|
300 __code allocuvm_loop(Type* vm_impl, pde_t* pgdir, uint oldsz, uint newsz, uint a, __code next(...));
|
|
301 __code copyuvm_check_null(Type* vm_impl, pde_t* pgdir, uint sz, __code next(...));
|
|
302 __code copyuvm_loop(Type* vm_impl,pde_t* pgdir, uint sz, pde_t* d, pte_t* pte, uint pa, uint i, uint ap, char* mem, __code next(int ret, ...));
|
|
303 __code clearpteu_check_ptevm_impl(Type* vm_impl, pde_t* pgdir, char* uva, __code next(...));
|
|
304 __code uva2ka_check_pe_types(Type* vm_impl, pde_t* pgdir, char* uva, __code next(...));
|
|
305 __code paging_intvm_impl(Type* vm_impl, uint phy_low, uint phy_hi, __code next(...));
|
|
306 __code copyout_loopvm_impl(Type* vm_impl, pde_t* pgdir, uint va, void* pp, uint len, __code next(...));
|
|
307 __code switchuvm_check_pgdirvm_impl(struct vm_impl* vm_impl, struct proc* p, __code next(...));
|
|
308 __code init_inituvm_check_sz(struct vm_impl* vm_impl, pde_t* pgdir, char* init, uint sz, __code next(...));
|
|
309 __code void_ret(Type* vm_impl);
|
|
310 __code next(...);
|
|
311 } vm_impl;
|
|
312
|
|
313 \end{lstlisting}
|
|
314
|
12
|
315
|
11
|
316
|
12
|
317 private での CbC の記述を vm.c と比べて説明する。
|
|
318 全体の記述量が多いため、if文とfor文のある loaduvm という関数で説明を行う。
|
|
319
|
|
320
|
|
321 \begin{lstlisting}[frame=lrbt,label=vm_loaduvm,caption={\footnotesize vm.c のloaduvm}]
|
8
|
322
|
12
|
323 int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
|
|
324 {
|
|
325 uint i, pa, n;
|
|
326 pte_t *pte;
|
8
|
327
|
12
|
328 if ((uint) addr % PTE_SZ != 0) {
|
|
329 panic("loaduvm: addr must be page aligned");
|
|
330 }
|
8
|
331
|
12
|
332 for (i = 0; i < sz; i += PTE_SZ) {
|
|
333 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
|
|
334 panic("loaduvm: address should exist");
|
|
335 }
|
8
|
336
|
12
|
337 pa = PTE_ADDR(*pte);
|
8
|
338
|
12
|
339 if (sz - i < PTE_SZ) {
|
|
340 n = sz - i;
|
|
341 } else {
|
|
342 n = PTE_SZ;
|
|
343 }
|
8
|
344
|
12
|
345 if (readi(ip, p2v(pa), offset + i, n) != n) {
|
|
346 return -1;
|
|
347 }
|
|
348 }
|
8
|
349
|
12
|
350 return 0;
|
8
|
351 }
|
|
352
|
|
353 \end{lstlisting}
|
|
354
|
|
355
|
12
|
356
|
|
357
|
|
358 \begin{lstlisting}[frame=lrbt,label=impl_vm_loaduvm,caption={\footnotesize privateでの loaduvm の実装}]
|
|
359 #interface "vm_impl.h"
|
|
360
|
|
361 __code loaduvm_ptesize_checkvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
362 char* addr = vm_impl->addr;
|
|
363
|
|
364 if ((uint) addr %PTE_SZ != 0) {
|
|
365 // goto panic
|
|
366 }
|
|
367
|
|
368 goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
|
|
369 }
|
|
370
|
|
371 __code loaduvm_loopvm_impl(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
372 uint i = vm_impl->i;
|
|
373 uint sz = vm_impl->sz;
|
|
374
|
|
375 if (i < sz) {
|
|
376 goto loaduvm_check_pgdir(vm_impl, next(ret, ...));
|
|
377 }
|
|
378
|
|
379 goto loaduvm_exit(vm_impl, next(ret, ...));
|
|
380 }
|
|
381
|
|
382
|
|
383 static pte_t* walkpgdir (pde_t *pgdir, const void *va, int alloc)
|
|
384 {
|
|
385 pde_t *pde;
|
|
386 pte_t *pgtab;
|
|
387
|
|
388 // pgdir points to the page directory, get the page direcotry entry (pde)
|
|
389 pde = &pgdir[PDE_IDX(va)];
|
|
390
|
|
391 if (*pde & PE_TYPES) {
|
|
392 pgtab = (pte_t*) p2v(PT_ADDR(*pde));
|
|
393
|
|
394 } else {
|
|
395 if (!alloc || (pgtab = (pte_t*) kpt_alloc()) == 0) {
|
|
396 return 0;
|
|
397 }
|
|
398
|
|
399 // Make sure all those PTE_P bits are zero.
|
|
400 memset(pgtab, 0, PT_SZ);
|
|
401
|
|
402 // The permissions here are overly generous, but they can
|
|
403 // be further restricted by the permissions in the page table
|
|
404 // entries, if necessary.
|
|
405 *pde = v2p(pgtab) | UPDE_TYPE;
|
|
406 }
|
|
407
|
|
408 return &pgtab[PTE_IDX(va)];
|
|
409 }
|
|
410
|
|
411
|
|
412 __code loaduvm_check_pgdir(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
413 pte_t* pte = vm_impl->pte;
|
|
414 pde_t* pgdir = vm_impl->pgdir;
|
|
415 uint i = vm_impl->i;
|
|
416 char* addr = vm_impl->addr;
|
|
417 uint pa = vm_impl->pa;
|
|
418
|
|
419 if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) {
|
|
420 // goto panic
|
|
421 }
|
|
422 pa = PTE_ADDR(*pte);
|
|
423
|
|
424 vm_impl->pte = pte;
|
|
425 vm_impl->pgdir = pgdir;
|
|
426 vm_impl->addr = addr;
|
|
427 vm_impl->pa = pa;
|
|
428
|
|
429 goto loaduvm_check_PTE_SZ(vm_impl, next(ret, ...));
|
|
430 }
|
|
431
|
|
432 __code loaduvm_check_PTE_SZ(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
433 uint sz = vm_impl->sz;
|
|
434 uint i = vm_impl->i;
|
|
435 uint n = vm_impl->n;
|
|
436 struct inode* ip = vm_impl->ip;
|
|
437 uint pa = vm_impl->pa;
|
|
438 uint offset = vm_impl->offset;
|
|
439
|
|
440 if (sz - i < PTE_SZ) {
|
|
441 n = sz - i;
|
|
442 } else {
|
|
443 n = PTE_SZ;
|
|
444 }
|
|
445
|
|
446 if (readi(ip, p2v(pa), offset + i, n) != n) {
|
|
447 ret = -1;
|
|
448 goto next(ret, ...);
|
|
449 }
|
|
450
|
|
451 vm_impl->n = n;
|
|
452
|
|
453 goto loaduvm_loopvm_impl(vm_impl, next(ret, ...));
|
|
454 }
|
|
455
|
|
456 __code loaduvm_exit(struct vm_impl* vm_impl, __code next(int ret, ...)) {
|
|
457 ret = 0;
|
|
458 goto next(ret, ...);
|
|
459 }
|
|
460
|
|
461 \end{lstlisting}
|
|
462
|
|
463
|
|
464
|
|
465
|
|
466
|
10
|
467 \section{インターフェースの呼び出し}
|
12
|
468 定義したインターフェースの呼び出し方について説明する。
|
10
|
469 CbC の場合 goto による遷移を行うので、関数呼び出しのように goto 以降のコードを実行できない。
|
12
|
470 例として、ソースコード \ref{cbc_goto} の16行目のように goto によってインターフェースで定義した命令を行うと、戻ってこれないため17行目以降が実行されなくなる。
|
10
|
471
|
|
472
|
|
473 \begin{lstlisting}[frame=lrbt,label=cbc_goto,caption={\footnotesize cbc インターフェースのgoto}]
|
|
474
|
|
475 void userinit(void)
|
|
476 {
|
|
477 struct proc* p;
|
|
478 extern char _binary_initcode_start[], _binary_initcode_size[];
|
|
479
|
|
480 p = allocproc();
|
|
481 initContext(&p->cbc_context);
|
|
482
|
|
483 initproc = p;
|
|
484
|
|
485 if((p->pgdir = kpt_alloc()) == NULL) {
|
|
486 panic("userinit: out of memory?");
|
|
487 }
|
|
488
|
|
489 goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
|
|
490 p->sz = PTE_SZ;
|
|
491
|
|
492 // craft the trapframe as if
|
|
493 memset(p->tf, 0, sizeof(*p->tf));
|
|
494
|
|
495
|
|
496 \end{lstlisting}
|
|
497
|
|
498
|
|
499
|
|
500
|
11
|
501 \begin{lstlisting}[frame=lrbt,label=dummy,caption={\footnotesize dummy を使った呼び出し}]
|
10
|
502
|
|
503
|
|
504 void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[])
|
|
505 {
|
|
506 // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
|
|
507 goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
|
|
508
|
|
509 }
|
|
510
|
|
511
|
|
512
|
|
513 __ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip
|
|
514
|
|
515 struct vm* vm = createvm_impl(cbc_context);
|
|
516 // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret);
|
|
517 Gearef(cbc_context, vm)->vm = (union Data*) vm;
|
|
518 Gearef(cbc_context, vm)->pgdir = pgdir;
|
|
519 Gearef(cbc_context, vm)->init = init;
|
|
520 Gearef(cbc_context, vm)->sz = sz ;
|
|
521 Gearef(cbc_context, vm)->next = C_vm_void_ret ;
|
|
522 goto meta(cbc_context, vm->init_inituvm);
|
|
523 }
|
|
524
|
|
525
|
|
526 void userinit(void)
|
|
527 {
|
|
528 struct proc* p;
|
|
529 extern char _binary_initcode_start[], _binary_initcode_size[];
|
|
530
|
|
531 p = allocproc();
|
|
532 initContext(&p->cbc_context);
|
|
533
|
|
534 initproc = p;
|
|
535
|
|
536 if((p->pgdir = kpt_alloc()) == NULL) {
|
|
537 panic("userinit: out of memory?");
|
|
538 }
|
|
539
|
|
540 dummy(p, _binary_initcode_start, _binary_initcode_size);
|
|
541
|
|
542
|
|
543
|
|
544 \end{lstlisting}
|
12
|
545 ソースコードの説明
|
|
546
|
|
547
|
|
548
|
|
549
|
|
550
|
|
551
|
|
552
|
|
553
|