From 05a6f2fcf4556ba9f3d0384c07554c387f6efba2 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Tue, 4 Jul 2017 22:23:37 +0200 Subject: got scheduling of task A and B working (now graphics output and termination is broken) --- src/hardware/interrupts.asm | 43 +++++++++++++++++++++++++++++++------------ src/hardware/interrupts.c | 26 +++++++++++++++----------- src/hardware/interrupts.h | 9 ++++++++- src/kernel/kernel.c | 31 ++++++++++++++++++++++++++++++- src/kernel/tasks.c | 2 +- src/kernel/tasks.h | 2 +- 6 files changed, 86 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/hardware/interrupts.asm b/src/hardware/interrupts.asm index 155b2af..30204e7 100644 --- a/src/hardware/interrupts.asm +++ b/src/hardware/interrupts.asm @@ -53,6 +53,8 @@ IRQ_BASE equ 0x20 global interrupts_handle_irq_%1 interrupts_handle_irq_%1: mov [interrupt_no], byte IRQ_BASE + %1 + ; error + push 0x0 jmp int_entry %endmacro @@ -62,11 +64,18 @@ irq_stub 0x0C int_entry: ; safe state of interrupted code - pusha - push ds - push es - push fs - push gs + ;pusha + push ebp + push edi + push esi + push edx + push ecx + push ebx + push eax + ;push ds + ;push es + ;push fs + ;push gs ; call the static C handler with the correct interrupt number ; uint32_t interrupts_handle_interrupt( uint8_t interrupt_no, uint32_t esp ); @@ -74,15 +83,25 @@ int_entry: mov eax, [interrupt_no] push eax call interrupts_handle_static_interrupt - ;add esp, 8 + ; switch stack mov esp, eax - ; restore state - pop gs - pop fs - pop es - pop ds - popa + ; restore state (no popa or pusha, we have to align to cpu_state in tasks.h) + ;pop gs + ;pop fs + ;pop es + ;pop ds + ;popa + pop eax + pop ebx + pop ecx + pop edx + pop esi + pop edi + pop ebp + + ; remove error from the stack + add esp, 4 iret diff --git a/src/hardware/interrupts.c b/src/hardware/interrupts.c index 614dbf0..4ca0f14 100644 --- a/src/hardware/interrupts.c +++ b/src/hardware/interrupts.c @@ -7,9 +7,6 @@ #include "keyboard.h" -// TODO: for now the code segment is the first entry in the boot GDT -#define GDT_CODE_SEGMENT_SELECTOR 8 - // the Present bit in a IDT entry #define IDT_PRESENT_BIT 0x80 @@ -75,15 +72,17 @@ void interrupt_handler_init( interrupt_handler_t *handler, uint8_t interrupt_no, // of the interrupt handler structure static interrupt_t *active_interrupt; -void interrupts_init( interrupt_t *interrupt ) +void interrupts_init( interrupt_t *interrupt, uint16_t gdt_code_segment_selector, task_manager_t *task_manager ) { memset( interrupt, 0, sizeof( interrupt_t ) ); interrupt_handler_t empty_interrupt_handler; interrupt_handler_init_void( &empty_interrupt_handler ); + + interrupt->task_manager = task_manager; for( int i = 0; i < NOF_INTERRUPTS; i++ ) { - interrupts_register_interrupt_gate( interrupt, i, GDT_CODE_SEGMENT_SELECTOR, + interrupts_register_interrupt_gate( interrupt, i, gdt_code_segment_selector, &interrupts_ignore_request, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); interrupts_register_interrupt_handler( empty_interrupt_handler ); } @@ -92,7 +91,7 @@ void interrupts_init( interrupt_t *interrupt ) interrupt_handler_t divide_by_zero_interrupt_handler; interrupt_handler_init( ÷_by_zero_interrupt_handler, 0x00, interrupt, interrupts_exception_division_by_zero, NULL ); - interrupts_register_interrupt_gate( interrupt, 0x00, GDT_CODE_SEGMENT_SELECTOR, + interrupts_register_interrupt_gate( interrupt, 0x00, gdt_code_segment_selector, &interrupts_handle_exception_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); interrupts_register_interrupt_handler( divide_by_zero_interrupt_handler ); @@ -100,16 +99,16 @@ void interrupts_init( interrupt_t *interrupt ) interrupt_handler_t pit_interrupt_handler; interrupt_handler_init( &pit_interrupt_handler, IRQ_BASE + 0x00, interrupt, interrupts_interrupt_PIT, NULL ); - interrupts_register_interrupt_gate( interrupt, IRQ_BASE + 0x00, GDT_CODE_SEGMENT_SELECTOR, + interrupts_register_interrupt_gate( interrupt, IRQ_BASE + 0x00, gdt_code_segment_selector, &interrupts_handle_irq_0x00, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); interrupts_register_interrupt_handler( pit_interrupt_handler ); // IRQ 1 - PS/2 keyboard - interrupts_register_interrupt_gate( interrupt, IRQ_BASE + 0x01, GDT_CODE_SEGMENT_SELECTOR, + interrupts_register_interrupt_gate( interrupt, IRQ_BASE + 0x01, gdt_code_segment_selector, &interrupts_handle_irq_0x01, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); // IRQ 12 - PS/2 mouse - interrupts_register_interrupt_gate( interrupt, IRQ_BASE + 0x0C, GDT_CODE_SEGMENT_SELECTOR, + interrupts_register_interrupt_gate( interrupt, IRQ_BASE + 0x0C, gdt_code_segment_selector, &interrupts_handle_irq_0x0C, KERNEL_RING, IDT_TYPE_INTERRUPT_GATE ); port8_init( &interrupt->PIC_master_control, 0x20 ); @@ -202,8 +201,13 @@ uint32_t interrupts_handle_interrupt( interrupt_t *interrupt, uint8_t interrupt_ } uint32_t new_esp = handler->handle( handler, esp ); - - // send ACK to PIC for hardware interrups + + // timer interrupt, schedule the tasks + if( interrupt_no == IRQ_BASE + 0x00 ) { + new_esp = (uint32_t)task_manager_schedule_task( interrupt->task_manager, (cpu_state_t *)esp ); + } + + // send ACK to PIC for hardware interrupts if( interrupt_no >= IRQ_BASE && interrupt_no <= IRQ_BASE + 16 ) { port8_write( &interrupt->PIC_master_control, OCW2_EOI ); if( interrupt_no >= IRQ_BASE + 8 ) { diff --git a/src/hardware/interrupts.h b/src/hardware/interrupts.h index 8ab485e..767bb2e 100644 --- a/src/hardware/interrupts.h +++ b/src/hardware/interrupts.h @@ -4,6 +4,7 @@ #include #include "port.h" +#include "tasks.h" // total number of supported interrupts #define NOF_INTERRUPTS 256 @@ -11,6 +12,11 @@ // offset for hardware interrupts #define IRQ_BASE 0x20 +// TODO: for now the code segment is the first entry in the boot GDT +// temporary, should be a gdt module with functions to retrieve the +// current code segment selector +#define GDT_CODE_SEGMENT_SELECTOR 8 + // TCC 0.9.26 bug?, __attribute__( ( packed ) ) on structs not working, // also not working on members.. resorting to pragmas #if defined( __TINYC__ ) @@ -64,6 +70,7 @@ typedef struct interrupt_t { interrupt_descriptor_table_pointer_t idt_pointer; interrupt_gate_descriptor_t descriptor_table[NOF_INTERRUPTS]; interrupt_handler_t interrupt_handler[NOF_INTERRUPTS]; + task_manager_t *task_manager; // PIC master control register: command and status register port8_t PIC_master_control; // PIC master data register: interrupt mask and data register @@ -76,7 +83,7 @@ typedef struct interrupt_t { void interrupts_enable( void ); void interrupts_disable( void ); -void interrupts_init( interrupt_t *interrupt ); +void interrupts_init( interrupt_t *interrupt, uint16_t gdt_code_segment_selector, task_manager_t *task_manager ); void interrupts_register_interrupt_gate( interrupt_t *interrupt, uint8_t interrupt_no, uint16_t gdt_code_segment_selector, void (*helper_handler)( ), uint8_t privilege_level, uint8_t descriptor_type ); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 9a9f32e..b9beeb1 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -26,6 +26,8 @@ #include "text_widget.h" #include "window.h" +#include "tasks.h" + static jmp_buf panic_jmp_buf; static void handle_keyboard_event( keyboard_event_t *event, void *context ); @@ -53,6 +55,9 @@ typedef struct { static global_context_t global_context; +static void funcA( ); +static void funcB( ); + // must be first entry in kernel.bin (0x8800) as stage 2 of // the boot loader expects the entry point to be here! void kernel_main( void ) @@ -83,9 +88,19 @@ void kernel_main( void ) goto TERMINATE; } + // TODO: two demo tasks for now, later we should do something useful in a task + task_manager_t task_manager; + task_manager_init( &task_manager ); + task_t taskA; + task_init( &taskA, GDT_CODE_SEGMENT_SELECTOR, &funcA ); + task_manager_add_task( &task_manager, &taskA ); + task_t taskB; + task_init( &taskB, GDT_CODE_SEGMENT_SELECTOR, &funcB ); + task_manager_add_task( &task_manager, &taskB ); + puts( "Initializing interrupts" ); interrupt_t interrupt; - interrupts_init( &interrupt ); + interrupts_init( &interrupt, GDT_CODE_SEGMENT_SELECTOR, &task_manager ); puts( "Initializing drivers" ); driver_manager_init( &global_context.driver_manager ); @@ -362,3 +377,17 @@ static void handle_mouse_event( mouse_event_t *event, void *context ) break; } } + +static void funcA( ) +{ + while( true ) { + printf( "A" ); + } +} + +static void funcB( ) +{ + while( true ) { + printf( "B" ); + } +} diff --git a/src/kernel/tasks.c b/src/kernel/tasks.c index 164409a..4dd7f38 100644 --- a/src/kernel/tasks.c +++ b/src/kernel/tasks.c @@ -3,7 +3,7 @@ #include "kernel.h" #include "string.h" -void task_init( task_t *task, uint16_t gdt_code_segment_selector, task_func_t *entrypoint ) +void task_init( task_t *task, uint16_t gdt_code_segment_selector, task_func_t entrypoint ) { memset( task, 0, sizeof( task_t ) ); diff --git a/src/kernel/tasks.h b/src/kernel/tasks.h index 604c463..523631b 100644 --- a/src/kernel/tasks.h +++ b/src/kernel/tasks.h @@ -47,7 +47,7 @@ typedef struct { typedef void (*task_func_t)( void ); -void task_init( task_t *task, uint16_t gdt_code_segment_selector, task_func_t *entrypoint ); +void task_init( task_t *task, uint16_t gdt_code_segment_selector, task_func_t entrypoint ); #define MAX_NOF_TASKS 256 -- cgit v1.2.3-54-g00ecf