diff --git a/include/errno.h b/include/errno.h new file mode 100644 index 0000000000000000000000000000000000000000..45b1818d35f6121ed7e4642b307bd6e737c9bf46 --- /dev/null +++ b/include/errno.h @@ -0,0 +1,51 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +#define ERROR 99 +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 + +#endif diff --git a/include/linux/mm.h b/include/linux/mm.h index d013e5cf2fb8f465ae469731bd3b4a50cdd899a4..ade08d0bf49cf364d8a0740b2e920d268301fae7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1,6 +1,10 @@ #ifndef _MM_H #define _MM_H +#define PAGE_SIZE 4096 + +extern unsigned long get_free_page(); + #define LOW_MEM 0x100000 extern unsigned long HIGH_MEMORY; #define PAGING_MEMORY (15*1024*1024) @@ -8,4 +12,6 @@ extern unsigned long HIGH_MEMORY; #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) #define USED 100 +extern unsigned char mem_map [ PAGING_PAGES ]; + #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index ab8f64e461411d6e9e590a6eb289f8c2a33b24ab..cfc82a5e30b1c33356c47df3d99a8f5162a761f0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3,15 +3,22 @@ #define HZ 100 +#define NR_TASKS 64 + +#define FIRST_TASK task[0] +#define LAST_TASK task[NR_TASKS-1] + #include #include + void trap_init(); void sched_init(); void test_a(); void test_b(); +int create_second_process(); -extern struct task_struct *task[2]; +extern struct task_struct *task[NR_TASKS]; extern struct task_struct *current; struct tss_struct { @@ -82,4 +89,24 @@ struct task_struct { "d" (_TSS(n)),"c" ((long) task[n])); \ } + +#define _get_base(addr) ({\ +unsigned long __base; \ +__asm__("movb %3,%%dh\n\t" \ + "movb %2,%%dl\n\t" \ + "shll $16,%%edx\n\t" \ + "movw %1,%%dx" \ + :"=d" (__base) \ + :"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7))); \ +__base;}) + +#define get_base(ldt) _get_base( ((char *)&(ldt)) ) + +#define get_limit(segment) ({ \ +unsigned long __limit; \ +__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \ +__limit;}) + #endif diff --git a/kernel/Makefile b/kernel/Makefile index 3415f0f164082b2a364351f8815294c279e9581d..b5ac62d35ec61ca76955a28f7310c0647ecd84d5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -2,7 +2,7 @@ GCC := gcc CCFLAG := -I../include -nostdinc -Wall -fomit-frame-pointer -fno-stack-protector -c -m32 LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 INCDIR := ../include -OBJS := head.o main.o sys_call.o asm.o sched.o printk.o vsprintf.o traps.o chr_drv/chr_drv.a ../mm/mm.o +OBJS := head.o main.o sys_call.o asm.o sched.o printk.o vsprintf.o traps.o fork.o chr_drv/chr_drv.a ../mm/mm.o system: $(OBJS) $(LD) $(LDFLAG) -e startup_32 -o $@ $^ @@ -31,6 +31,9 @@ vsprintf.o : vsprintf.c traps.o : traps.c $(GCC) $(CCFLAG) -o $@ $< +fork.o : fork.c + $(GCC) $(CCFLAG) -o $@ $< + chr_drv/chr_drv.a: chr_drv/*.c cd chr_drv; make chr_drv.a; cd .. diff --git a/kernel/asm.S b/kernel/asm.S index c6e39b1e7db9c0ef6a40fb11037e6ed875d43c37..1a82981e8e5a85164571084da28a623719eeb259 100644 --- a/kernel/asm.S +++ b/kernel/asm.S @@ -1,7 +1,7 @@ .code32 .globl divide_error, .globl invalid_TSS, segment_not_present, stack_segment -.globl general_protection +.globl general_protection, page_fault divide_error: pushl $do_divide_error @@ -88,3 +88,7 @@ general_protection: pushl $do_general_protection jmp error_code +page_fault: + pushl $do_page_fault + jmp error_code + diff --git a/kernel/fork.c b/kernel/fork.c new file mode 100644 index 0000000000000000000000000000000000000000..47dc817274f075e59fb82b3a4aa68482042e391b --- /dev/null +++ b/kernel/fork.c @@ -0,0 +1,53 @@ +#include + +#include +#include + +int find_empty_process() { + int i; + for (i = 1; i < NR_TASKS; i++) { + if (!task[i]) + return i; + } + + return -EAGAIN; +} + +int create_second_process1() { + int nr; + struct task_struct *p; + //char* ustack; + + p = (struct task_struct *) get_free_page(); + if (!p) + return -EAGAIN; + + /* + ustack = (char*) get_free_page(); + if (!ustack) + return -EAGAIN; + */ + + //*p = *current; + + p->tss.eip = (long)test_b; + p->tss.ldt = _LDT(nr); + p->tss.ss0 = 0x10; + p->tss.esp0 = PAGE_SIZE + (long)p; + p->tss.ss = 0x10; + p->tss.ds = 0x10; + p->tss.es = 0x10; + p->tss.fs = 0x10; + p->tss.gs = 0x10; + p->tss.cs = 0x08; + p->tss.esp = PAGE_SIZE + (long)p; + p->tss.eflags = 0x602; + + set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); + + task[nr] = p; + + return nr; +} + diff --git a/kernel/main.c b/kernel/main.c index 17da17637707b60f5340fbca3ee9486b4505d86d..4b939072a26f94edc312f800d9121dbad17c6dfc 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -44,6 +44,8 @@ void main(void) sched_init(); tty_init(); + + printk("%x, %x\n\r", task[0], task[1]); move_to_user_mode(); test_a(); diff --git a/kernel/sched.c b/kernel/sched.c index ca42d15afa2c3618e801d7a51aa6b6c2fc5e9b05..d0aed538f5d3f76efd3bf3e55db2c1273777258c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1,3 +1,4 @@ +#include #include #include @@ -20,7 +21,7 @@ static union task_union init_task = {INIT_TASK, }; static union task_union second_task = {INIT_TASK,}; struct task_struct * current = &(init_task.task); -struct task_struct * task[2] = {&(init_task.task), &(second_task.task)}; +struct task_struct * task[NR_TASKS] = {&(init_task.task), &(second_task.task)}; long user_stack[PAGE_SIZE >> 2]; @@ -55,22 +56,23 @@ void do_timer(long cpl) { } void sched_init() { + int i; + struct desc_struct * p; + set_tss_desc(gdt + FIRST_TSS_ENTRY, &(init_task.task.tss)); set_ldt_desc(gdt + FIRST_LDT_ENTRY, &(init_task.task.ldt)); - set_tss_desc(gdt + FIRST_TSS_ENTRY + 2, &(second_task.task.tss)); - set_ldt_desc(gdt + FIRST_LDT_ENTRY + 2, &(second_task.task.ldt)); - - second_task.task.tss.eip = (long)test_b; - second_task.task.tss.ldt = _LDT(1); - second_task.task.tss.ss0 = 0x10; - second_task.task.tss.esp0 = PAGE_SIZE + (long)&second_task; - second_task.task.tss.ss = 0x10; - second_task.task.tss.ds = 0x10; - second_task.task.tss.es = 0x10; - second_task.task.tss.cs = 0x08; - second_task.task.tss.fs = 0x10; - second_task.task.tss.esp = PAGE_SIZE + (long)&second_task; - second_task.task.tss.eflags = 0x602; + + p = gdt+2+FIRST_TSS_ENTRY; + + for(i=1;ia = p->b = 0; + p++; + p->a = p->b = 0; + p++; + } + + create_second_process(); __asm__("pushfl; andl $0xffffbfff, (%esp); popfl"); ltr(0); @@ -86,6 +88,34 @@ void sched_init() { set_system_gate(0x80, &system_call); } +int create_second_process() { + struct task_struct *p; + int i, nr; + + nr = find_empty_process(); + if (nr < 0) + return -EAGAIN; + + p = (struct task_struct*) &(second_task.task); + + set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); + + p->tss.eip = (long)test_b; + p->tss.ldt = _LDT(nr); + p->tss.ss0 = 0x10; + p->tss.esp0 = PAGE_SIZE + (long)&second_task; + p->tss.ss = 0x10; + p->tss.ds = 0x10; + p->tss.es = 0x10; + p->tss.cs = 0x08; + p->tss.fs = 0x10; + p->tss.esp = PAGE_SIZE + (long)&second_task; + p->tss.eflags = 0x602; + + task[nr] = p; +} + void test_a(void) { __asm__("movl $0, %edi\n\r" "movl $0x17, %eax\n\t" diff --git a/kernel/traps.c b/kernel/traps.c index a07739ff17b789715019993817960900ba00d24b..078563f486fa94bab77334fd8156efe90e8ee8e1 100644 --- a/kernel/traps.c +++ b/kernel/traps.c @@ -2,21 +2,50 @@ #include #include +#define get_seg_byte(seg,addr) ({ \ +register char __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define get_seg_long(seg,addr) ({ \ +register unsigned long __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + + +#define _fs() ({ \ +register unsigned short __res; \ +__asm__("mov %%fs,%%ax":"=a" (__res):); \ +__res;}) + void divide_error(); void invalid_TSS(); void segment_not_present(); void stack_segment(); void general_protection(); +void page_fault(); static void die(char* str, long esp_ptr, long nr) { + int i = 0; long* esp = (long*)esp_ptr; - printk("%s: %04x\n\r", str, 0xffff & nr); - printk("EIP:\t%04x:", esp[1]); - printk("%p\n\r", esp[0]); - printk("EFLAGS:\t%p\n\r", esp[2]); - printk("ESP:\t%04x:", esp[4]); - printk("%p\n\r", esp[3]); + printk("\n\rEIP:\t%04x:%p\n\rEFLAGS:\t%p\n\rESP:\t%04x:%p\n\r", + esp[1],esp[0],esp[2],esp[4],esp[3]); + + printk("fs: %04x\n\r",_fs()); + printk("base: %p, limit: %p\n\r",get_base(current->ldt[1]),get_limit(0x17)); + if (esp[4] == 0x17) { + printk("Stack: "); + for (i=0;i<4;i++) + printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); + printk("\n\r"); + } + + for(i=0;i<10;i++) + printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); + printk("\n\r"); while (1) { } @@ -46,11 +75,16 @@ void do_general_protection(long esp, long error_code) { die("general protection", esp, error_code); } +void do_page_fault(long esp, long error_code) { + die("page fault", esp, error_code); +} + void trap_init() { set_trap_gate(0, ÷_error); set_trap_gate(10, &invalid_TSS); set_trap_gate(11, &segment_not_present); set_trap_gate(12, &stack_segment); set_trap_gate(13, &general_protection); + set_trap_gate(14, &page_fault); } diff --git a/mm/Makefile b/mm/Makefile index b84f028c14a7849f380534d5e287e2532e10de5b..e1cfe5bea32349119e85e5675190a27bb6a5848e 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -3,14 +3,16 @@ LD := ld CCFLAG := -I../include -nostdinc -Wall -fomit-frame-pointer -fno-stack-protector -c -m32 LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 INCDIR := ../include -OBJS := memory.o +OBJS := swap.o memory.o mm.o : $(OBJS) - $(LD) -m elf_i386 -r -o $@ $< + $(LD) -m elf_i386 -r -o $@ $^ memory.o : memory.c $(GCC) $(CCFLAG) -o $@ $< +swap.o : swap.c + $(GCC) $(CCFLAG) -o $@ $< clean : rm *.o diff --git a/mm/swap.c b/mm/swap.c new file mode 100644 index 0000000000000000000000000000000000000000..6b4ae3e580727e14874f0ea6377e5b6e36a6e78f --- /dev/null +++ b/mm/swap.c @@ -0,0 +1,26 @@ +#include + +unsigned long get_free_page() { + register unsigned long __res asm("ax"); + +repeat: +__asm__("std ; repne ; scasb\n\t" + "jne 1f\n\t" + "movb $1,1(%%edi)\n\t" + "sall $12, %%ecx\n\t" + "addl %2, %%ecx\n\t" + "movl %%ecx, %%edx\n\t" + "movl $1024, %%ecx\n\t" + "leal 4092(%%edx), %%edi\n\t" + "rep; stosl;\n\t" + "movl %%edx,%%eax\n" + "1:" + :"=a"(__res) + :"i"(0), "i"(LOW_MEM), "c"(PAGING_PAGES), + "D"(mem_map+PAGING_PAGES-1) + :"dx"); + + if (__res >= HIGH_MEMORY) + goto repeat; + return __res; +}