Merge branch 'riscv' into riscv-proc

This commit is contained in:
Frans Kaashoek 2019-07-02 14:19:31 -04:00
commit 1e4d7065d6
13 changed files with 375 additions and 133 deletions

View file

@ -185,9 +185,9 @@ pagetable_t uvmcreate(void);
void uvminit(pagetable_t, uchar *, uint);
uint64 uvmalloc(pagetable_t, uint64, uint64);
uint64 uvmdealloc(pagetable_t, uint64, uint64);
void uvmcopy(pagetable_t, pagetable_t, uint64);
int uvmcopy(pagetable_t, pagetable_t, uint64);
void uvmfree(pagetable_t, uint64);
void mappages(pagetable_t, uint64, uint64, uint64, int);
int mappages(pagetable_t, uint64, uint64, uint64, int);
void unmappages(pagetable_t, uint64, uint64, int);
uint64 walkaddr(pagetable_t, uint64);
int copyout(pagetable_t, uint64, char *, uint64);

View file

@ -47,7 +47,7 @@ kernelvec:
ld ra, 0(sp)
ld sp, 8(sp)
ld gp, 16(sp)
ld tp, 24(sp)
// not this, in case we moved CPUs: ld tp, 24(sp)
ld t0, 32(sp)
ld t1, 40(sp)
ld t2, 48(sp)

View file

