From 8f138254a4ca7951d575a93b7b942be461bb20bb Mon Sep 17 00:00:00 2001 From: hinus Date: Fri, 18 Jun 2021 20:17:56 +0800 Subject: [PATCH 1/2] Title: traps init. Issue: https://gitee.com/hinus/linux_kernel_011/issues/I3V4FC Description: some important traps. --- include/asm/system.h | 2 ++ include/linux/sched.h | 1 + kernel/Makefile | 8 ++++- kernel/asm.S | 81 +++++++++++++++++++++++++++++++++++++++++++ kernel/main.c | 2 ++ kernel/traps.c | 38 ++++++++++++++++++++ 6 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 kernel/asm.S create mode 100644 kernel/traps.c diff --git a/include/asm/system.h b/include/asm/system.h index b44e6b6..c1e67bc 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 2278399..fa73fc3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -6,6 +6,7 @@ #include #include +void trap_init(); void sched_init(); struct tss_struct { diff --git a/kernel/Makefile b/kernel/Makefile index dcc6f1f..3415f0f 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 0000000..0d04433 --- /dev/null +++ b/kernel/asm.S @@ -0,0 +1,81 @@ +.code32 +.globl divide_error, 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 + +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 b68535b..3cdd802 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -39,6 +39,8 @@ void main(void) main_memory_start = buffer_memory_end; mem_init(main_memory_start, memory_end); + + trap_init(); sched_init(); tty_init(); diff --git a/kernel/traps.c b/kernel/traps.c new file mode 100644 index 0000000..4ad920a --- /dev/null +++ b/kernel/traps.c @@ -0,0 +1,38 @@ +#include +#include + +void divide_error(); +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); + + 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_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(12, &stack_segment); + set_trap_gate(13, &general_protection); +} + -- Gitee From 34da13eb405542602d6a303c6b7480328492212a Mon Sep 17 00:00:00 2001 From: hinus Date: Sat, 19 Jun 2021 01:30:45 +0800 Subject: [PATCH 2/2] Title: Create 2nd process. Issue: https://gitee.com/hinus/linux_kernel_011/issues/I3W29M https://gitee.com/hinus/linux_kernel_011/issues/I3VH1T Description: Create 2nd process, and make them switch to each other. bugfix, i in vsprintf is not initialized. --- include/linux/sched.h | 17 ++++++++++ kernel/asm.S | 13 ++++++-- kernel/main.c | 3 +- kernel/sched.c | 75 ++++++++++++++++++++++++++++++++++++++++--- kernel/traps.c | 18 +++++++++++ kernel/vsprintf.c | 2 +- 6 files changed, 119 insertions(+), 9 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index fa73fc3..ab8f64e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -8,6 +8,11 @@ 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; @@ -65,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/asm.S b/kernel/asm.S index 0d04433..c6e39b1 100644 --- a/kernel/asm.S +++ b/kernel/asm.S @@ -1,5 +1,6 @@ .code32 -.globl divide_error, stack_segment +.globl divide_error, +.globl invalid_TSS, segment_not_present, stack_segment .globl general_protection divide_error: @@ -71,9 +72,17 @@ error_code: 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 + jmp error_code general_protection: pushl $do_general_protection diff --git a/kernel/main.c b/kernel/main.c index 3cdd802..17da176 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -44,9 +44,10 @@ void main(void) 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 503810e..ca42d15 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 index 4ad920a..a07739f 100644 --- a/kernel/traps.c +++ b/kernel/traps.c @@ -1,7 +1,10 @@ #include #include +#include void divide_error(); +void invalid_TSS(); +void segment_not_present(); void stack_segment(); void general_protection(); @@ -9,6 +12,11 @@ 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) { } @@ -22,6 +30,14 @@ 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); } @@ -32,6 +48,8 @@ void do_general_protection(long esp, long 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 35b2057..64aa7bc 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; -- Gitee