@@ -116,6 +116,21 @@ env_init(void)
116
116
{
117
117
// Set up envs array
118
118
// LAB 3: Your code here.
119
+ struct Env * p , * tail ;
120
+
121
+ tail = env_free_list ;
122
+
123
+ for (size_t i = 0 ; i < NENV ; i ++ ) {
124
+ p = envs + i ;
125
+ p -> env_id = 0 ;
126
+ p -> env_status = ENV_FREE ;
127
+ if (tail == NULL ) {
128
+ tail = env_free_list = p ;
129
+ } else {
130
+ tail -> env_link = p ;
131
+ tail = tail -> env_link ;
132
+ }
133
+ }
119
134
120
135
// Per-CPU part of the initialization
121
136
env_init_percpu ();
@@ -179,7 +194,11 @@ env_setup_vm(struct Env *e)
179
194
// - The functions in kern/pmap.h are handy.
180
195
181
196
// LAB 3: Your code here.
182
-
197
+ p -> pp_ref ++ ;
198
+ e -> env_pgdir = page2kva (p );
199
+ for (i = PDX (UTOP ); i < NPDENTRIES ; i ++ ) {
200
+ e -> env_pgdir [i ] = kern_pgdir [i ];
201
+ }
183
202
// UVPT maps the env's own page table read-only.
184
203
// Permissions: kernel R, user R
185
204
e -> env_pgdir [PDX (UVPT )] = PADDR (e -> env_pgdir ) | PTE_P | PTE_U ;
@@ -257,7 +276,7 @@ env_alloc(struct Env **newenv_store, envid_t parent_id)
257
276
// Pages should be writable by user and kernel.
258
277
// Panic if any allocation attempt fails.
259
278
//
260
- static void
279
+ void
261
280
region_alloc (struct Env * e , void * va , size_t len )
262
281
{
263
282
// LAB 3: Your code here.
@@ -267,6 +286,24 @@ region_alloc(struct Env *e, void *va, size_t len)
267
286
// 'va' and 'len' values that are not page-aligned.
268
287
// You should round va down, and round (va + len) up.
269
288
// (Watch out for corner-cases!)
289
+ struct PageInfo * p ;
290
+ char * eva , * sva ;
291
+
292
+ if (len <= 0 ) {
293
+ return ;
294
+ }
295
+ //TODO: check later
296
+ eva = ROUNDUP (va + len , PGSIZE );
297
+ sva = ROUNDDOWN (va , PGSIZE );
298
+ for (; sva < eva ; sva += PGSIZE ) {
299
+ if (!(p = page_alloc (0 ))) {
300
+ panic ("region_alloc: %e\n" , - E_NO_MEM );
301
+ }
302
+ p -> pp_ref ++ ;
303
+ if (page_insert (e -> env_pgdir , p , sva , PTE_W | PTE_U ) < 0 ) {
304
+ panic ("region_alloc: %e\n" , - E_NO_MEM );
305
+ }
306
+ }
270
307
}
271
308
272
309
//
@@ -323,11 +360,39 @@ load_icode(struct Env *e, uint8_t *binary)
323
360
// What? (See env_run() and env_pop_tf() below.)
324
361
325
362
// LAB 3: Your code here.
363
+ struct Proghdr * ph , * eph ;
364
+ struct Elf * elf ;
365
+
366
+ elf = (struct Elf * )binary ;
367
+
368
+ if (elf -> e_magic != ELF_MAGIC )
369
+ panic ("load_icode: bad\n" );
370
+
371
+ lcr3 (PADDR (e -> env_pgdir ));
372
+
373
+ e -> env_break = 0 ;
374
+ ph = (struct Proghdr * ) ((uint8_t * ) elf + elf -> e_phoff );
375
+ eph = ph + elf -> e_phnum ;
376
+ for (; ph < eph ; ph ++ ) {
377
+ if (ph -> p_type != ELF_PROG_LOAD )
378
+ continue ;
379
+ if (ph -> p_flags == (ELF_PROG_FLAG_READ | ELF_PROG_FLAG_WRITE )) {
380
+ e -> env_break = MAX ((ph -> p_va + ph -> p_memsz ), e -> env_break );
381
+ }
382
+ region_alloc (e , (void * )ph -> p_va , ph -> p_memsz );
383
+ for (size_t i = 0 ; i < ph -> p_filesz ; i ++ ) {
384
+ * (((uint8_t * )ph -> p_va ) + i ) = * (binary + ph -> p_offset + i );
385
+ }
386
+ memset ((void * )(ph -> p_va + ph -> p_filesz ), 0 , ph -> p_memsz - ph -> p_filesz );
387
+ }
326
388
327
389
// Now map one page for the program's initial stack
328
390
// at virtual address USTACKTOP - PGSIZE.
329
391
330
392
// LAB 3: Your code here.
393
+ region_alloc (e , (void * )(USTACKTOP - PGSIZE ), PGSIZE );
394
+ e -> env_tf .tf_eip = elf -> e_entry ;
395
+ lcr3 (PADDR (kern_pgdir ));
331
396
}
332
397
333
398
//
@@ -341,6 +406,14 @@ void
341
406
env_create (uint8_t * binary , enum EnvType type )
342
407
{
343
408
// LAB 3: Your code here.
409
+ struct Env * e ;
410
+ int r ;
411
+
412
+ if ((r = env_alloc (& e , 0 )) < 0 ) {
413
+ panic ("env_create: %e\n" , r );
414
+ }
415
+ load_icode (e , binary );
416
+ e -> env_type = type ;
344
417
}
345
418
346
419
//
@@ -457,7 +530,16 @@ env_run(struct Env *e)
457
530
// e->env_tf to sensible values.
458
531
459
532
// LAB 3: Your code here.
533
+ //panic("env_run not yet implemented");
534
+ if (curenv && curenv -> env_status == ENV_RUNNING )
535
+ curenv -> env_status = ENV_RUNNABLE ;
536
+
537
+ curenv = e ;
538
+ curenv -> env_status = ENV_RUNNING ;
539
+ curenv -> env_runs ++ ;
540
+ lcr3 (PADDR (curenv -> env_pgdir ));
541
+
542
+ env_pop_tf (& curenv -> env_tf );
460
543
461
- panic ("env_run not yet implemented" );
462
544
}
463
545
0 commit comments