From b47005e42e52da061d3279a038e350140b299ee1 Mon Sep 17 00:00:00 2001 From: AceVest Date: Sun, 27 Jul 2014 17:08:24 +0800 Subject: [PATCH] fix bug in syscall.S --- Makefile | 1 + bin/shell.c | 39 ++++++++------ drivers/vga.c | 1 + fs/ext2.c | 28 ++++++++-- fs/write.c | 1 + include/ext2.h | 6 ++- include/mm.h | 2 +- include/page.h | 2 +- include/syscall.h | 2 - include/system.h | 59 ++++++++++++++------ kernel/exec.c | 135 ++++++++++++++++++++++------------------------ kernel/fork.c | 29 ++++++++-- kernel/innerint.c | 6 ++- kernel/setup.c | 1 + kernel/syscall.S | 6 ++- kernel/syscall.c | 13 +++-- lib/syscall.c | 19 ++----- lib/write.c | 2 +- mm/buddy.c | 11 ++-- mm/mm.c | 5 +- mm/page.c | 6 ++- 21 files changed, 223 insertions(+), 151 deletions(-) diff --git a/Makefile b/Makefile index 0cfd1a5..45a147e 100644 --- a/Makefile +++ b/Makefile @@ -40,4 +40,5 @@ install: cp bin/hello /kernel/bin/ cp bin/shell /kernel/bin/ cp: + cd bin && make ./scripts/copy.sh diff --git a/bin/shell.c b/bin/shell.c index bca1539..65eeaac 100644 --- a/bin/shell.c +++ b/bin/shell.c @@ -16,25 +16,32 @@ int systest(); int main() { + char x[10]; + x[0] = 'a'; + x[1] = 'b'; + x[2] = 'c'; + x[3] = '\n'; +#if 1 + //while(1) write(0, x, 4); + //while(1) systest(); + int pid = fork(); - - while(1) + if(pid > 0) { - char buf[256]; - read(0, buf, 256); - write(0, buf, 256); -#if 0 - asm("movl $11, %eax;" \ - "pushl $1f;" \ - "pushl %ecx;" \ - "pushl %edx;" \ - "pushl %ebp;" \ - "movl %esp,%ebp;" \ - "sysenter;" \ - "1:"); + //write(0, "parent\n", 7); + //write(0, x, 4); + while(1) + ; systest(); + } + else if(pid == 0) #endif - systest(); - asm("nop;nop;nop;"); + { + //write(0, "child\n", 6); + //write(0, x, 4); + while(1) + { + systest(); + } } return 0; diff --git a/drivers/vga.c b/drivers/vga.c index c6fc7b6..a7724e7 100644 --- a/drivers/vga.c +++ b/drivers/vga.c @@ -174,6 +174,7 @@ void vga_putc(unsigned int nr, unsigned char c, const unsigned char color) void vga_puts(unsigned int nr, const char *buf, unsigned char color) { + assert(buf != 0); if(nr >= VGA_MAX_SCREEN_CNT) return ; diff --git a/fs/ext2.c b/fs/ext2.c index cd8731e..f29e731 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -28,6 +28,11 @@ ext2_inode_t ext2_root_inode; static ext2_inode_t boot_inode; static ext2_inode_t krnl_inode; +unsigned long ext2_block_size() +{ + return (EXT2_MIN_BLOCK_SIZE << (EXT2_SB)->s_log_block_size); +} + void *ext2_alloc_block() { return (void *) kmem_cache_alloc(ext2_block_cache, 0); @@ -86,13 +91,13 @@ void ext2_read_file(const ext2_inode_t *inode, char *buf) for(i=0; ii_block[i], 1, buf+i*EXT2_BLOCK_SIZE); - printk("read block\n"); + printd("read block\n"); } unsigned int left = inode->i_size % EXT2_BLOCK_SIZE; if(left) { - printk("read left %u bytes\n", left); + printd("read left %u bytes\n", left); void *blk = ext2_alloc_block(); @@ -100,9 +105,26 @@ void ext2_read_file(const ext2_inode_t *inode, char *buf) ext2_free_block(blk); } - printk("read file done\n"); + printd("read file done\n"); +} + +void ext2_read_data(const ext2_inode_t *inode, unsigned int offset, size_t size, char *buf) +{ + assert(inode != 0); + assert(buf != 0); + assert(inode->i_size > 0 && inode->i_size<=MAX_SUPT_FILE_SIZE); + assert(offset+size <= inode->i_size); + assert(offset % EXT2_BLOCK_SIZE == 0); // for easy + printk("offset %x size %x %x\n", offset, size, offset+size); + assert((offset+size) % EXT2_BLOCK_SIZE == 0); + + unsigned int blkid = offset / EXT2_BLOCK_SIZE; + unsigned int blkcnt = size / EXT2_BLOCK_SIZE; + printk("id %u cnt %u\n", blkid, blkcnt); + BLKRW(inode->i_block[blkid], blkcnt, buf); } + unsigned int ext2_search_indir(const char *name, const ext2_inode_t *inode) { unsigned int ino = 0; diff --git a/fs/write.c b/fs/write.c index efb85e7..b80d133 100644 --- a/fs/write.c +++ b/fs/write.c @@ -14,6 +14,7 @@ *-------------------------------------------------------------------------- */ +#include extern void vga_puts(unsigned int nr, const char *buf, unsigned char color); int sysc_write(int fd, const char *buf, unsigned long size) diff --git a/include/ext2.h b/include/ext2.h index fa487fb..bc20046 100644 --- a/include/ext2.h +++ b/include/ext2.h @@ -34,7 +34,10 @@ #define EXT2_SB (&ext2_fs.ext2_sb) #define EXT2_GD (ext2_fs.ext2_gd) -#define EXT2_BLOCK_SIZE (EXT2_MIN_BLOCK_SIZE << (EXT2_SB)->s_log_block_size) + +unsigned long ext2_block_size(); +#define EXT2_BLOCK_SIZE ext2_block_size() +//#define EXT2_BLOCK_SIZE (EXT2_MIN_BLOCK_SIZE << (EXT2_SB)->s_log_block_size) #define EXT2_SECT_PER_BLOCK (EXT2_BLOCK_SIZE/512) @@ -209,5 +212,6 @@ enum void ext2_read_inode(unsigned int ino, ext2_inode_t *inode); void ext2_read_file(const ext2_inode_t *inode, char *buf); +void ext2_read_data(const ext2_inode_t *inode, unsigned int offset, size_t size, char *buf); #endif //_EXT2_H diff --git a/include/mm.h b/include/mm.h index ec39222..07620fb 100644 --- a/include/mm.h +++ b/include/mm.h @@ -15,7 +15,7 @@ #define BOOTMEM_PAGE_USED 1 void *alloc_bootmem(unsigned long size, unsigned long align); -unsigned long bootmem_total_pages(); +unsigned long bootmem_max_pfn(); unsigned long bootmem_page_state(unsigned long pfn); #define bootmem_alloc_pages(n) alloc_bootmem((n)*PAGE_SIZE, PAGE_SIZE) diff --git a/include/page.h b/include/page.h index ee926d4..8624991 100644 --- a/include/page.h +++ b/include/page.h @@ -44,7 +44,7 @@ typedef unsigned long pte_t; #define PTECNT_PER_PAGE (PAGE_SIZE/sizeof(pte_t)) #define PAGE_ITEMS (PAGE_SIZE/sizeof(unsigned long)) -#define PAGE_ALIGN(page) (page & PAGE_MASK) +#define PAGE_ALIGN(page) (((unsigned long)(page)) & PAGE_MASK) #define PAGE_UP(page) (((unsigned long)page + PAGE_SIZE -1) & PAGE_MASK) #define PAGE_DOWN PAGE_ALIGN diff --git a/include/syscall.h b/include/syscall.h index 3ea6fcf..7530188 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -29,14 +29,12 @@ int _syscall1(int nr, unsigned long a); int _syscall2(int nr, unsigned long a, unsigned long b); int _syscall3(int nr, unsigned long a, unsigned long b, unsigned long c); int _syscall4(int nr, unsigned long a, unsigned long b, unsigned long c, unsigned long d); -int _syscall5(int nr, unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long e); #define syscall0(nr) _syscall0(nr) #define syscall1(nr, a) _syscall1(nr, (unsigned long)a) #define syscall2(nr, a, b) _syscall2(nr, (unsigned long)a, (unsigned long)b) #define syscall3(nr, a, b, c) _syscall3(nr, (unsigned long)a, (unsigned long)b, (unsigned long)c) #define syscall4(nr, a, b, c, d) _syscall4(nr, (unsigned long)a, (unsigned long)b, (unsigned long)c, (unsigned long)d) -#define syscall5(nr, a, b, c, d, e) _syscall5(nr, (unsigned long)a, (unsigned long)b, (unsigned long)c, (unsigned long)d, (unsigned long)e) enum { diff --git a/include/system.h b/include/system.h index 7adc73e..ac2b5ff 100644 --- a/include/system.h +++ b/include/system.h @@ -21,12 +21,12 @@ #include #define KRNLADDR PAGE_OFFSET -#define PT_REGS_EDI 0 -#define PT_REGS_ESI 4 -#define PT_REGS_EBP 8 -#define PT_REGS_EBX 12 -#define PT_REGS_EDX 16 -#define PT_REGS_ECX 20 +#define PT_REGS_EBX 0 +#define PT_REGS_ECX 4 +#define PT_REGS_EDX 8 +#define PT_REGS_ESI 12 +#define PT_REGS_EDI 16 +#define PT_REGS_EBP 20 #define PT_REGS_EAX 24 #define PT_REGS_DS 28 #define PT_REGS_ES 32 @@ -131,6 +131,7 @@ enum GDTSelectorIndex INDEX_EMP8, INDEX_TSS, }; +#if 0 // pushal push eax, ecx, edx, ebx, esp, ebp, esi, edi typedef struct pt_regs { @@ -156,16 +157,42 @@ typedef struct pt_regs u32 esp; u16 ss, _ss; } __attribute__((packed)) pt_regs_t; +#else +typedef struct pt_regs +{ + u32 ebx; + u32 ecx; + u32 edx; + u32 esi; + u32 edi; + u32 ebp; + u32 eax; + u16 ds, _ds; + u16 es, _es; + u16 fs, _fs; + u16 gs, _gs; + union + { + u32 irq; + u32 errcode; + }; + u32 eip; + u16 cs, _cs; + u32 eflags; + u32 esp; + u16 ss, _ss; +} __attribute__((packed)) pt_regs_t; +#endif typedef unsigned long dev_t; typedef struct system { u32 mmap_addr; - u32 mmap_size; // Byte + u32 mmap_size; // Byte - u32 mm_lower; // KB - u32 mm_upper; // KB + u32 mm_lower; // KB + u32 mm_upper; // KB u64 mm_size; // Byte u32 page_count; @@ -206,20 +233,20 @@ extern System system; pushl %es; \ pushl %ds; \ pushl %eax; \ - pushl %ecx; \ - pushl %edx; \ - pushl %ebx; \ pushl %ebp; \ pushl %esi; \ - pushl %edi; + pushl %edi; \ + pushl %edx; \ + pushl %ecx; \ + pushl %ebx; #define RESTORE_REGS \ + popl %ebx; \ + popl %ecx; \ + popl %edx; \ popl %edi; \ popl %esi; \ popl %ebp; \ - popl %ebx; \ - popl %edx; \ - popl %ecx; \ popl %eax; \ popl %ds; \ popl %es; \ diff --git a/kernel/exec.c b/kernel/exec.c index 3c69cb5..393e29e 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -20,9 +20,33 @@ #include #include #include +#include extern void *syscall_exit; +void put_paging(unsigned long vaddr, unsigned long paddr, unsigned long flags) +{ + assert(PAGE_ALIGN(vaddr) == vaddr); + assert(PAGE_ALIGN(paddr) == paddr); + + unsigned int npde = get_npd(vaddr); + unsigned int npte = get_npt(vaddr); + + pde_t *page_dir = (pde_t *) current->cr3; + pte_t *page_table = (pte_t *) PAGE_ALIGN(page_dir[npde]); + + if(page_table == 0) + { + page_table = (pte_t *) va2pa(alloc_one_page(0)); + assert(page_table != 0); + } + + + page_dir[npde] = (unsigned long) page_table | flags; + page_table = pa2va(page_table); + page_table[npte] = paddr | flags; +} + int sysc_exec(const char *path, char *const argv[]) { assert(argv == NULL); // unsupport now @@ -35,93 +59,58 @@ int sysc_exec(const char *path, char *const argv[]) ext2_read_inode(ino, &inode); - //void *buf = (void*)kmalloc(inode.i_size, 0); - void *buf = (void *) alloc_pages(0, 5); - assert(buf != 0); + Elf32_Ehdr *ehdr= (Elf32_Ehdr *)alloc_one_page(0); + assert(ehdr != 0); + ext2_read_data(&inode, 0, PAGE_SIZE, (char *)ehdr); + printk("%08x\n", *((unsigned long *)ehdr->e_ident)); + assert(strncmp(ELFMAG, ehdr->e_ident, sizeof(ELFMAG)-1) == 0); + printk("Elf Entry: %08x\n", ehdr->e_entry); - printk("exec buf %08x \n", buf); - printd("begin read elf\n"); - ext2_read_file(&inode, buf); - printd("end read elf\n"); - pElf32_Ehdr ehdr = (pElf32_Ehdr) buf; - //assert(strncmp(ELFMAG, ehdr->e_ident, sizeof(ELFMAG)-1) == 0); - if(strncmp(ELFMAG, ehdr->e_ident, sizeof(ELFMAG)-1) != 0) + int i, j; + for(i=0; ie_phnum; ++i) { - printk("file %s can not execute\n", path); - kfree(buf); - return -ENOEXEC; - } - //printk("Entry: %08x phnum:%d\n", ehdr->e_entry, ehdr->e_phnum); - - int size = 0; - int i; - for(i=0; ie_phnum; i++) - { - pElf32_Phdr phdr; - phdr = (pElf32_Phdr)(buf+ehdr->e_phoff+(i*ehdr->e_phentsize)); + Elf32_Phdr *phdr; + phdr = (Elf32_Phdr*)(((unsigned long)ehdr) + ehdr->e_phoff + (i*ehdr->e_phentsize)); printk("Type %08x Off %08x Va %08x Pa %08x Fsz %08x Mmsz %08x\n", - phdr->p_type, phdr->p_offset, phdr->p_vaddr, phdr->p_paddr, - phdr->p_filesz, phdr->p_memsz); + phdr->p_type, phdr->p_offset, phdr->p_vaddr, phdr->p_paddr, + phdr->p_filesz, phdr->p_memsz); - if(phdr->p_type == PT_LOAD) - { - if(phdr->p_offset > 0 && phdr->p_memsz > 0) - { - size = ALIGN(phdr->p_offset + phdr->p_memsz, 0x1000); - } - } - } - printk("ELF MEM SIZE %u\n", size); + unsigned long vaddr = phdr->p_vaddr; + unsigned long offset= phdr->p_offset; + unsigned long mmsz = phdr->p_memsz; + unsigned long filesz= phdr->p_filesz; - char *exe = (char *) kmalloc(size, 0); - assert(exe != 0); - printk("EXE ADDR %08x\n", exe); - for(i=0; ie_phnum; i++) - { - pElf32_Phdr phdr; - phdr = (pElf32_Phdr)(buf+ehdr->e_phoff+(i*ehdr->e_phentsize)); if(phdr->p_type != PT_LOAD) continue; - if(phdr->p_filesz != 0) + + assert(mmsz >= filesz); + + unsigned int pgcnt = (mmsz + PAGE_SIZE - 1) / PAGE_SIZE; + unsigned int blkcnt= (filesz + EXT2_BLOCK_SIZE - 1) / EXT2_BLOCK_SIZE; + + void *buf = kmalloc(pgcnt*PAGE_SIZE, PAGE_SIZE); + assert(PAGE_ALIGN(buf) == (unsigned long)buf); + assert(buf != 0); + + + printk("vvvbufsz %08x datasz %08x\n", pgcnt*PAGE_SIZE, blkcnt*EXT2_BLOCK_SIZE); + + if(filesz > 0) + ext2_read_data(&inode, offset, blkcnt*EXT2_BLOCK_SIZE, buf); + + for(j=0; jp_offset), (void*)(buf+phdr->p_offset), phdr->p_filesz); + put_paging(vaddr + j*PAGE_SIZE, (unsigned long) (va2pa(buf)) + j*PAGE_SIZE, 7); } } - - /* - * 因为目前文件支持最大为12*EXT2_BLOCK_SIZE - * 即12K~48K之间 - * 所以就以一个页目录项来简化处理 - */ - u32 *pd = (u32*) current->cr3; - 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"); - - //printk("npd: %d pt:%08x\n", npd, pt); - memset(pa2va(pt), 0, PAGE_SIZE); - pd[npd] = (u32) pt | 7; - pt = pa2va(pt); - for(i=npt, c=0; i<1024; i++, c++) - { - 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); + + disable_irq(); pt_regs_t *regs = ((pt_regs_t *)(TASK_SIZE+(unsigned long)current)) - 1; memset((void*)regs, 0, sizeof(pt_regs_t)); @@ -137,7 +126,9 @@ int sysc_exec(const char *path, char *const argv[]) regs->edx = regs->eip; regs->ecx = (0xC0000000 - 16); - kfree(buf); + //kfree(buf); + + free_pages((unsigned long)ehdr); asm("movl $0, %%eax; movl %%ebx,%%ebp; movl %%ebp,%%esp;jmp syscall_exit;"::"b"((unsigned long)(regs))); diff --git a/kernel/fork.c b/kernel/fork.c index 257eb6e..0d5f08f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -11,6 +11,7 @@ */ #include +#include int sysc_fork(pt_regs_t regs) { @@ -23,6 +24,7 @@ extern pid_t get_next_pid(); int do_fork(pt_regs_t *regs, unsigned long flags) { + static int forkcnt = 7; task_union *tsk; tsk = alloc_task_union(); printk("fork task %08x flags %08x\n", tsk, flags); @@ -31,7 +33,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) memcpy(tsk, current, sizeof(task_union)); - { + //{ tsk->cr3 = (unsigned long) alloc_one_page(0); if(tsk->cr3 == 0) panic("failed init tsk cr3"); @@ -55,22 +57,38 @@ int do_fork(pt_regs_t *regs, unsigned long flags) continue; } - if(spde != 0) - dpde = PAGE_FLAGS(spde) | (unsigned long) va2pa(alloc_one_page(0)); + if(pde_src[i] == 0) + continue; + + if(PAGE_ALIGN(spde) != 0) + { + dpde = alloc_one_page(0); + assert(dpde != 0); + memset((void*)dpde, 0, PAGE_SIZE); + dpde = PAGE_FLAGS(spde) | (unsigned long) va2pa(dpde); + } + else + { + pde_dst[i] = 0; + continue; + } pde_dst[i] = dpde; pte_t *pte_src = pa2va(PAGE_ALIGN(spde)); pte_t *pte_dst = pa2va(PAGE_ALIGN(dpde)); for(j=0; j< PAGE_PTE_CNT; ++j) { + + //printl(20, "[%d %d]", i, j); pte_src[j] &= ~PAGE_WR; pte_dst[j] = pte_src[j]; page_t *page = pa2page(pte_src[j]); page->count ++; } + } - } + //} tsk->pid = get_next_pid(); tsk->ppid = current->pid; @@ -82,7 +100,6 @@ int do_fork(pt_regs_t *regs, unsigned long flags) child_regs->eax = 0; child_regs->eflags |= 0x200; //enable IF - tsk->esp0 = TASK_SIZE + (unsigned long) tsk; tsk->esp = (unsigned long) child_regs; tsk->eip = (unsigned long) ret_from_fork_user; @@ -104,5 +121,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) list_add(&tsk->list, &root_task.list); irq_restore(iflags); + + printk("%s:%d\n", __func__, __LINE__); return (int)tsk->pid; } diff --git a/kernel/innerint.c b/kernel/innerint.c index 6705301..da05f74 100644 --- a/kernel/innerint.c +++ b/kernel/innerint.c @@ -96,9 +96,11 @@ void doPageFault(pt_regs_t regs) //printd("do page fault errcode %x addr %08x\n", errcode, addr); - if(errcode & PAGE_US) + if(errcode == 0 || errcode == 2) { - //panic("user program try to access a page and cause a protection fault. addr %08x", addr); + unsigned long *pde_src = (unsigned long *) current->cr3; + printk("p=%x\n", pde_src[796]); + //panic("errcode %08x addr %08x", errcode, addr); } if((errcode & PAGE_P) == 0) diff --git a/kernel/setup.c b/kernel/setup.c index 90d81db..f3e623f 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -94,5 +94,6 @@ void setup_kernel() setup_fs(); printk("%s\n", version); + //vga_dbg_toggle(); } diff --git a/kernel/syscall.S b/kernel/syscall.S index c9fb5d6..7a44a44 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -54,9 +54,11 @@ syscall_entry: call *sysc_handler_table(,%eax,4) +normal_syscall_exit: leal sysexit, %edx movl %edx, PT_REGS_EDX(%esp) - movl %ebp, PT_REGS_ECX(%esp) + movl PT_REGS_EBP(%esp), %edx + movl %edx, PT_REGS_ECX(%esp) syscall_exit: movl %eax, PT_REGS_EAX(%esp) @@ -72,7 +74,7 @@ bad_sysc_nr: ret_from_fork_user: xorl %eax, %eax - jmp syscall_exit + jmp normal_syscall_exit ret_from_fork_krnl: movl PT_REGS_EDX(%esp), %edx diff --git a/kernel/syscall.c b/kernel/syscall.c index 91084b4..3c7292d 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -52,6 +52,9 @@ int sysc_test() { static unsigned int cnt=0; printl(MPL_TEST, "sysc_test %u", cnt++); + + //unsigned long *pde = (unsigned long *)current->cr3; + //printk("sysctest %08x\n", pde[797]); } void init_sysc_handler_table() @@ -60,11 +63,11 @@ void init_sysc_handler_table() for(i=0; icr3; pte_t *pte; unsigned long page = alloc_one_page(0); @@ -52,6 +53,7 @@ void do_no_page(void *addr) void do_wp_page(void *addr) { + //printk("%s addr %08x\n", __func__, (unsigned long)addr); int npde = get_npd(addr); int npte = get_npt(addr); @@ -84,6 +86,8 @@ void do_wp_page(void *addr) dst = va2pa(dst); pt[npte] = dst | flags; + pt[npte] |= PAGE_WR; + pd[npde] |= PAGE_WR; dst = (unsigned long)pa2va(PAGE_ALIGN(dst)); @@ -91,7 +95,7 @@ void do_wp_page(void *addr) } else { - //pd[npde] |= PAGE_WR; + pd[npde] |= PAGE_WR; pt[npte] |= PAGE_WR; //pd[npde] |= PAGE_US; //pt[npte] |= PAGE_US; -- 2.44.0