@ -111,6 +111,30 @@ found:
return p;
}
// free a proc structure and the data hanging from it,
// including user pages.
// the proc lock must be held.
static void
freeproc(struct proc *p)
{
if(p->kstack)
kfree(p->kstack);
p->kstack = 0;
if(p->tf)
kfree((void*)p->tf);
p->tf = 0;
if(p->pagetable)
proc_freepagetable(p->pagetable, p->sz);
p->pagetable = 0;
p->sz = 0;
p->pid = 0;
p->parent = 0;
p->name[0] = 0;
p->chan = 0;
p->killed = 0;
p->state = UNUSED;
}
// Create a page table for a given process,
// with no users pages, but with trampoline pages.
// Called both when creating a process, and
@ -147,7 +171,8 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz)
{
unmappages(pagetable, TRAMPOLINE, PGSIZE, 0);
unmappages(pagetable, TRAMPOLINE-PGSIZE, PGSIZE, 0);
uvmfree(pagetable, sz);
if(sz > 0)
uvmfree(pagetable, sz);
}
// a user program that calls exec("/init")
@ -226,7 +251,10 @@ fork(void)
}
// Copy user memory from parent to child.
uvmcopy(p->pagetable, np->pagetable, p->sz);
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
freeproc(np);
return -1;
}
np->sz = p->sz;
np->parent = p;
@ -342,17 +370,7 @@ wait(void)
if(np->state == ZOMBIE){
// Found one.
pid = np->pid;
kfree(np->kstack);
np->kstack = 0;
kfree((void*)np->tf);
np->tf = 0;
proc_freepagetable(np->pagetable, np->sz);
np->pagetable = 0;
np->pid = 0;
np->parent = 0;
np->name[0] = 0;
np->killed = 0;
np->state = UNUSED;
freeproc(np);
release(&np->lock);
release(&p->lock);
return pid;

View file

@ -117,29 +117,29 @@ argstr(int n, char *buf, int max)
return fetchstr(addr, buf, max);
}
extern int sys_chdir(void);
extern int sys_close(void);
extern int sys_dup(void);
extern int sys_exec(void);
extern int sys_exit(void);
extern int sys_fork(void);
extern int sys_fstat(void);
extern int sys_getpid(void);
extern int sys_kill(void);
extern int sys_link(void);
extern int sys_mkdir(void);
extern int sys_mknod(void);
extern int sys_open(void);
extern int sys_pipe(void);
extern int sys_read(void);
extern int sys_sbrk(void);
extern int sys_sleep(void);
extern int sys_unlink(void);
extern int sys_wait(void);
extern int sys_write(void);
extern int sys_uptime(void);
extern uint64 sys_chdir(void);
extern uint64 sys_close(void);
extern uint64 sys_dup(void);
extern uint64 sys_exec(void);
extern uint64 sys_exit(void);
extern uint64 sys_fork(void);
extern uint64 sys_fstat(void);
extern uint64 sys_getpid(void);
extern uint64 sys_kill(void);
extern uint64 sys_link(void);
extern uint64 sys_mkdir(void);
extern uint64 sys_mknod(void);
extern uint64 sys_open(void);
extern uint64 sys_pipe(void);
extern uint64 sys_read(void);
extern uint64 sys_sbrk(void);
extern uint64 sys_sleep(void);
extern uint64 sys_unlink(void);
extern uint64 sys_wait(void);
extern uint64 sys_write(void);
extern uint64 sys_uptime(void);
static int (*syscalls[])(void) = {
static uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
[SYS_wait] sys_wait,

View file

@ -52,7 +52,7 @@ fdalloc(struct file *f)
return -1;
}
int
uint64
sys_dup(void)
{
struct file *f;
@ -66,7 +66,7 @@ sys_dup(void)
return fd;
}
int
uint64
sys_read(void)
{
struct file *f;
@ -78,7 +78,7 @@ sys_read(void)
return fileread(f, p, n);
}
int
uint64
sys_write(void)
{
struct file *f;
@ -91,7 +91,7 @@ sys_write(void)
return filewrite(f, p, n);
}
int
uint64
sys_close(void)
{
int fd;
@ -104,7 +104,7 @@ sys_close(void)
return 0;
}
int
uint64
sys_fstat(void)
{
struct file *f;
@ -116,7 +116,7 @@ sys_fstat(void)
}
// Create the path new as a link to the same inode as old.
int
uint64
sys_link(void)
{
char name[DIRSIZ], new[MAXPATH], old[MAXPATH];
@ -182,7 +182,7 @@ isdirempty(struct inode *dp)
}
//PAGEBREAK!
int
uint64
sys_unlink(void)
{
struct inode *ip, *dp;
@ -284,7 +284,7 @@ create(char *path, short type, short major, short minor)
return ip;
}
int
uint64
sys_open(void)
{
char path[MAXPATH];
@ -347,7 +347,7 @@ sys_open(void)
return fd;
}
int
uint64
sys_mkdir(void)
{
char path[MAXPATH];
@ -363,7 +363,7 @@ sys_mkdir(void)
return 0;
}
int
uint64
sys_mknod(void)
{
struct inode *ip;
@ -383,7 +383,7 @@ sys_mknod(void)
return 0;
}
int
uint64
sys_chdir(void)
{
char path[MAXPATH];
@ -408,7 +408,7 @@ sys_chdir(void)
return 0;
}
int
uint64
sys_exec(void)
{
char path[MAXPATH], *argv[MAXARG];
@ -446,7 +446,7 @@ sys_exec(void)
return ret;
}
int
uint64
sys_pipe(void)
{
uint64 fdarray; // user pointer to array of two integers

View file

@ -7,32 +7,32 @@
#include "spinlock.h"
#include "proc.h"
int
uint64
sys_exit(void)
{
exit();
return 0; // not reached
}
int
uint64
sys_getpid(void)
{
return myproc()->pid;
}
int
uint64
sys_fork(void)
{
return fork();
}
int
uint64
sys_wait(void)
{
return wait();
}
int
uint64
sys_sbrk(void)
{
int addr;
@ -46,7 +46,7 @@ sys_sbrk(void)
return addr;
}
int
uint64
sys_sleep(void)
{
int n;
@ -67,7 +67,7 @@ sys_sleep(void)
return 0;
}
int
uint64
sys_kill(void)
{
int pid;
@ -79,7 +79,7 @@ sys_kill(void)
// return how many clock tick interrupts have occurred
// since start.
int
uint64
sys_uptime(void)
{
uint xticks;

View file

@ -37,7 +37,7 @@ void
usertrap(void)
{
int which_dev = 0;
if((r_sstatus() & SSTATUS_SPP) != 0)
panic("usertrap: not from user mode");
@ -49,8 +49,6 @@ usertrap(void)
// save user program counter.
p->tf->epc = r_sepc();
intr_on();
if(r_scause() == 8){
// system call
@ -59,11 +57,15 @@ usertrap(void)
// but we want to return to the next instruction.
p->tf->epc += 4;
// an interrupt will change sstatus &c registers,
// so don't enable until done with those registers.
intr_on();
syscall();
} else if((which_dev = devintr()) != 0){
// ok
} else {
printf("usertrap(): unexpected scause 0x%p pid=%d\n", r_scause(), p->pid);
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
p->killed = 1;
}
@ -121,12 +123,14 @@ usertrapret(void)
((void (*)(uint64,uint64))TRAMPOLINE)(TRAMPOLINE - PGSIZE, satp);
}
// interrupts and exceptions from kernel code go here,
// interrupts and exceptions from kernel code go here via kernelvec,
// on whatever the current kernel stack is.
// must be 4-byte aligned to fit in stvec.
void
kerneltrap()
{
int which_dev = 0;
uint64 sepc = r_sepc();
uint64 sstatus = r_sstatus();
uint64 scause = r_scause();
@ -135,11 +139,20 @@ kerneltrap()
if(intr_get() != 0)
panic("kerneltrap: interrupts enabled");
if(devintr() == 0){
printf("scause 0x%p\n", scause);
if((which_dev = devintr()) == 0){
printf("scause %p\n", scause);
printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
panic("kerneltrap");
}
// give up the CPU if this is a timer interrupt.
if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
yield();
// the yield() may have caused some traps to occur,
// so restore trap registers for use by kernelvec.S's sepc instruction.
w_sepc(sepc);
w_sstatus(sstatus);
}
// check if it's an external interrupt or software interrupt,

View file

@ -97,8 +97,8 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
}
// Look up a virtual address, return the physical address,
// Can only be used to look up user pages.
// or 0 if not mapped.
// Can only be used to look up user pages.
uint64
walkaddr(pagetable_t pagetable, uint64 va)
{
@ -119,8 +119,9 @@ walkaddr(pagetable_t pagetable, uint64 va)
// Create PTEs for virtual addresses starting at va that refer to
// physical addresses starting at pa. va and size might not
// be page-aligned.
void
// be page-aligned. Returns 0 on success, -1 if walk() couldn't
// allocate a needed page-table page.
int
mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
{
uint64 a, last;
@ -130,7 +131,7 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
last = PGROUNDDOWN(va + size - 1);
for(;;){
if((pte = walk(pagetable, a, 1)) == 0)
panic("mappages: walk");
return -1;
if(*pte & PTE_V)
panic("remap");
*pte = PA2PTE(pa) | perm | PTE_V;
@ -139,6 +140,7 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
a += PGSIZE;
pa += PGSIZE;
}
return 0;
}
// Remove mappings from a page table. The mappings in
@ -222,7 +224,11 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
return 0;
}
memset(mem, 0, PGSIZE);
mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U);
if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
kfree(mem);
uvmdealloc(pagetable, a, oldsz);
return 0;
}
}
return newsz;
}
@ -273,7 +279,9 @@ uvmfree(pagetable_t pagetable, uint64 sz)
// its memory into a child's page table.
// Copies both the page table and the
// physical memory.
void
// returns 0 on success, -1 on failure.
// frees any allocated pages on failure.
int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
{
pte_t *pte;
@ -289,10 +297,18 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
pa = PTE2PA(*pte);
flags = PTE_FLAGS(*pte);
if((mem = kalloc()) == 0)
panic("uvmcopy: kalloc failed");
goto err;
memmove(mem, (char*)pa, PGSIZE);
mappages(new, i, PGSIZE, (uint64)mem, flags);
if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){
kfree(mem);
goto err;
}
}
return 0;
err:
unmappages(new, 0, i, 1);
return -1;
}
// Copy from kernel to user.