Skip to content

Commit

Permalink
完成PA4阶段2
Browse files Browse the repository at this point in the history
  • Loading branch information
cs-qyzhang committed Dec 11, 2019
1 parent 76162b9 commit 9b0db57
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 15 deletions.
2 changes: 2 additions & 0 deletions nanos-lite/include/proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ typedef union {

extern PCB *current;
extern void naive_uload(PCB *pcb, const char *filename);
extern void context_uload(PCB *pcb, const char *filename);
extern void run_proc(PCB *pcb);

#endif
81 changes: 80 additions & 1 deletion nanos-lite/src/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
# define Elf_Phdr Elf32_Phdr
#endif

#define min(x, y) ((x) < (y) ? (x) : (y))
#define PTE_ADDR(pte) ((uint32_t)(pte) & ~0xfff)
#define OFF(va) ((uint32_t)(va) & 0xfff)

static uintptr_t loader(PCB *pcb, const char *filename) {
// XXX();
int fd = fs_open(filename, 0, 0);
Expand All @@ -28,8 +32,49 @@ static uintptr_t loader(PCB *pcb, const char *filename) {
fs_read(fd, (void *)&phdr, elf_header.e_phentsize);
if (phdr.p_type == PT_LOAD) {
fs_lseek(fd, phdr.p_offset, SEEK_SET);

#ifdef HAS_VME
// 为用户进程申请虚存空间
void *vaddr = (void *)phdr.p_vaddr;
void *paddr;
int32_t left_file_size = phdr.p_filesz;

// 这里注意在映射后由于没有修改CR3寄存器,所以现在的映射还没有启用,在
// fs_read和memset时要对物理地址进行修改而不是虚拟地址

// 处理第一页 (第一页可能不是页对齐)
paddr = new_page(1);
_map(&pcb->as, vaddr, paddr, 0);
uint32_t page_write_size = min(left_file_size, PTE_ADDR((uint32_t)vaddr + PGSIZE) - (uint32_t)vaddr);
fs_read(fd, (void *)(PTE_ADDR(paddr) | OFF(vaddr)), page_write_size);
left_file_size -= page_write_size;
vaddr += page_write_size;
for (; left_file_size > 0; left_file_size -= page_write_size, vaddr += page_write_size) {
assert(((uint32_t)vaddr & 0xfff) == 0);
paddr = new_page(1);
_map(&pcb->as, vaddr, paddr, 0);
page_write_size = min(left_file_size, PGSIZE);
fs_read(fd, paddr, page_write_size);
}

// 将进程剩下的地址空间赋值为0
left_file_size = phdr.p_memsz - phdr.p_filesz;
if (((uint32_t)vaddr & 0xfff) != 0) {
page_write_size = min(left_file_size, PTE_ADDR((uint32_t)vaddr + PGSIZE) - (uint32_t)vaddr);
memset((void *)(PTE_ADDR(paddr) | OFF(vaddr)), 0, page_write_size);
left_file_size -= page_write_size;
vaddr += page_write_size;
}
for (page_write_size = PGSIZE; left_file_size > 0; left_file_size -= page_write_size, vaddr += page_write_size) {
assert(((uint32_t)vaddr & 0xfff) == 0);
paddr = new_page(1);
_map(&pcb->as, vaddr, paddr, 0);
memset(paddr, 0, page_write_size);
}
#else
fs_read(fd, (void *)phdr.p_vaddr, phdr.p_filesz);
memset((void *)(phdr.p_vaddr + phdr.p_filesz), 0, phdr.p_memsz - phdr.p_filesz);
#endif
}
}

Expand All @@ -39,8 +84,37 @@ static uintptr_t loader(PCB *pcb, const char *filename) {
return elf_header.e_entry;
}

static uintptr_t kloader(PCB *pcb, const char *filename) {
// XXX();
int fd = fs_open(filename, 0, 0);
if (fd == -1) {
panic("loader: can't open file %s!", filename);
}

Elf_Ehdr elf_header;
fs_read(fd, (void *)&elf_header, sizeof(Elf_Ehdr));
if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG))
panic("file %s ELF format error!", filename);

for (size_t i = 0; i < elf_header.e_phnum; ++i) {
Elf_Phdr phdr;
fs_lseek(fd, elf_header.e_phoff + elf_header.e_phentsize * i, SEEK_SET);
fs_read(fd, (void *)&phdr, elf_header.e_phentsize);
if (phdr.p_type == PT_LOAD) {
fs_lseek(fd, phdr.p_offset, SEEK_SET);
fs_read(fd, (void *)phdr.p_vaddr, phdr.p_filesz);
memset((void *)(phdr.p_vaddr + phdr.p_filesz), 0, phdr.p_memsz - phdr.p_filesz);
}
}

fs_close(fd);
printf("load file: %s, entry: %x\n", filename, elf_header.e_entry);

return elf_header.e_entry;
}

