diff --git a/Makefile b/Makefile index 0946426..71db3a3 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ kernel/elf.o \ kernel/syscall.o \ kernel/io/keyboard.o \ kernel/heap.o \ +kernel/task.o \ LIB_OBJS=\ $(ARCHDIR)/bootstrap.o \ @@ -32,6 +33,7 @@ $(ARCHDIR)/tty.o \ $(ARCHDIR)/strlib.o \ $(ARCHDIR)/interrupts/idt.o \ $(ARCHDIR)/interrupts/interrupt.o \ +$(ARCHDIR)/interrupts/irq0.o \ $(ARCHDIR)/interrupts/syscall.o \ $(ARCHDIR)/gdt.o \ $(ARCHDIR)/userland.o \ diff --git a/arch/i686/ata.c b/arch/i686/ata.c new file mode 100644 index 0000000..e69de29 diff --git a/arch/i686/interrupts/idt.c b/arch/i686/interrupts/idt.c index aa85dcc..6017f44 100644 --- a/arch/i686/interrupts/idt.c +++ b/arch/i686/interrupts/idt.c @@ -15,6 +15,15 @@ #define IRQ6 (IRQ0 + 6) #define IRQ7 (IRQ0 + 7) +#define IRQ8 0x28 +#define IRQ9 (IRQ8 + 1) +#define IRQ10 (IRQ8 + 2) +#define IRQ11 (IRQ8 + 3) +#define IRQ12 (IRQ8 + 4) +#define IRQ13 (IRQ8 + 5) +#define IRQ14 (IRQ8 + 6) +#define IRQ15 (IRQ8 + 7) + #define NUM_ENTRIES 0x100 struct InterruptDescriptor { @@ -97,21 +106,20 @@ static void load_idt() idt.base = entries; asm ( "lidt %0" : : "m"(idt) ); - asm ( "sti" ); } -struct InterruptDescriptor generate_entry(bool present, void isr(struct interrupt_frame*), uint8_t gate_type, uint8_t ring, uint8_t selector) +static struct InterruptDescriptor generate_entry(bool present, void isr(struct interrupt_frame*), uint8_t gate_type, uint8_t ring, uint8_t selector) { struct InterruptDescriptor entry; entry.present = present; - entry.offset = (uint32_t)isr; + entry.offset = (size_t)isr; entry.gate_type = gate_type; entry.ring = ring; entry.selector = selector; return entry; } -void idt_init() +static void add_exceptions() { struct InterruptDescriptor entry; @@ -130,23 +138,47 @@ void idt_init() entry = generate_entry(true, double_fault, 0xF, 0, 0x8); add_entry(entry, DoubleFault); - entry = generate_entry(true, irq, 0xE, 0, 0x8); +} + +static void add_irqs() +{ + struct InterruptDescriptor entry; + entry = generate_entry(true, irq_1, 0xE, 0, 0x8); for (int i = IRQ0; i <= IRQ7; i++) { add_entry(entry, i); } + entry = generate_entry(true, irq_2, 0xE, 0, 0x8); + for (int i = IRQ8; i <= IRQ15; i++) + { + add_entry(entry, i); + } + + entry = generate_entry(true, irq0, 0xE, 0, 0x8); + add_entry(entry, IRQ0); + entry = generate_entry(true, keyboard_interrupt, 0xE, 0, 0x8); add_entry(entry, IRQ1); +} +static void add_syscall() +{ struct InterruptDescriptor syscall_entry; syscall_entry.present = true; - syscall_entry.offset = (uint32_t)syscall; + syscall_entry.offset = (size_t)syscall; syscall_entry.gate_type = 0xE; syscall_entry.ring = 3; syscall_entry.selector = 0x8; add_entry(syscall_entry, 0x80); +} + +void idt_init() +{ + add_exceptions(); + add_irqs(); + add_syscall(); load_idt(); } diff --git a/arch/i686/interrupts/interrupt.c b/arch/i686/interrupts/interrupt.c index 8e97996..8e0cfaf 100644 --- a/arch/i686/interrupts/interrupt.c +++ b/arch/i686/interrupts/interrupt.c @@ -1,15 +1,11 @@ #include +#include +#include "interrupt.h" #include #include #include #include "../io.h" -struct interrupt_frame { - uint32_t eflags; - uint32_t cs; - uint32_t eip; -}; - uint8_t test = 'a'; static void stack_trace() @@ -25,40 +21,45 @@ static void stack_trace() } } -__attribute__((interrupt)) void divide_by_zero(void*) +__attribute__((interrupt)) void divide_by_zero(struct interrupt_frame*) { terminal_writestring("Yo dude u cant divide by zero yao\n"); while (1) { } } -__attribute__((interrupt)) void general_protection_fault(void*) +__attribute__((interrupt)) void general_protection_fault(struct interrupt_frame*) { terminal_writestring("GPF handler called\n"); while (1) { } } -__attribute__((interrupt)) void double_fault(void*) +__attribute__((interrupt)) void double_fault(struct interrupt_frame*) { stack_trace(); terminal_writestring("2 Errors in a row, u better behave naughty naughty\n"); while (1) { } } -__attribute__((interrupt)) void exception(void*) +__attribute__((interrupt)) void exception(struct interrupt_frame*) { terminal_writestring("Some weird error code stuff\n"); while (1) { } } -__attribute__((interrupt)) void keyboard_interrupt(void*) +__attribute__((interrupt)) void keyboard_interrupt(struct interrupt_frame*) { uint8_t scancode = inb(0x60); handle_keyboard(scancode); outb(0x20, 0x20); } -__attribute__((interrupt)) void irq(void*) +__attribute__((interrupt)) void irq_1(struct interrupt_frame*) { outb(0x20, 0x20); } +__attribute__((interrupt)) void irq_2(struct interrupt_frame*) +{ + outb(0xA0, 0x20); + outb(0x20, 0x20); +} diff --git a/arch/i686/interrupts/interrupt.h b/arch/i686/interrupts/interrupt.h index 0c8d7b2..d4b6c59 100644 --- a/arch/i686/interrupts/interrupt.h +++ b/arch/i686/interrupts/interrupt.h @@ -1,4 +1,12 @@ -struct interrupt_frame; +#include + +struct interrupt_frame { + size_t eip; + size_t cs; + size_t eflags; + size_t ss; + size_t esp; +}; __attribute__((interrupt)) void divide_by_zero(struct interrupt_frame* frame); __attribute__((interrupt)) void general_protection_fault(struct interrupt_frame* frame); @@ -6,7 +14,10 @@ __attribute__((interrupt)) void double_fault(struct interrupt_frame* frame); __attribute__((interrupt)) void exception(struct interrupt_frame* frame); -__attribute__((interrupt)) void syscall(void*); +__attribute__((interrupt)) void syscall(struct interrupt_frame* frame); __attribute__((interrupt)) void keyboard_interrupt(struct interrupt_frame* frame); -__attribute__((interrupt)) void irq(struct interrupt_frame* frame); +__attribute__((interrupt)) void irq_1(struct interrupt_frame* frame); +__attribute__((interrupt)) void irq_2(struct interrupt_frame* frame); + +__attribute__((interrupt)) void irq0(struct interrupt_frame* frame); diff --git a/arch/i686/interrupts/irq0.s b/arch/i686/interrupts/irq0.s new file mode 100644 index 0000000..9a2285c --- /dev/null +++ b/arch/i686/interrupts/irq0.s @@ -0,0 +1,62 @@ +.global irq0 +.extern _switch_task + +.global jump_kernel +.global jump_user + +.extern ss +.extern esp +.extern eflags +.extern cs +.extern eip + +irq0: +push %esp + +push %ebp + +push %edx +push %ecx +push %ebx +push %eax + +call _switch_task + +iret + +jump_kernel: +pop %eax /* pop return instruction */ + +pop %eax +pop %ebx +pop %ecx +pop %edx + +pop %ebp +pop %esp + +push (eflags) +push (cs) +push (eip) + +iret + +jump_user: +pop %eax /* pop return instruction */ + +pop %eax +pop %ebx +pop %ecx +pop %edx + +pop %ebp + +push (ss) +push (esp) +push (eflags) +push (cs) +push (eip) + +iret + + diff --git a/arch/i686/interrupts/pic.c b/arch/i686/interrupts/pic.c index a4e37f9..a34609a 100644 --- a/arch/i686/interrupts/pic.c +++ b/arch/i686/interrupts/pic.c @@ -21,17 +21,18 @@ void init_pic() { uint8_t a1; + uint8_t a2; a1 = inb(PIC1_DATA); // save masks - inb(PIC2_DATA); - + a2 = inb(PIC2_DATA); + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode) io_wait(); outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait(); outb(PIC1_DATA, 0x20); // ICW2: Master PIC vector offset io_wait(); - outb(PIC2_DATA, 0xFF); // ICW2: Slave PIC vector offset + outb(PIC2_DATA, 0x28); // ICW2: Slave PIC vector offset io_wait(); outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) io_wait(); @@ -45,5 +46,5 @@ void init_pic() { outb(PIC1_DATA, a1); // restore saved masks. // outb(PIC2_DATA, a2); - outb(PIC2_DATA, 0xFF); + outb(PIC2_DATA, a2); } diff --git a/include/kernel/io/ata.h b/include/kernel/io/ata.h new file mode 100644 index 0000000..e69de29 diff --git a/include/kernel/task.h b/include/kernel/task.h new file mode 100644 index 0000000..8819488 --- /dev/null +++ b/include/kernel/task.h @@ -0,0 +1,38 @@ +#include +#include + +struct CPUState { + size_t eax; + size_t ebx; + size_t ecx; + size_t edx; + size_t eip; + size_t esp; + size_t ebp; + size_t cs; + size_t ds; + size_t eflags; +}; + +struct Task { + struct CPUState state; +}; + +void switch_task( + size_t eax, + size_t ebx, + size_t ecx, + size_t edx, + + size_t ebp, + + size_t esp_real, + + size_t eip, + size_t cs, + size_t eflags, + size_t esp_fake, + size_t ds +); +void setup_tasks(); +void add_task(struct Task task); diff --git a/kernel/elf.c b/kernel/elf.c index 2d7edbd..5b4cfbb 100644 --- a/kernel/elf.c +++ b/kernel/elf.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) { @@ -20,5 +21,22 @@ void run_program(uint8_t* program, size_t length) uint8_t* userland_code = (uint8_t*) 0x00800000; memcpy(userland_code, program, length); - jump_to_userspace(); + struct CPUState target = { + .eip = (size_t) userland_code, + .esp = 0x00c00100, + .eax = 0, + .ebx = 0, + .ecx = 0, + .edx = 0, + .cs = 0x18 | 0x3, + .ds = 0x20 | 0x3, + .eflags = 0x0200, + .ebp = 0x00c00100, + }; + + struct Task task = { + .state = target, + }; + + add_task(task); } diff --git a/kernel/io/fat.c b/kernel/io/fat.c new file mode 100644 index 0000000..e69de29 diff --git a/kernel/kernel.c b/kernel/kernel.c index 23807e0..716ab5e 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -17,6 +18,7 @@ uint8_t program[] = { 0xcd, 0x80, // int 0x80 0xba, 0x00, 0x00, 0x00, 0x00, // mov 0, %edx 0xcd, 0x80, // int 0x80 + 0xcd, 0x20, // int 0x20 0xb9, 0x00, 0x00, 0x80, 0x00, // mov $start, %ecx 0xff, 0xe1, // jmp *%ecx }; @@ -26,9 +28,18 @@ void kernel_main(void) /* Initialize terminal interface */ terminal_initialize(); - init_pic(); idt_init(); + init_pic(); heap_init(); + setup_tasks(); + + asm("sti"); + run_program(program, sizeof(program)); + + while (true) { + asm("hlt"); + } + } diff --git a/kernel/task.c b/kernel/task.c new file mode 100644 index 0000000..346f941 --- /dev/null +++ b/kernel/task.c @@ -0,0 +1,141 @@ +#include +#include + +struct Task* tasks; +size_t tasks_capacity; +size_t num_tasks; + +size_t current_task = 0; + +void setup_tasks() +{ + tasks = malloc(sizeof(*tasks)); + tasks_capacity = 1; + num_tasks = 1; +} + +void add_task(struct Task task) +{ + if (num_tasks == tasks_capacity) { + struct Task* temp = malloc(sizeof(*tasks) * tasks_capacity * 2); + + for (size_t i = 0; i < num_tasks; i++) { + temp[i] = tasks[i]; + } + + tasks_capacity *= 2; + + free(tasks); + tasks = temp; + } + + tasks[num_tasks] = task; + num_tasks++; +} + +size_t ss; +size_t esp; +size_t eflags; +size_t cs; +size_t eip; + +void jump_kernel(size_t eax, size_t ebx, size_t ecx, size_t edx, size_t ebp, size_t esp); +void jump_user(size_t eax, size_t ebx, size_t ecx, size_t edx, size_t ebp); + +static void save_state( + size_t eax, + size_t ebx, + size_t ecx, + size_t edx, + + size_t esp, + size_t ebp, + + size_t eip, + + size_t cs, + size_t ds, + + size_t eflags +) { + struct CPUState state = { + .eax = eax, + .ebx = ebx, + .ecx = ecx, + .edx = edx, + + .esp = esp, + .ebp = ebp, + + .eip = eip, + + .cs = cs, + .ds = ds, + + .eflags = eflags, + }; + + tasks[current_task].state = state; + + current_task++; + current_task %= num_tasks; +} + +void next_task() { + struct CPUState s = tasks[current_task].state; + + ss = s.ds; + esp = s.esp; + eflags = s.eflags; + cs = s.cs; + eip = s.eip; + + if ((cs & 3) == 0) { + jump_kernel(s.eax, s.ebx, s.ecx, s.edx, s.ebp, s.esp); + } else { + jump_user(s.eax, s.ebx, s.ecx, s.edx, s.ebp); + } +} + +void _switch_task( + size_t eax, + size_t ebx, + size_t ecx, + size_t edx, + + size_t ebp, + + size_t esp_current, + + size_t eip_passed, + size_t cs_passed, + size_t eflags_passed, + size_t esp_passed, + size_t ds_passed +) +{ + if (num_tasks == 0) { + return; + }; + + size_t ds; + if ((cs & 3) == 0) { + ds = 0x10; + esp_current = esp_current + sizeof(size_t) * 3; + } else { + ds = ds_passed; + esp_current = esp_passed; + } + + ss = ds_passed; + esp = esp_passed; + eflags = eflags_passed; + cs = cs_passed; + eip = eip_passed; + + save_state(eax, ebx, ecx, edx, esp, ebp, eip_passed, cs_passed, ds, eflags_passed); + + next_task(); +} + +