Skip to content

Commit

Permalink
Finish all challs in Lab 3
Browse files Browse the repository at this point in the history
  • Loading branch information
sev1n75 committed Mar 17, 2024
1 parent e908dc3 commit 816f857
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 72 deletions.
1 change: 1 addition & 0 deletions answers-pgtbl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
when srcva < p->sz buf len is less than 0
14 changes: 10 additions & 4 deletions kernel/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ int fork(void);
int growproc(int);
pagetable_t proc_pagetable(struct proc *);
void proc_freepagetable(pagetable_t, uint64);
void proc_kpagetable_trapframe(struct proc *);
void proc_clear_kpagetable(pagetable_t, uint64);
int kill(int);
struct cpu* mycpu(void);
struct cpu* getmycpu(void);
Expand Down Expand Up @@ -166,12 +168,12 @@ uint64 kvmpa(uint64);
void kvmmap(pagetable_t, uint64, uint64, uint64, int);
int mappages(pagetable_t, uint64, uint64, uint64, int);
pagetable_t uvmcreate(void);
void uvminit(pagetable_t, uchar *, uint);
uint64 uvmalloc(pagetable_t, uint64, uint64);
uint64 uvmdealloc(pagetable_t, uint64, uint64);
void uvminit(pagetable_t, pagetable_t, uchar *, uint);
uint64 uvmalloc(pagetable_t, pagetable_t, uint64, uint64);
uint64 uvmdealloc(pagetable_t, uint64, uint64, int);
#ifdef SOL_COW
#else
int uvmcopy(pagetable_t, pagetable_t, uint64);
int uvmcopy(pagetable_t, pagetable_t, pagetable_t, uint64);
#endif
void uvmfree(pagetable_t, uint64);
void uvmunmap(pagetable_t, uint64, uint64, int);
Expand All @@ -181,6 +183,7 @@ int copyout(pagetable_t, uint64, char *, uint64);
int copyin(pagetable_t, char *, uint64, uint64);
int copyinstr(pagetable_t, char *, uint64, uint64);
void vmprint(pagetable_t);
pte_t * walk(pagetable_t , uint64 , int);

// plic.c
void plicinit(void);
Expand All @@ -193,6 +196,9 @@ void virtio_disk_init(void);
void virtio_disk_rw(struct buf *, int);
void virtio_disk_intr(void);

// vmcopyin.c
int copyin_new(pagetable_t, char *, uint64, uint64);
int copyinstr_new(pagetable_t, char *, uint64, uint64);
// number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))

Expand Down
23 changes: 20 additions & 3 deletions kernel/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ exec(char *path, char **argv)
if((pagetable = proc_pagetable(p)) == 0)
goto bad;

uvmunmap(p->kpagetable, 0, PGROUNDUP(p->sz)/PGSIZE, 0);

// Load program into memory.
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
if(readi(ip, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph))
Expand All @@ -49,7 +51,7 @@ exec(char *path, char **argv)
if(ph.vaddr + ph.memsz < ph.vaddr)
goto bad;
uint64 sz1;
if((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz)) == 0)
if((sz1 = uvmalloc(pagetable, p->kpagetable, sz, ph.vaddr + ph.memsz)) == 0)
goto bad;
sz = sz1;
if(ph.vaddr % PGSIZE != 0)
Expand All @@ -68,7 +70,7 @@ exec(char *path, char **argv)
// Use the second as the user stack.
sz = PGROUNDUP(sz);
uint64 sz1;
if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE)) == 0)
if((sz1 = uvmalloc(pagetable, p->kpagetable, sz, sz + 2*PGSIZE)) == 0)
goto bad;
sz = sz1;
uvmclear(pagetable, sz-2*PGSIZE);
Expand Down Expand Up @@ -121,8 +123,23 @@ exec(char *path, char **argv)
return argc; // this ends up in a0, the first argument to main(argc, argv)

bad:
if(pagetable)
if(pagetable) {
proc_freepagetable(pagetable, sz);
uvmunmap(p->kpagetable, 0, PGROUNDUP(sz)/PGSIZE, 0); // doing the same when dealing with pagetable
// recover userpart of kpagetable
pte_t *pte;
uint64 pa, i;
uint flags;
for(i = 0; i < p->sz; i += PGSIZE){
if((pte = walk(p->pagetable, i, 0)) == 0)
panic("exec: pte should exist");
if((*pte & PTE_V) == 0)
panic("exec: page not present");
pa = PTE2PA(*pte);
flags = PTE_FLAGS(*pte);
mappages(p->kpagetable, i, PGSIZE, (uint64)pa, (flags&(~PTE_U)) );
}
}
if(ip){
iunlockput(ip);
end_op();
Expand Down
1 change: 1 addition & 0 deletions kernel/memlayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@
// TRAPFRAME (p->trapframe, used by the trampoline)
// TRAMPOLINE (the same page as in the kernel)
#define TRAPFRAME (TRAMPOLINE - PGSIZE)
#define MAXUVA 0x0c000000L
30 changes: 26 additions & 4 deletions kernel/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ allocproc(void)
release(&p->lock);
return 0;
}
proc_kpagetable_trapframe(p);

