From 837255c8ff040f84699d3c2efd329fc04dbafbdf Mon Sep 17 00:00:00 2001 From: Michal Idziorek Date: Sat, 30 Aug 2014 18:32:21 +0200 Subject: Added multitasking support for two tasks ;) --- asm/int_clock_handler.asm | 37 ++++++++++++++ kernel/kernel.c | 87 +++++++++++++++++++++++++------ kernel/pci.c | 8 +-- kernel/task.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/timer.c | 15 +++--- screenshots/foolos.png | Bin 24446 -> 27535 bytes 6 files changed, 247 insertions(+), 28 deletions(-) create mode 100644 asm/int_clock_handler.asm create mode 100644 kernel/task.c diff --git a/asm/int_clock_handler.asm b/asm/int_clock_handler.asm new file mode 100644 index 0000000..dd0de96 --- /dev/null +++ b/asm/int_clock_handler.asm @@ -0,0 +1,37 @@ +global int_clock_handler +[extern task_switch_next] + +CLOCK_COUNTER: + db 0x00 + +[bits 32] +int_clock_handler: + + ;Notice there is no IRQ number or error code - we don't need them + + inc byte [CLOCK_COUNTER] + + cmp byte [CLOCK_COUNTER], 0x10 + + jne skip_clock + + mov byte [CLOCK_COUNTER], 0x00 + + pusha ;Push all standard registers + + push esp ;Push pointer to all the stuff we just pushed + + call task_switch_next ;Call C code + + mov esp, eax ;Replace the stack with what the C code gave us + + popa ;Put the standard registers back + + skip_clock: + + mov al, 0x20 ;Port number AND command number to Acknowledge IRQ + out 0x20, al ;Acknowledge IRQ, so we keep getting interrupts + + ;We didn't push an error code or IRQ number, so we don't have to edit esp now + + iret ;Interrupt-Return diff --git a/kernel/kernel.c b/kernel/kernel.c index 88df43e..eee66d7 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -24,24 +24,56 @@ void int_floppy_handler(); uint32_t read_eip(); -// just a test handler for software interrupt 88, todo: remove and -// implement some syscalls! -// -void int_test_handler_worker() -{ - // this can not be called directly from interrupt handler - // due to optional parameters (...) probably! - panic(FOOLOS_MODULE_NAME,"unhandled EXCEPTION!"); -} -void int_test_handler() +void int_unhandled() { X86_IRQ_BEGIN - int_test_handler_worker(); - sleep(30); - while(1); // hang! + panic(FOOLOS_MODULE_NAME,"unhandled EXCEPTION!"); X86_IRQ_END } +void int_irq0(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Divide by 0"); X86_IRQ_END } +void int_irq1(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Single step (debugger)"); X86_IRQ_END } +void int_irq2(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Non Maskable Interrupt"); X86_IRQ_END } +void int_irq3(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Breakpoint (debugger)"); X86_IRQ_END } +void int_irq4(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Overflow"); X86_IRQ_END } +void int_irq5(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Bounds check"); X86_IRQ_END } +void int_irq6(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Undefined OP Code"); X86_IRQ_END } +void int_irq7(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"No coprocessor"); X86_IRQ_END } +void int_irq8(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Double Fault"); X86_IRQ_END } +void int_irq9(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Coprocessor Segment Overrun"); X86_IRQ_END } +void int_irq10(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Invalid TSS"); X86_IRQ_END } +void int_irq11(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Segment Not Present"); X86_IRQ_END } +void int_irq12(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Stack Segment Overrun"); X86_IRQ_END } + +void show_error(uint32_t err) +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"interrupt error code: 0x%08x",err); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"External Event: %x",err&0b001); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Location: %x",err&0b110); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Selector: %x",err&0b1111111111111000); +} + +void int_irq13() +{ + X86_IRQ_BEGIN + + + uint32_t err; + asm("pop %eax"); // get Error Code + asm ("mov %%eax, %0":"=r"(err)); + show_error(err); + + panic(FOOLOS_MODULE_NAME,"General Protection Fault"); + + X86_IRQ_END +} + +void int_irq14(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Page Fault"); X86_IRQ_END } +void int_irq15(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Unassigned"); X86_IRQ_END } +void int_irq16(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Coprocessor error"); X86_IRQ_END } +void int_irq17(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Alignment Check"); X86_IRQ_END } +void int_irq18(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Machine Check"); X86_IRQ_END } + // heart of our operating system. void kernel_main(uint32_t initial_stack) { @@ -69,7 +101,6 @@ void kernel_main(uint32_t initial_stack) log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"initial esp: 0x%08X",initial_stack); - // // PIT config (timer) timer_init(); @@ -104,10 +135,31 @@ void kernel_main(uint32_t initial_stack) int_install_ir(38, 0b10001110, 0x08,&int_floppy_handler); // install test software interrupt handler - int_install_ir(88, 0b10001110, 0x08,&int_test_handler); + int_install_ir(88, 0b10001110, 0x08,&int_unhandled); - for(int i=0;i<19;i++) - int_install_ir(i, 0b10001110, 0x08,&int_test_handler); + // exceptions + int_install_ir(0, 0b10001110, 0x08,&int_irq0); + int_install_ir(1, 0b10001110, 0x08,&int_irq1); + int_install_ir(2, 0b10001110, 0x08,&int_irq2); + int_install_ir(3, 0b10001110, 0x08,&int_irq3); + int_install_ir(4, 0b10001110, 0x08,&int_irq4); + int_install_ir(5, 0b10001110, 0x08,&int_irq5); + int_install_ir(6, 0b10001110, 0x08,&int_irq6); + int_install_ir(7, 0b10001110, 0x08,&int_irq7); + int_install_ir(8, 0b10001110, 0x08,&int_irq8); + int_install_ir(9, 0b10001110, 0x08,&int_irq9); + int_install_ir(10, 0b10001110, 0x08,&int_irq10); + int_install_ir(11, 0b10001110, 0x08,&int_irq11); + int_install_ir(12, 0b10001110, 0x08,&int_irq12); + int_install_ir(13, 0b10001110, 0x08,&int_irq13); + int_install_ir(14, 0b10001110, 0x08,&int_irq14); + int_install_ir(15, 0b10001110, 0x08,&int_irq15); + int_install_ir(16, 0b10001110, 0x08,&int_irq16); + int_install_ir(17, 0b10001110, 0x08,&int_irq17); + int_install_ir(18, 0b10001110, 0x08,&int_irq18); + + // multitasking + task_init(); // now we can enable interrupts back again int_enable(); @@ -120,6 +172,7 @@ void kernel_main(uint32_t initial_stack) // floppy floppy_init(); + //init shell shell_init(); /* diff --git a/kernel/pci.c b/kernel/pci.c index c1e6753..c8bd95d 100644 --- a/kernel/pci.c +++ b/kernel/pci.c @@ -85,11 +85,11 @@ uint16_t pciCheck(uint8_t bus, uint8_t slot) { // uint16_t irq=pciConfigReadWord(bus,slot,0,0x3C); // uint16_t irq2=pciConfigReadWord(bus,slot,0,0x3E); -// init_e1000(); + init_e1000(); -// test_bar(bus,slot,0x10); -// test_bar(bus,slot,0x14); -// test_bar(bus,slot,0x18); + test_bar(bus,slot,0x10); + test_bar(bus,slot,0x14); + test_bar(bus,slot,0x18); // scr_put_hex(irq); // scr_put_hex(irq2); diff --git a/kernel/task.c b/kernel/task.c new file mode 100644 index 0000000..fb71640 --- /dev/null +++ b/kernel/task.c @@ -0,0 +1,128 @@ +// http://hosted.cjmovie.net/TutMultitask.htm +// +// +#include "kernel.h" +#include "../lib/logger/log.h" // logger facilities +#define FOOLOS_MODULE_NAME "task" + +void task_test1() +{ + uint8_t c1; + + while(1) + { + c1++; + asm("cli"); + + PutString("task1: %03d", 0,560,0xffffff, c1); + + asm("sti"); + } + +} + +void task_test2() +{ + uint8_t c2; + + while(1) + { + c2++; + asm("cli"); + PutString("task2: %03d", 0,580,0xffffff, c2); + + asm("sti"); + } + +} + +////////////// +// +typedef struct{ //Simple structure for a thread + unsigned int esp0; //Stack for kernel + unsigned int esp3; //Stack for process +} Thread; + + +Thread Threads[2]; //Space for our simple threads. Just 2! +int CurrentTask = -1; //The thread currenlty running (-1 == none) + + +void task_create(int pid,void(*thread)()) +{ + unsigned int *stack; + + Threads[pid].esp0 = pmmngr_alloc_block(); + stack = (unsigned int*)Threads[pid].esp0+4000; //This makes a pointer to the stack for us + + //First, this stuff is pushed by the processor + *--stack = 0x0202; //This is EFLAGS + *--stack = 0x08; //This is CS, our code segment + *--stack = (uint32_t)thread; //This is EIP + + //Next, the stuff pushed by 'pusha' + *--stack = 0; //EDI + *--stack = 0; //ESI + *--stack = 0; //EBP + *--stack = 0; //Just an offset, no value + *--stack = 0; //EBX + *--stack = 0; //EDX + *--stack = 0; //ECX + *--stack = 0; //EAX + + //Now these are the data segments pushed by the IRQ handler + + /* + *--stack = 0x10; //DS + *--stack = 0x10; //ES + *--stack = 0x10; //FS + *--stack = 0x10; //GS + */ + + + Threads[pid].esp0 = (uint32_t)stack; //Update the stack pointer + + +}; + +uint32_t task_switch_next(uint32_t oldesp) +{ + + + + if(CurrentTask != -1){ //Were we even running a task? + Threads[CurrentTask].esp0 =oldesp; //Save the new esp for the thread + + //Now switch what task we're on + if(CurrentTask == 0)CurrentTask = 1; + else CurrentTask = 0; + } else{ + CurrentTask = 0; //We just started multi-tasking, start with task 0 + } + + uint32_t esp=0; + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"oldesp: 0x%08X saved / next task: %d (esp: 0x%08X) ",oldesp, CurrentTask,Threads[CurrentTask].esp0); + + return Threads[CurrentTask].esp0; //Return new stack pointer to ASM +} + +void stack_trace(uint32_t *stack,int size) +{ + for(int i=size;i>=0;i--) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"stack: 0x%08X -> 0x%08X", stack, *stack); + stack++; + + + } +} + +void task_init() +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"init multitasking."); + task_create(0,task_test1); + task_create(1,task_test2); +} + + + diff --git a/kernel/timer.c b/kernel/timer.c index f2e512c..b713674 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -42,33 +42,34 @@ static uint8_t timer8=0; uint16_t timer16=0; // clock handler +/* void int_clock_handler() { X86_IRQ_BEGIN; timer64++; -#ifdef DEBUG timer8++; - // show point once every 1 second if(timer8==25) { - scr_put_string("."); - timer8=0; + timer16++; } -#endif - timer8++; if(timer8==25) { - timer16++; +#ifdef DEBUG + scr_put_string("."); +#endif timer8=0; + task_switch(); + } X86_IRQ_END; } +*/ void timer_init() { diff --git a/screenshots/foolos.png b/screenshots/foolos.png index e5574a2..a81ae6d 100644 Binary files a/screenshots/foolos.png and b/screenshots/foolos.png differ -- cgit v1.2.3