diff --git a/include/asm/system.h b/include/asm/system.h index b44e6b6c3c2fe70693923d8db3b54a2be3a6c3e9..c1e67bc963998d4e9f1118252da33764b022ca2d 100644 --- a/include/asm/system.h +++ b/include/asm/system.h @@ -33,6 +33,8 @@ __asm__("movw %%dx, %%ax\n\t" \ "o"(*(4 + (char*)(gate_addr))), \ "d"((char*)(addr)), "a" (0x00080000)) +#define set_trap_gate(n, addr) \ + _set_gate(&idt[n], 15, 0, addr) #define set_intr_gate(n, addr) \ _set_gate(&idt[n], 14, 0, addr) diff --git a/include/linux/sched.h b/include/linux/sched.h index 2278399dac843f834d5e7c5afe40b319ceb79644..ab8f64e461411d6e9e590a6eb289f8c2a33b24ab 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -6,7 +6,13 @@ #include #include +void trap_init(); void sched_init(); +void test_a(); +void test_b(); + +extern struct task_struct *task[2]; +extern struct task_struct *current; struct tss_struct { long back_link; @@ -64,4 +70,16 @@ struct task_struct { #define ltr(n) __asm__("ltr %%ax"::"a"(_TSS(n))) #define lldt(n) __asm__("lldt %%ax"::"a"(_LDT(n))) +#define switch_to(n) {\ + struct {long a,b;} __tmp; \ + __asm__("cmpl %%ecx,current\n\t" \ + "je 1f\n\t" \ + "movw %%dx,%1\n\t" \ + "xchgl %%ecx,current\n\t" \ + "ljmp *%0\n\t" \ + "1:" \ + ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ + "d" (_TSS(n)),"c" ((long) task[n])); \ +} + #endif diff --git a/kernel/Makefile b/kernel/Makefile index dcc6f1fc3bff872d93609f578d1eb8ae2bc66de7..3415f0f164082b2a364351f8815294c279e9581d 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 sched.o printk.o vsprintf.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 chr_drv/chr_drv.a ../mm/mm.o system: $(OBJS) $(LD) $(LDFLAG) -e startup_32 -o $@ $^ @@ -13,6 +13,9 @@ head.o : head.S sys_call.o : sys_call.S $(GCC) -m32 -traditional -c -o $@ $< +asm.o : asm.S + $(GCC) -m32 -traditional -c -o $@ $< + main.o : main.c $(GCC) $(CCFLAG) -o $@ $< @@ -25,6 +28,9 @@ printk.o : printk.c vsprintf.o : vsprintf.c $(GCC) $(CCFLAG) -o $@ $< +traps.o : traps.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 new file mode 100644 index 0000000000000000000000000000000000000000..c6e39b1e7db9c0ef6a40fb11037e6ed875d43c37 --- /dev/null +++ b/kernel/asm.S @@ -0,0 +1,90 @@ +.code32 +.globl divide_error, +.globl invalid_TSS, segment_not_present, stack_segment +.globl general_protection + +divide_error: + pushl $do_divide_error +no_error_code: + xchgl %eax, (%esp) + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl $0 + leal 44(%esp), %edx + pushl %edx + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movw %dx, %fs + call *%eax + addl $8, %esp + pop %fs + pop %es + pop %ds + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + + +double_fault: + pushl $do_double_fault +error_code: + xchgl %eax, 4(%esp) + xchgl %ebx, (%esp) + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl %eax + leal 44(%esp), %eax + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + call *%ebx + addl $8, %esp + pop %fs + pop %es + pop %ds + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + +invalid_TSS: + pushl $do_invalid_TSS + jmp error_code + +segment_not_present: + pushl $do_segment_not_present + jmp error_code + +stack_segment: + pushl $do_stack_segment + jmp error_code + +general_protection: + pushl $do_general_protection + jmp error_code + diff --git a/kernel/main.c b/kernel/main.c index b68535b983c94e14398a4d52c3bb5590ac5ce497..17da17637707b60f5340fbca3ee9486b4505d86d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -39,12 +39,15 @@ void main(void) main_memory_start = buffer_memory_end; mem_init(main_memory_start, memory_end); + + trap_init(); sched_init(); tty_init(); - printk("%d %d\n\r", 12, 34); move_to_user_mode(); + test_a(); + __asm__ __volatile__( "int $0x80\n\r" "loop:\n\r" diff --git a/kernel/sched.c b/kernel/sched.c index 503810ee3c943cabecea03ff5bd45cffcd6ee4b7..ca42d15afa2c3618e801d7a51aa6b6c2fc5e9b05 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3,6 +3,8 @@ #include #include +#define COUNTER 100 + #define LATCH (1193180/HZ) #define PAGE_SIZE 4096 @@ -15,6 +17,10 @@ union task_union { }; 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)}; long user_stack[PAGE_SIZE >> 2]; @@ -24,18 +30,48 @@ struct short b; } stack_start = {&user_stack[PAGE_SIZE >> 2], 0x10}; + +int clock = COUNTER; + void do_timer(long cpl) { - static unsigned char c = '0'; - if (c > 127) { - c = '0'; + static int isFirst = 1; + if (clock >0 && clock <= COUNTER) { + clock--; + } + else if (clock == 0) { + clock = COUNTER; + if (isFirst) { + isFirst = 0; + switch_to(1); + } + else { + isFirst = 1; + switch_to(0); + } + } + else { + clock = COUNTER; } - printk("\b%c", c++); } void sched_init() { - 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; + __asm__("pushfl; andl $0xffffbfff, (%esp); popfl"); ltr(0); lldt(0); @@ -50,3 +86,32 @@ void sched_init() { set_system_gate(0x80, &system_call); } +void test_a(void) { +__asm__("movl $0, %edi\n\r" + "movl $0x17, %eax\n\t" + "movw %ax, %ds \n\t" + "movw %ax, %es \n\t" + "movw %ax, %fs \n\t" + "movw $0x18, %ax\n\t" + "movw %ax, %gs \n\t" + "movb $0x0c, %ah\n\r" + "movb $'A', %al\n\r" + "loopa:\n\r" + "movw %ax, %gs:(%edi)\n\r" + "jmp loopa"); +} + +void test_b(void) { +__asm__("movl $0, %edi\n\r" + "movl $0x17, %eax\n\t" + "movw %ax, %ds \n\t" + "movw %ax, %es \n\t" + "movw %ax, %fs \n\t" + "movw $0x18, %ax\n\t" + "movw %ax, %gs \n\t" + "movb $0x0f, %ah\n\r" + "movb $'B', %al\n\r" + "loopb:\n\r" + "movw %ax, %gs:(%edi)\n\r" + "jmp loopb"); +} diff --git a/kernel/traps.c b/kernel/traps.c new file mode 100644 index 0000000000000000000000000000000000000000..a07739ff17b789715019993817960900ba00d24b --- /dev/null +++ b/kernel/traps.c @@ -0,0 +1,56 @@ +#include +#include +#include + +void divide_error(); +void invalid_TSS(); +void segment_not_present(); +void stack_segment(); +void general_protection(); + +static void die(char* str, long esp_ptr, long nr) { + 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]); + + while (1) { + } +} + +void do_divide_error(long esp, long error_code) { + die("divide error", esp, error_code); +} + +void do_double_fault(long esp, long error_code) { + die("double fault", esp, error_code); +} + +void do_segment_not_present(long esp, long error_code) { + die("segment not present", esp, error_code); +} + +void do_invalid_TSS(long esp, long error_code) { + die("invalid tss", esp, error_code); +} + +void do_stack_segment(long esp, long error_code) { + die("stack segment", esp, error_code); +} + +void do_general_protection(long esp, long error_code) { + die("general protection", 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); +} + diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c index 35b2057b8df94988c9ee41d9c93463c071f9a1b2..64aa7bc6266d70fc36d4e0458ad849001ecd5dab 100644 --- a/kernel/vsprintf.c +++ b/kernel/vsprintf.c @@ -30,7 +30,7 @@ static char * number(char * str, int num, int base, int size, int precision ,int type) { char c,sign,tmp[36]; const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - int i; + int i = 0; if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; if (type&LEFT) type &= ~ZEROPAD;