From 18b78a31edf7e71937b0a3efb6aab8025966b7b4 Mon Sep 17 00:00:00 2001 From: AceVest Date: Sat, 19 Jul 2014 00:28:28 +0800 Subject: [PATCH] support to execute user program on hard disk --- bin/shell.c | 11 +++++++++++ include/system.h | 12 +++++++----- include/task.h | 1 + kernel/exec.c | 43 +++++++++++++++---------------------------- kernel/fork.c | 1 - kernel/init.c | 4 ++++ kernel/innerint.c | 2 +- kernel/sched.c | 5 +++++ kernel/syscall.S | 10 +++++----- lib/libc.S | 19 +++++++++++++++++-- lib/syscall.c | 1 + scripts/copy.sh | 1 + 12 files changed, 68 insertions(+), 42 deletions(-) diff --git a/bin/shell.c b/bin/shell.c index cde33b0..770862e 100644 --- a/bin/shell.c +++ b/bin/shell.c @@ -16,8 +16,19 @@ int systest(); int main() { + while(1) { +#if 0 + asm("movl $11, %eax;" \ + "pushl $1f;" \ + "pushl %ecx;" \ + "pushl %edx;" \ + "pushl %ebp;" \ + "movl %esp,%ebp;" \ + "sysenter;" \ + "1:"); +#endif systest(); asm("nop;nop;nop;"); } diff --git a/include/system.h b/include/system.h index 7cbcdb9..7adc73e 100644 --- a/include/system.h +++ b/include/system.h @@ -83,11 +83,13 @@ static inline void free_phys_pages(void *p) free_virt_pages((void*)va2pa(p)); } -#define panic(msg, ...) do { \ - asm("cli;"); \ - printk("PANIC:\" # msg # \" file:%s function:%s line:%d\n", \ - ##__VA_ARGS__, __FILE__, __FUNCTION__, __LINE__); \ - while(1); \ +#define panic(msg, ...) do { \ + asm("cli;"); \ + printk("PANIC:" \ + msg \ + " file:%s function:%s line:%d\n", \ + ##__VA_ARGS__, __FILE__, __FUNCTION__, __LINE__); \ + while(1); \ } while(0); extern char etext, edata, end; diff --git a/include/task.h b/include/task.h index 13351a9..3503079 100644 --- a/include/task.h +++ b/include/task.h @@ -30,6 +30,7 @@ enum TASK_UNUSED, TASK_RUNNING, TASK_WAIT, + TASK_EXEC, TASK_EXITING }; diff --git a/kernel/exec.c b/kernel/exec.c index a24ddab..3c69cb5 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -21,6 +21,8 @@ #include #include +extern void *syscall_exit; + int sysc_exec(const char *path, char *const argv[]) { assert(argv == NULL); // unsupport now @@ -100,9 +102,10 @@ int sysc_exec(const char *path, char *const argv[]) u32 *pt; u32 pa_exe; u32 npd, npt; - + int c; pa_exe = va2pa(exe); npd = get_npd(ehdr->e_entry); + npt = get_npt(ehdr->e_entry); pt = (u32*)va2pa(alloc_one_page(0)); if(pt == NULL) panic("out of memory"); @@ -111,32 +114,16 @@ int sysc_exec(const char *path, char *const argv[]) memset(pa2va(pt), 0, PAGE_SIZE); pd[npd] = (u32) pt | 7; pt = pa2va(pt); - for(i=0; ie_phnum; i++) + for(i=npt, c=0; i<1024; i++, c++) { - pElf32_Phdr phdr; - phdr = (pElf32_Phdr)(buf+ehdr->e_phoff+(i*ehdr->e_phentsize)); - if(phdr->p_type != PT_LOAD) - continue; - - u32 npt_min, npt_max; - - npt_min = get_npt(phdr->p_vaddr); - npt_max = get_npt(phdr->p_vaddr+phdr->p_memsz); - //printk("npt_min:%d npt_max:%d\n", npt_min, npt_max); - int j; - for(j=npt_min; j<=npt_max; j++) - { - pt[j] = (u32)(pa_exe | 7); // 对于.text不能这样 - //printk("pt[j] :%08x\n", pt[j]); - pa_exe = PAGE_SIZE+pa_exe; - } + pt[i] = va2pa(PAGE_ALIGN((unsigned long)exe)) + c * PAGE_SIZE; + pt[i] |= 7; } + load_cr3(current); printk("exe : %08x cr3:%08x\n", exe, pd); - /* 准备内核栈的数据并从ret_from_fork返回 */ - pt_regs_t * regs = ((pt_regs_t *)(TASK_SIZE+(unsigned long)current)) - 1; - extern void ret_from_fork_user(); + pt_regs_t *regs = ((pt_regs_t *)(TASK_SIZE+(unsigned long)current)) - 1; memset((void*)regs, 0, sizeof(pt_regs_t)); regs->ss = SELECTOR_USER_DS; regs->ds = SELECTOR_USER_DS; @@ -144,15 +131,15 @@ int sysc_exec(const char *path, char *const argv[]) regs->fs = SELECTOR_USER_DS; regs->gs = SELECTOR_USER_DS; regs->esp = (KRNLADDR-4*sizeof(unsigned long)); - regs->eflags = 0x200; - regs->cs = SELECTOR_USER_CS; - regs->eip = (unsigned long)ehdr->e_entry; - current->esp = (unsigned long) regs; - current->eip = (unsigned long)ret_from_fork_user; - *((unsigned long *)regs->esp) = (unsigned long)ehdr->e_entry; + regs->eflags= 0x200; + regs->cs = SELECTOR_USER_CS; + regs->eip = (unsigned long)ehdr->e_entry; + regs->edx = regs->eip; + regs->ecx = (0xC0000000 - 16); kfree(buf); + asm("movl $0, %%eax; movl %%ebx,%%ebp; movl %%ebp,%%esp;jmp syscall_exit;"::"b"((unsigned long)(regs))); return 0; } diff --git a/kernel/fork.c b/kernel/fork.c index c406b80..257eb6e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -33,7 +33,6 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { tsk->cr3 = (unsigned long) alloc_one_page(0); - printl(MPL_TEST+1, "cr3 %08x", tsk->cr3); if(tsk->cr3 == 0) panic("failed init tsk cr3"); diff --git a/kernel/init.c b/kernel/init.c index 991331a..66b6bd5 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -28,7 +28,11 @@ extern void *ring3_stack_top; void user_task_entry() { printk("user_task_entry: %08x %08x\n", ring3_stack_top, &ring3_stack_top); +#if 0 asm("sti;sysexit;"::"d"(&ring3), "c"(&ring3_stack_top)); +#else + sysc_exec("/bin/shell", 0); +#endif } void init_task_entry() diff --git a/kernel/innerint.c b/kernel/innerint.c index 1fce729..6705301 100644 --- a/kernel/innerint.c +++ b/kernel/innerint.c @@ -98,7 +98,7 @@ void doPageFault(pt_regs_t regs) if(errcode & PAGE_US) { - panic("user program try to access a page and cause a protection fault. addr %08x", addr); + //panic("user program try to access a page and cause a protection fault. addr %08x", addr); } if((errcode & PAGE_P) == 0) diff --git a/kernel/sched.c b/kernel/sched.c index 4711476..d8acd73 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -139,13 +139,18 @@ unsigned long schedule() p = list_entry(pos, task_union, list); if(p->state != TASK_RUNNING) + { + if(p->state == TASK_EXEC) + p->state = TASK_RUNNING; continue; + } if(p->weight > max_weight) { max_weight = p->weight; sel = p; } + else if(p->weight == 0) { p->weight = TASK_INIT_WEIGHT; diff --git a/kernel/syscall.S b/kernel/syscall.S index b3abf9f..c9fb5d6 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -27,6 +27,7 @@ .global ret_from_fork_user .global ret_from_fork_krnl .global sysexit +.global syscall_exit syscall_entry: movl (%esp),%esp @@ -53,16 +54,15 @@ syscall_entry: call *sysc_handler_table(,%eax,4) + leal sysexit, %edx + movl %edx, PT_REGS_EDX(%esp) + movl %ebp, PT_REGS_ECX(%esp) + syscall_exit: movl %eax, PT_REGS_EAX(%esp) RESTORE_REGS - # addl $20, %esp # no need now - - leal sysexit, %edx - movl %ebp, %ecx - sti /* sysenter have cleared IF, and sysexit will not set IF. */ sysexit diff --git a/lib/libc.S b/lib/libc.S index 90807ba..f4e14e2 100644 --- a/lib/libc.S +++ b/lib/libc.S @@ -9,6 +9,21 @@ _start: nop nop +/* + movl $11, %eax; + + pushl $1f; + pushl %ecx; + pushl %edx; + pushl %ebp; + movl %esp,%ebp; + sysenter; + 1: + +loop: + jmp loop + */ + pushl $0 # env pushl $0 # argv pushl $1 # argc @@ -25,5 +40,5 @@ _start: nop nop nop -1: - jmp 1b +die: + jmp die diff --git a/lib/syscall.c b/lib/syscall.c index d781aa9..b9dc9e2 100644 --- a/lib/syscall.c +++ b/lib/syscall.c @@ -9,6 +9,7 @@ #define SYSENTER_ASM \ + "movl $11,%%eax;" \ "pushl $1f;" \ "pushl %%ecx;" \ "pushl %%edx;" \ diff --git a/scripts/copy.sh b/scripts/copy.sh index 44f2f07..c10d0b0 100755 --- a/scripts/copy.sh +++ b/scripts/copy.sh @@ -18,6 +18,7 @@ md5sum /mnt/boot/Kernel mkdir -p /mnt/bin/ cp ./bin/shell /mnt/bin/ cp ./bin/hello /mnt/bin/ +md5sum /mnt/bin/* umount /mnt/ -- 2.44.0