void naive_uload(PCB *pcb, const char *filename) {
uintptr_t entry = loader(pcb, filename);
uintptr_t entry = kloader(pcb, filename);
Log("Jump to entry = %x", entry);
((void(*)())entry) ();
}
Expand All @@ -54,6 +128,11 @@ void context_kload(PCB *pcb, void *entry) {
}

void context_uload(PCB *pcb, const char *filename) {
memset(pcb, 0, sizeof(PCB)); // 用于在调用execve时将原有进程保存的max_brk等信息清空
#ifdef HAS_VME
_protect(&pcb->as); // 建立用户进程虚存空间中的内核映射
#endif

uintptr_t entry = loader(pcb, filename);

_Area stack;
Expand Down
17 changes: 15 additions & 2 deletions nanos-lite/src/mm.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "memory.h"
#include "proc.h"

static void *pf = NULL;

Expand All @@ -14,13 +15,25 @@ void free_page(void *p) {
}

/* The brk() system call handler. */
int mm_brk(uintptr_t brk, intptr_t increment) {
int mm_brk(uintptr_t new_brk) {
printf("mm_brk: %x, max_brk: %x\n", (uint32_t)new_brk, (uint32_t)current->max_brk);
// 首次调用记录max_brk
if (current->max_brk == 0) {
current->max_brk = (new_brk & 0xfff) ? ((new_brk & ~0xfff) + PGSIZE) : new_brk;
return 0;
}

for (; current->max_brk < new_brk; current->max_brk += PGSIZE) {
_map(&current->as, (void *)current->max_brk, new_page(1), 0);
}

return 0;
}

void init_mm() {
pf = (void *)PGROUNDUP((uintptr_t)_heap.start);
Log("free physical pages starting from %p", pf);
Log("free physical pages starting from %x", (uint32_t)pf);
Log("_heap.start: %x, _heap.end: %x", (uint32_t)_heap.start, (uint32_t)_heap.end);

_vme_init(new_page, free_page);
}
19 changes: 14 additions & 5 deletions nanos-lite/src/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,38 @@ void hello_fun(void *arg) {
}
}

void run_proc(PCB *pcb) {
extern void _urun(_AddressSpace *as, void (*entry)());
_urun(&pcb->as, (void (*)())pcb->cp->eip);
}

void init_proc() {
extern void context_kload(PCB *pcb, void *entry);
extern void context_uload(PCB *pcb, const char *filename);

//context_kload(&pcb[0], (void *)hello_fun);
//context_uload(&pcb[1], "/bin/init");

switch_boot_pcb();
//switch_boot_pcb();
current = &pcb[0];

Log("Initializing processes...");

// load program here
naive_uload(NULL, "/bin/init");

//naive_uload(NULL, "/bin/dummy");
context_uload(&pcb[0], "/bin/init");
context_uload(&pcb[1], "/bin/hello");
run_proc(&pcb[0]);
}

_Context* schedule(_Context *prev) {
//static int is_boot = 0;
//const int boot_pcb_nice = 2000;

printf("schedule!\n");
current->cp = prev;
//current = &pcb[0];
//current = (is_boot++ % boot_pcb_nice) ? &pcb_boot : &pcb[0];
//current = (current == &pcb[0] ? &pcb[1] : &pcb[0]);
current = (current == &pcb[0] ? &pcb[1] : &pcb[0]);

return current->cp;
}
15 changes: 13 additions & 2 deletions nanos-lite/src/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,25 @@ static inline int32_t sys_close(int fd) {
}

static inline int32_t sys_execve(const char *pathname, char *const argv[], char *const envp[]) {
naive_uload(NULL, pathname);
context_uload(current, pathname);
run_proc(current);
return 0;
}

static inline int32_t sys_exit(int32_t status) {
//_halt(0);
return sys_execve("/bin/init", NULL, NULL);
}

static inline int32_t sys_brk(uint32_t brk) {
#ifdef HAS_VME
extern int mm_brk(uintptr_t new_brk);
return mm_brk(brk);
#else
return 0;
#endif
}

_Context* do_syscall(_Context *c) {
uintptr_t a[4];
a[0] = c->GPR1;
Expand Down Expand Up @@ -69,7 +80,7 @@ _Context* do_syscall(_Context *c) {
c->GPRx = sys_lseek(a[1], a[2], a[3]);
break;
case SYS_brk: // 总是成功
c->GPRx = 0;
c->GPRx = sys_brk(a[1]);
break;
case SYS_fstat:
panic("Unhandled syscall ID = %d", a[0]);
Expand Down
4 changes: 3 additions & 1 deletion navy-apps/libs/libos/src/nanos.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ int _write(int fd, void *buf, size_t count) {
void *_sbrk(intptr_t increment) {
extern uint32_t _end;
static uint32_t program_break = 0;
if (program_break == 0)
if (program_break == 0) {
program_break = &_end;
_syscall_(SYS_brk, program_break, 0, 0); // 第一次调用
}
if (_syscall_(SYS_brk, program_break + increment, 0, 0) == 0) {
uint32_t old_break = program_break;
program_break += increment;
Expand Down
7 changes: 7 additions & 0 deletions nexus-am/am/src/x86/nemu/cte.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ void __am_vectrap();
void __am_vecnull();

_Context* __am_irq_handle(_Context *c) {
extern void __am_get_cur_as(_Context *c);
__am_get_cur_as(c);

_Context *next = c;
if (user_handler) {
_Event ev = {0};
Expand All @@ -25,6 +28,10 @@ _Context* __am_irq_handle(_Context *c) {
}
}

// 改变CR3
extern void __am_switch(_Context *c);
__am_switch(next);

return next;
}

Expand Down
15 changes: 11 additions & 4 deletions nexus-am/am/src/x86/nemu/vme.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ int _vme_init(void* (*pgalloc_f)(size_t), void (*pgfree_f)(void*)) {

set_cr3(kpdirs);
set_cr0(get_cr0() | CR0_PG);
printf("enable vme!\n");
vme_enable = 1;

return 0;
Expand All @@ -58,6 +57,7 @@ int _vme_init(void* (*pgalloc_f)(size_t), void (*pgfree_f)(void*)) {
int _protect(_AddressSpace *as) {
PDE *updir = (PDE*)(pgalloc_usr(1));
as->ptr = updir;
memset(as->ptr, 0, PGSIZE);
// map kernel space
for (int i = 0; i < NR_PDE; i ++) {
updir[i] = kpdirs[i];
Expand All @@ -83,7 +83,7 @@ void __am_switch(_Context *c) {

// 将va虚拟地址映射到pa物理地址,将该映射关系写入页表中
int _map(_AddressSpace *as, void *va, void *pa, int prot) {
PTE *pdir = as->ptr;
PTE *pdir = (as == NULL) ? (void *)get_cr3() : (void *)as->ptr;
PDE *pptab = &pdir[PDX(va)];

if (!(*pptab & PTE_P)) { // 如果页表不存在则分配一个页目录
Expand All @@ -94,7 +94,7 @@ int _map(_AddressSpace *as, void *va, void *pa, int prot) {

PDE *ptab = &(((PDE *)PTE_ADDR(*pptab))[PTX(va)]);
if (*ptab & PTE_P) { // 如果页已经存在则报错
printf("ERROR:vme _map(): page map already exists!");
printf("ERROR:vme _map(): page map already exists! %x\n", *ptab);
assert(0);
}
*ptab = PTE_ADDR(pa) | PTE_P;
Expand All @@ -108,7 +108,14 @@ _Context *_ucontext(_AddressSpace *as, _Area ustack, _Area kstack, void *entry,
context->cs = 8;
context->eip = (uint32_t)entry;
memset(&context->eflags, 0x02, sizeof(context->eflags));
context->as = NULL;
context->as = as;

return context;
}

void _urun(_AddressSpace *as, void (*entry)()) {
printf("_urun Jump to entry = 0x%x, ptr: %x\n", (uint32_t)entry, (uint32_t)as->ptr);
set_cr3(as->ptr);
cur_as = as;
entry();
}

0 comments on commit 9b0db57

Please sign in to comment.