// Set up new context to start executing at forkret,
// which returns to user space.
Expand All @@ -143,6 +144,8 @@ freeproc(struct proc *p)
if(p->trapframe)
kfree((void*)p->trapframe);
p->trapframe = 0;
if(p->kpagetable)
proc_clear_kpagetable(p->kpagetable, p->sz);
if(p->pagetable)
proc_freepagetable(p->pagetable, p->sz);
if(p->kstack) {
Expand Down Expand Up @@ -207,6 +210,23 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz)
uvmfree(pagetable, sz);
}

// map current proc->>trapframe to kpagetable
void proc_kpagetable_trapframe(struct proc *p){
// map the trapframe just below TRAMPOLINE, for trampoline.S.
if(mappages(p->kpagetable, TRAPFRAME, PGSIZE, (uint64)(p->trapframe), PTE_R | PTE_W) < 0)
panic("proc_kpagetable_trapframe");
}

// clear user space and trapframe
// not free kpagetable
// better be called before proc_freepagetable?not sure
void proc_clear_kpagetable(pagetable_t kpagetable, uint64 sz) {
uvmunmap(kpagetable, TRAPFRAME, 1, 0);

if(sz > 0)
uvmunmap(kpagetable, 0, PGROUNDUP(sz)/PGSIZE, 0);
}

// a user program that calls exec("/init")
// od -t xC initcode
uchar initcode[] = {
Expand All @@ -230,7 +250,8 @@ userinit(void)

// allocate one user page and copy init's instructions
// and data into it.
uvminit(p->pagetable, initcode, sizeof(initcode));
// and map to kpagetable
uvminit(p->pagetable, p->kpagetable, initcode, sizeof(initcode));
p->sz = PGSIZE;

// prepare for the very first "return" from kernel to user.
Expand All @@ -255,11 +276,12 @@ growproc(int n)

sz = p->sz;
if(n > 0){
if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0) {
if((sz = uvmalloc(p->pagetable, p->kpagetable, sz, sz + n)) == 0) {
return -1;
}
} else if(n < 0){
sz = uvmdealloc(p->pagetable, sz, sz + n);
uvmdealloc(p->kpagetable, sz, sz + n, 0);
sz = uvmdealloc(p->pagetable, sz, sz + n, 1);
}
p->sz = sz;
return 0;
Expand All @@ -280,7 +302,7 @@ fork(void)
}

