Skip to content

Commit 8f90d2b

Browse files
committed
my solution to lab3
1 parent 9f27730 commit 8f90d2b

14 files changed

+336
-21
lines changed

answer-lab3.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
1. 目的是为了将用户有权限触发的系统调用和其他用户不可交互的异常处理函数区分开来,
2+
如果处理函数都指向同一个函数就不能提供保护的同时实现系统调用。
3+
2. page fault handler的DPL是0,用户模式执行int $14会因为权限不够而触发general protection fault,即trap 13,
4+
在trap_init()里把page fault的idt项的DPL设为3,那么用户就可以执行int $14,不过这样会让用户可以越权执行内存管理。
5+
3. int3是在用户模式调用的,如果T_BRKPT的idt项的DPL为3那么就可以正常触发break point exception,如果DPL为0就会触发
6+
general protection fault。应把DPL设为3。
7+
4. 关键在于是否进行保护,int3的语义就是不进行保护的,所以可以把DPL设为3,而page fault不是。

inc/env.h

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct Env {
5454

5555
// Address space
5656
pde_t *env_pgdir; // Kernel virtual address of page dir
57+
uint32_t env_break;
5758
};
5859

5960
#endif // !JOS_INC_ENV_H

inc/x86.h

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33

44
#include <inc/types.h>
55

6+
#define wrmsr(msr,val1,val2) \
7+
__asm__ __volatile__("wrmsr" \
8+
: /* no outputs */ \
9+
: "c" (msr), "a" (val1), "d" (val2))
10+
611
static inline void
712
breakpoint(void)
813
{

kern/env.c

+85-3
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,21 @@ env_init(void)
116116
{
117117
// Set up envs array
118118
// 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+
}
119134

120135
// Per-CPU part of the initialization
121136
env_init_percpu();
@@ -179,7 +194,11 @@ env_setup_vm(struct Env *e)
179194
// - The functions in kern/pmap.h are handy.
180195

181196
// 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+
}
183202
// UVPT maps the env's own page table read-only.
184203
// Permissions: kernel R, user R
185204
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)
257276
// Pages should be writable by user and kernel.
258277
// Panic if any allocation attempt fails.
259278
//
260-
static void
279+
void
261280
region_alloc(struct Env *e, void *va, size_t len)
262281
{
263282
// LAB 3: Your code here.
@@ -267,6 +286,24 @@ region_alloc(struct Env *e, void *va, size_t len)
267286
// 'va' and 'len' values that are not page-aligned.
268287
// You should round va down, and round (va + len) up.
269288
// (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+
}
270307
}
271308

272309
//
@@ -323,11 +360,39 @@ load_icode(struct Env *e, uint8_t *binary)
323360
// What? (See env_run() and env_pop_tf() below.)
324361

325362
// 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+
}
326388

327389
// Now map one page for the program's initial stack
328390
// at virtual address USTACKTOP - PGSIZE.
329391

330392
// 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));
331396
}
332397

333398
//
@@ -341,6 +406,14 @@ void
341406
env_create(uint8_t *binary, enum EnvType type)
342407
{
343408
// 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;
344417
}
345418

346419
//
@@ -457,7 +530,16 @@ env_run(struct Env *e)
457530
// e->env_tf to sensible values.
458531

459532
// 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);
460543

461-
panic("env_run not yet implemented");
462544
}
463545

kern/env.h

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ void env_free(struct Env *e);
1616
void env_create(uint8_t *binary, enum EnvType type);
1717
void env_destroy(struct Env *e); // Does not return if e == curenv
1818

19+
void region_alloc(struct Env *e, void *va, size_t len);
20+
1921
int envid2env(envid_t envid, struct Env **env_store, bool checkperm);
2022
// The following two functions do not return
2123
void env_run(struct Env *e) __attribute__((noreturn));

kern/kdebug.c

+11
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ debuginfo_eip(uintptr_t addr, struct Eipdebuginfo *info)
142142
// Make sure this memory is valid.
143143
// Return -1 if it is not. Hint: Call user_mem_check.
144144
// LAB 3: Your code here.
145+
if (user_mem_check(curenv, usd, sizeof(*usd), 0) < 0)
146+
return -1;
145147

146148
stabs = usd->stabs;
147149
stab_end = usd->stab_end;
@@ -150,6 +152,10 @@ debuginfo_eip(uintptr_t addr, struct Eipdebuginfo *info)
150152

