diff --git a/connect_gdb.sh b/connect_gdb.sh new file mode 100755 index 0000000..29fa887 --- /dev/null +++ b/connect_gdb.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +i686-elf-gdb build/ukern.elf \ + -ex "target remote localhost:1234" \ + -ex "break start" \ + -ex "continue" diff --git a/include/idt.h b/include/idt.h index 90ab51a..527a926 100644 --- a/include/idt.h +++ b/include/idt.h @@ -3,24 +3,24 @@ #include typedef struct InterruptDescriptor_s { - uint16_t offset_1; + uint16_t offset_lo; uint16_t selector; uint8_t reserved; uint8_t attributes; - uint16_t offset_2; + uint16_t offset_hi; } InterruptDescriptor_t; typedef struct IDTR_s { uint16_t size; InterruptDescriptor_t* IDT; -} IDTR_t; +} __attribute__((packed)) IDTR_t; extern IDTR_t idtr; -extern InterruptDescriptor_t* idt_start; -extern char num_interrupts; +extern InterruptDescriptor_t idt_start; +extern unsigned char num_interrupts; void setup_idt(); void write_descriptors(); -void load_idt(); +extern void load_idt(); #endif diff --git a/include/interrupt_handlers.h b/include/interrupt_handlers.h index 4d5c7ce..1e03db7 100644 --- a/include/interrupt_handlers.h +++ b/include/interrupt_handlers.h @@ -1,10 +1,12 @@ #ifndef INTERRUPTHANDLERS_H #define INTERRUPTHANDLERS_H #include -extern void* isr_ptrs; +extern void (*isr_ptrs[])(void); + +//Struct is built "backwards" since it is pushed in this order. typedef struct StateSnapshot_s { - uint32_t eax, ecx, edx, ebx, esp, esi, edi; + uint32_t edi, esi, esp, ebx, edx, ecx, eax; uint32_t interrupt_id, error_code; uint32_t eip, cs, eflags; } StateSnapshot_t; diff --git a/src/allocidt.s b/src/allocidt.s index 263a1aa..8d3df6a 100644 --- a/src/allocidt.s +++ b/src/allocidt.s @@ -1,15 +1,19 @@ -%define NUM_INTERRUPTS 32 -global idtr, idt_start, num_interrupts -section .idtr +%define NUM_INTERRUPTS 255 +global idtr, idt_start, num_interrupts, load_idt + +section .text + load_idt: + lidt [idtr] + ret + +section .idtr align=8 num_interrupts: db NUM_INTERRUPTS idtr: - ;Normally, the size would be the size of the whole table, but i'm only defining 32 interrupts for now. - ;dw idt_end - idt_start - dw NUM_INTERRUPTS * 8 - dd idt_start + ;IDTR looks like the size (minus 1) and then the pointer to the start of it. + dw 0 + dd 0 section .idt nobits idt_start: - resb NUM_INTERRUPTS * 8 - idt_end: + resb (NUM_INTERRUPTS+1) * 8 diff --git a/src/gdt.s b/src/gdt.s index 5f93f15..1c1da6c 100644 --- a/src/gdt.s +++ b/src/gdt.s @@ -50,7 +50,8 @@ section .gdt_sect db 0 db 0b10001001 dw 0 + gdt_end: gdtr: - dw gdtr - gdt - 1 + dw gdt_end - gdt - 1 dd gdt diff --git a/src/idt.c b/src/idt.c index b353ff2..239d72e 100644 --- a/src/idt.c +++ b/src/idt.c @@ -1,18 +1,35 @@ #include "idt.h" - +#include "interrupt_handlers.h" void setup_idt() { + idtr.size = (sizeof(InterruptDescriptor_t) * 256) - 1; + idtr.IDT = &idt_start; write_descriptors(); load_idt(); } void write_descriptors() { - for(int i = 0; i < num_interrupts; i++) { + for(int i = 0; i <= num_interrupts; i++) { + uint32_t current_isr = (uint32_t)isr_ptrs[i]; + InterruptDescriptor_t* current_idt_entry = idtr.IDT + (i*8); + + // Offset bits 0-15 + current_idt_entry->offset_lo = current_isr & 0xFFFF; + current_idt_entry->offset_hi = current_isr >> 16; + current_idt_entry->selector = 0x08; // GDT index = 1 (kernel code seg), TI = 0 (pull from GDT, not LDT), RPL = 0 (ring 0) + //Attributes is a complex field. Lets break it down: + //First 4 bits is the gate type. Task, interrupt, trap. + //bit 44 is a zero + //Bits 45-46 is DPL - or what rings can access the interrupt via the INT instruction. + if(i < 32) + //All interrupt gates, only R0 can access. + current_idt_entry->attributes = 0b10001110; + else + //All interrupt gates, all rings can use these ints. + current_idt_entry->attributes = 0b11101110; + } } -void load_idt() { - return; -} diff --git a/src/interrupts.s b/src/interrupts.s index 47eae1a..2e1db19 100644 --- a/src/interrupts.s +++ b/src/interrupts.s @@ -34,7 +34,7 @@ isr_%1: %assign j 0 -%rep 32 +%rep 255 isr_ %+ j: ISR_ENTRY j %assign j j+1 @@ -42,7 +42,7 @@ isr_%1: ; Generate a table of pointers that point to each of our ISRs. This will be accessed from C to setup our IDT. isr_ptrs: %assign i 0 - %rep 32 + %rep 255 dd isr_ %+ i %assign i i+1 %endrep diff --git a/src/kio.c b/src/kio.c index a99a8ce..0b3dec6 100644 --- a/src/kio.c +++ b/src/kio.c @@ -76,7 +76,6 @@ void vga_printdec(uint32_t out) { void vga_printf(const char* fmt, ...) { va_list args; va_start(args, fmt); - while(*fmt) { if(*fmt == '%') { fmt++; diff --git a/src/kttools.c b/src/kttools.c index 1412ee6..4c9ac6e 100644 --- a/src/kttools.c +++ b/src/kttools.c @@ -30,6 +30,11 @@ */ void i_to_str(uint32_t num, char* buf, int size, int radix) { //null terminate the string + if(num == 0){ + buf[0] = '0'; + buf[1] = '\0'; + return; + } buf[--size] = '\0'; while(size > 0 && (num) != 0){ int isolated_num = num % radix; diff --git a/src/main.c b/src/main.c index eb46240..76c92cd 100644 --- a/src/main.c +++ b/src/main.c @@ -4,15 +4,24 @@ #include "kio.h" #include "kttools.h" #include "kmultiboot.h" - +#include "idt.h" //finally, main. void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) { //Hello C! Let's get to work in cleaning up our environment a bit and creating some safety. //First interrupts. + vga_clear(); + vga_printf("IDT base = %X", idtr.IDT); - + setup_idt(); + + vga_printf("IDT test :)"); + int x = 5; + int y = 1; + x = x / (y-1); + + vga_printf("%d", x); //wipe the screen vga_clear(); //We're going to use this buffer as our 8char hex representation for reading mem @@ -28,5 +37,6 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) vga_printf("MEM_LOWER:%X\n", multiboot_info->mem_lower); vga_printf("MEM_UPPER:%X\n", multiboot_info->mem_upper); + }