// Copy user memory from parent to child.
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
if(uvmcopy(p->pagetable, np->pagetable, np->kpagetable, p->sz) < 0){
freeproc(np);
release(&np->lock);
return -1;
Expand Down
91 changes: 30 additions & 61 deletions kernel/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ kvminit()
kvmmap(kernel_pagetable, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);

// CLINT
kvmmap(kernel_pagetable, CLINT, CLINT, 0x10000, PTE_R | PTE_W);
//kvmmap(kernel_pagetable, CLINT, CLINT, 0x10000, PTE_R | PTE_W);

// PLIC
kvmmap(kernel_pagetable, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
Expand All @@ -53,7 +53,7 @@ pagetable_t kvm_pagetable() {
memset(kpagetable, 0, PGSIZE);
kvmmap(kpagetable, UART0, UART0, PGSIZE, PTE_R | PTE_W);
kvmmap(kpagetable, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
kvmmap(kpagetable, CLINT, CLINT, 0x10000, PTE_R | PTE_W);
//kvmmap(kpagetable, CLINT, CLINT, 0x10000, PTE_R | PTE_W);
kvmmap(kpagetable, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
kvmmap(kpagetable, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);
kvmmap(kpagetable, (uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W);
Expand Down Expand Up @@ -225,7 +225,7 @@ uvmcreate()
// for the very first process.
// sz must be less than a page.
void
uvminit(pagetable_t pagetable, uchar *src, uint sz)
uvminit(pagetable_t pagetable, pagetable_t kpagetable, uchar *src, uint sz)
{
char *mem;

Expand All @@ -234,31 +234,42 @@ uvminit(pagetable_t pagetable, uchar *src, uint sz)
mem = kalloc();
memset(mem, 0, PGSIZE);
mappages(pagetable, 0, PGSIZE, (uint64)mem, PTE_W|PTE_R|PTE_X|PTE_U);
mappages(kpagetable, 0, PGSIZE, (uint64)mem, PTE_W|PTE_R|PTE_X);
memmove(mem, src, sz);
}

// Allocate PTEs and physical memory to grow process from oldsz to
// newsz, which need not be page aligned. Returns new size or 0 on error.
uint64
uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
uvmalloc(pagetable_t pagetable, pagetable_t kpagetable, uint64 oldsz, uint64 newsz)
{
char *mem;
uint64 a;

if(newsz < oldsz)
return oldsz;
if(PGROUNDUP(newsz) >= MAXUVA)
return 0;

oldsz = PGROUNDUP(oldsz);
for(a = oldsz; a < newsz; a += PGSIZE){
mem = kalloc();
if(mem == 0){
uvmdealloc(pagetable, a, oldsz);
uvmdealloc(kpagetable, a, oldsz, 0);
uvmdealloc(pagetable, a, oldsz, 1);
return 0;
}
memset(mem, 0, PGSIZE);
if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
kfree(mem);
uvmdealloc(pagetable, a, oldsz);
uvmdealloc(kpagetable, a, oldsz, 0);
uvmdealloc(pagetable, a, oldsz, 1);
return 0;
}
if(mappages(kpagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R) != 0){
kfree(mem);
uvmdealloc(kpagetable, a, oldsz, 0);
uvmdealloc(pagetable, a, oldsz, 1);
return 0;
}
}
Expand All @@ -270,14 +281,14 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
// need to be less than oldsz. oldsz can be larger than the actual
// process size. Returns the new process size.
uint64
uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int do_free)
{
if(newsz >= oldsz)
return oldsz;

if(PGROUNDUP(newsz) < PGROUNDUP(oldsz)){
int npages = (PGROUNDUP(oldsz) - PGROUNDUP(newsz)) / PGSIZE;
uvmunmap(pagetable, PGROUNDUP(newsz), npages, 1);
uvmunmap(pagetable, PGROUNDUP(newsz), npages, do_free);
}

return newsz;
Expand All @@ -289,6 +300,7 @@ void
freewalk(pagetable_t pagetable)
{
// there are 2^9 = 512 PTEs in a page table.
//vmprint(pagetable);
for(int i = 0; i < 512; i++){
pte_t pte = pagetable[i];
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
Expand Down Expand Up @@ -320,7 +332,7 @@ void kvm_freepagetable(pagetable_t pagetable) {
uint64 page_size;
uvmunmap(pagetable, UART0, PGSIZE/PGSIZE, 0);
uvmunmap(pagetable, VIRTIO0, PGSIZE/PGSIZE, 0);
uvmunmap(pagetable, CLINT, 0x10000/PGSIZE, 0);
//uvmunmap(pagetable, CLINT, 0x10000/PGSIZE, 0);
uvmunmap(pagetable, PLIC, 0x400000/PGSIZE, 0);

page_size = PGROUNDUP((uint64)etext - KERNBASE);
Expand All @@ -342,7 +354,7 @@ void kvm_freepagetable(pagetable_t pagetable) {
// returns 0 on success, -1 on failure.
// frees any allocated pages on failure.
int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
uvmcopy(pagetable_t old, pagetable_t new, pagetable_t new_kpagetable, uint64 sz)
{
pte_t *pte;
uint64 pa, i;
Expand All @@ -363,10 +375,16 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
kfree(mem);
goto err;
}
if(mappages(new_kpagetable, i, PGSIZE, (uint64)mem, (flags&(~PTE_U)) ) != 0){
kfree(mem);
goto err;
}

}
return 0;

err:
uvmunmap(new_kpagetable, 0, i / PGSIZE, 0);
uvmunmap(new, 0, i / PGSIZE, 1);
return -1;
}
Expand Down Expand Up @@ -415,23 +433,7 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
int
copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
{
uint64 n, va0, pa0;

while(len > 0){
va0 = PGROUNDDOWN(srcva);
pa0 = walkaddr(pagetable, va0);
if(pa0 == 0)
return -1;
n = PGSIZE - (srcva - va0);
if(n > len)
n = len;
memmove(dst, (void *)(pa0 + (srcva - va0)), n);

len -= n;
dst += n;
srcva = va0 + PGSIZE;
}
return 0;
return copyin_new(pagetable, dst, srcva, len);
}

// Copy a null-terminated string from user to kernel.
Expand All @@ -441,40 +443,7 @@ copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len)
int
copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max)
{
uint64 n, va0, pa0;
int got_null = 0;

while(got_null == 0 && max > 0){
va0 = PGROUNDDOWN(srcva);
pa0 = walkaddr(pagetable, va0);
if(pa0 == 0)
return -1;
n = PGSIZE - (srcva - va0);
if(n > max)
n = max;

char *p = (char *) (pa0 + (srcva - va0));
while(n > 0){
if(*p == '\0'){
*dst = '\0';
got_null = 1;
break;
} else {
*dst = *p;
}
--n;
--max;
p++;
dst++;
}

srcva = va0 + PGSIZE;
}
if(got_null){
return 0;
} else {
return -1;
}
return copyinstr_new(pagetable, dst, srcva, max);
}

void vmprint(pagetable_t pagetable) {
Expand Down
1 change: 1 addition & 0 deletions time.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24

0 comments on commit 816f857

Please sign in to comment.