151153
// Make sure the STABS and string table memory is valid.
152154
// LAB 3: Your code here.
155+
if (user_mem_check(curenv, stabs, sizeof(*stabs), 0) < 0)
156+
return -1;
157+
if (user_mem_check(curenv, stabstr, sizeof(*stabstr), 0) < 0)
158+
return -1;
153159
}
154160

155161
// String table validity checks
@@ -204,6 +210,11 @@ debuginfo_eip(uintptr_t addr, struct Eipdebuginfo *info)
204210
// Look at the STABS documentation and <inc/stab.h> to find
205211
// which one.
206212
// Your code here.
213+
stab_binsearch(stabs, &lline, &rline, N_SLINE, addr);
214+
if (lline <= rline)
215+
info->eip_line = lline;
216+
else
217+
return -1;
207218

208219

209220
// Search backwards from the line number for the relevant filename

kern/pmap.c

+28
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ mem_init(void)
167167
}
168168
page_free_list = NULL;
169169

170+
envs = (struct Env *)boot_alloc(NENV * sizeof(struct Env));
171+
for (size_t i = 0; i < NENV; i++) {
172+
memset(envs + i, 0, sizeof(struct Env));
173+
}
174+
curenv = NULL;
175+
170176

171177
//////////////////////////////////////////////////////////////////////
172178
// Now that we've allocated the initial kernel data structures, we set
@@ -192,6 +198,8 @@ mem_init(void)
192198
// Your code goes here:
193199
boot_map_region(kern_pgdir, UPAGES, PTSIZE, PADDR(pages), PTE_U);
194200

201+
boot_map_region(kern_pgdir, UENVS, PTSIZE, PADDR(envs), PTE_U);
202+
195203
//////////////////////////////////////////////////////////////////////
196204
// Use the physical memory that 'bootstack' refers to as the kernel
197205
// stack. The kernel stack grows down from virtual address KSTACKTOP.
@@ -563,6 +571,26 @@ int
563571
user_mem_check(struct Env *env, const void *va, size_t len, int perm)
564572
{
565573
// LAB 3: Your code here.
574+
char *sva, *eva;
575+
uintptr_t uva;
576+
pte_t *p;
577+
578+
uva = (uintptr_t)va;
579+
if (uva >= ULIM) {
580+
user_mem_check_addr = uva;
581+
return -E_FAULT;
582+
}
583+
584+
sva = (char *)ROUNDDOWN(uva, PGSIZE);
585+
eva = (char *)ROUNDUP(uva + len, PGSIZE);
586+
for (; sva < eva; sva += PGSIZE) {
587+
p = pgdir_walk(env->env_pgdir, sva, 0);
588+
if (!p || ((*p & (perm | PTE_P)) != (perm | PTE_P))) {
589+
user_mem_check_addr = MAX(uva, (uintptr_t)sva);
590+
return -E_FAULT;
591+
}
592+
}
593+
566594

567595
return 0;
568596
}

kern/syscall.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ sys_cputs(const char *s, size_t len)
2121
// Destroy the environment if not.
2222

2323
// LAB 3: Your code here.
24+
user_mem_assert(curenv, s, len, 0);
2425

2526
// Print the string supplied by the user.
2627
cprintf("%.*s", len, s);
@@ -77,7 +78,9 @@ static int
7778
sys_sbrk(uint32_t inc)
7879
{
7980
// LAB3: your code here.
80-
return 0;
81+
region_alloc(curenv, (void *)curenv->env_break, inc);
82+
curenv->env_break += inc;
83+
return curenv->env_break;
8184
}
8285

8386
// Dispatches to the correct kernel function, passing the arguments.
@@ -88,11 +91,24 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
8891
// Return any appropriate return value.
8992
// LAB 3: Your code here.
9093

91-
panic("syscall not implemented");
94+
//panic("syscall not implemented");
9295

9396
switch (syscallno) {
94-
default:
95-
return -E_INVAL;
97+
case SYS_cputs:
98+
sys_cputs((char *)a1, (size_t)a2);
99+
return 0;
100+
case SYS_cgetc:
101+
return sys_cgetc();
102+
case SYS_getenvid:
103+
return sys_getenvid();
104+
case SYS_env_destroy:
105+
return sys_env_destroy((envid_t)a1);
106+
case SYS_map_kernel_page:
107+
return sys_map_kernel_page((void *)a1, (void *)a2);
108+
case SYS_sbrk:
109+
return sys_sbrk(a1);
110+
default:
111+
return -E_INVAL;
96112
}
97113
}
98114

0 commit comments

Comments
 (0)