summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-07-04 22:23:37 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-07-04 22:23:37 +0200
commit05a6f2fcf4556ba9f3d0384c07554c387f6efba2 (patch)
tree85d430b47f0d5b1ad004f04d9ab4fbc602c83ed2 /src
parente6efe69c614d7781d18a7189831e8243abf57664 (diff)
downloadabaos-05a6f2fcf4556ba9f3d0384c07554c387f6efba2.tar.gz
abaos-05a6f2fcf4556ba9f3d0384c07554c387f6efba2.tar.bz2
got scheduling of task A and B working (now graphics output and termination is broken)
Diffstat (limited to 'src')
-rw-r--r--src/hardware/interrupts.asm43
-rw-r--r--src/hardware/interrupts.c26
-rw-r--r--src/hardware/interrupts.h9
-rw-r--r--src/kernel/kernel.c31
-rw-r--r--src/kernel/tasks.c2
-rw-r--r--src/kernel/tasks.h2
6 files changed, 86 insertions, 27 deletions
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( &divide_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 <stdint.h>
#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