diff --git a/k/Makefile b/k/Makefile index 02ba1c9..99c5520 100644 --- a/k/Makefile +++ b/k/Makefile @@ -31,7 +31,9 @@ OBJS = \ list.o \ memory.o \ serial.o \ - gdt.o + gdt.o \ + idt.o \ + isr.o DEPS = $(OBJS:.o=.d) @@ -39,7 +41,7 @@ DEPS = $(OBJS:.o=.d) all: $(TARGET) $(TARGET): CPPFLAGS += -MMD -Iinclude -I ../libs/libc/include/ -$(TARGET): CFLAGS += $(K_EXTRA_CFLAGS) +$(TARGET): CFLAGS += $(K_EXTRA_CFLAGS) -g $(TARGET): LDFLAGS += -Wl,-Tk.lds $(TARGET): LDLIBS = -L../libs/libc -lc $(TARGET): $(OBJS) diff --git a/k/gdt.c b/k/gdt.c index c8e0182..507795f 100644 --- a/k/gdt.c +++ b/k/gdt.c @@ -2,7 +2,7 @@ static struct gdt gdt = { 0 }; -static void create_kernel_ds() +static void create_kernel_ds(void) { struct gdt_entry *entry = gdt.entries + KERNEL_DS_INDEX; @@ -30,7 +30,7 @@ static void create_kernel_ds() entry->base_3 = (base >> 24) & 0xff; } -static void create_kernel_cs() +static void create_kernel_cs(void) { struct gdt_entry *entry = gdt.entries + KERNEL_CS_INDEX; @@ -58,13 +58,13 @@ static void create_kernel_cs() entry->base_3 = (base >> 24) & 0xff; } -static void create_gdt() +static void create_gdt(void) { create_kernel_ds(); create_kernel_cs(); } -static void load_gdt() +static void load_gdt(void) { struct gdt_r gdtr; gdtr.addr = (uint32_t)&gdt; @@ -76,12 +76,9 @@ static void load_gdt() : "memory"); } -static void load_ds() +static void load_ds(void) { - struct segment_selector selector; - selector.index = KERNEL_DS_INDEX; - selector.table_indicator = 0; - selector.rpl = 0; + struct segment_selector selector = KERNEL_DS_SEGMENT_SELECTOR; asm volatile("movw %0, %%ax\n" "movw %%ax, %%ds\n" @@ -93,12 +90,9 @@ static void load_ds() : "ax"); } -static void load_cs() +static void load_cs(void) { - struct segment_selector selector; - selector.index = KERNEL_CS_INDEX; - selector.table_indicator = 0; - selector.rpl = 0; + struct segment_selector selector = KERNEL_CS_SEGMENT_SELECTOR; asm volatile("pushl %0\n" "pushl $1f\n" @@ -108,13 +102,13 @@ static void load_cs() : "m" (selector)); } -static void reload_segment_selectors() +static void reload_segment_selectors(void) { load_ds(); load_cs(); } -void init_gdt() +void init_gdt(void) { create_gdt(); load_gdt(); diff --git a/k/gdt.h b/k/gdt.h index c2833cd..3a0f9fc 100644 --- a/k/gdt.h +++ b/k/gdt.h @@ -9,6 +9,9 @@ #define KERNEL_CS_INDEX 1 #define KERNEL_DS_INDEX 2 +#define KERNEL_CS_SEGMENT_SELECTOR {0, 0, KERNEL_CS_INDEX} +#define KERNEL_DS_SEGMENT_SELECTOR {0, 0, KERNEL_DS_INDEX} + struct gdt_entry { uint16_t limit_1 : 16; // 16 lsbs of the segment limit @@ -60,6 +63,6 @@ struct segment_selector uint16_t index : 13; // index of the entry in the table } __attribute__ ((packed)); -void init_gdt(); +void init_gdt(void); #endif /* !GDT_H */ diff --git a/k/idt.c b/k/idt.c new file mode 100644 index 0000000..7392c42 --- /dev/null +++ b/k/idt.c @@ -0,0 +1,88 @@ +#include "idt.h" +#include "stdio.h" + +static struct idt idt = { 0 }; + +static struct idt_entry_descriptor idt_entries_descriptors[IDT_NB_ENTRIES] = { + {(uint32_t)&isr_divide, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 0 + {(uint32_t)&isr_debug, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 1 + {(uint32_t)&isr_nmi, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 2 + {(uint32_t)&isr_breakpoint, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 3 + {(uint32_t)&isr_overflow, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 4 + {(uint32_t)&isr_bound_range_exceeded, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 5 + {(uint32_t)&isr_invalid_opcode, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 6 + {(uint32_t)&isr_device_not_available, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 7 + {(uint32_t)&isr_double_fault, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 8 + {(uint32_t)&isr_coprocessor_segment_overrun, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 9 + {(uint32_t)&isr_invalid_tss, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 10 + {(uint32_t)&isr_segment_not_present, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 11 + {(uint32_t)&isr_stack_segment_fault, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 12 + {(uint32_t)&isr_general_protection, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 13 + {(uint32_t)&isr_page_fault, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 14 + {0, {0, 0, 0}, 0}, // 15 + {(uint32_t)&isr_fpu_floating_point_error, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 16 + {(uint32_t)&isr_alignment_check, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 17 + {(uint32_t)&isr_machine_check, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 18 + {(uint32_t)&isr_simd_floating_point_exception, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 19 + {(uint32_t)&isr_virtualization_exception, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 20 + {(uint32_t)&isr_control_protection_exception, KERNEL_CS_SEGMENT_SELECTOR, INTERRUPT_TYPE}, // 21 + {0, {0, 0, 0}, 0}, // 22 + {0, {0, 0, 0}, 0}, // 23 + {0, {0, 0, 0}, 0}, // 24 + {0, {0, 0, 0}, 0}, // 25 + {0, {0, 0, 0}, 0}, // 26 + {0, {0, 0, 0}, 0}, // 27 + {0, {0, 0, 0}, 0}, // 28 + {0, {0, 0, 0}, 0}, // 29 + {0, {0, 0, 0}, 0}, // 30 + {0, {0, 0, 0}, 0} // 31 +}; + +void interrupt_handler(struct isr_param *isr_param) +{ + printf("Oh no %d!\r\n", isr_param->int_vector); +} + +struct idt_entry create_idt_entry(struct idt_entry_descriptor descriptor) +{ + struct idt_entry res = { 0 }; + + res.selector = descriptor.selector; + res.offset_1 = descriptor.offset & 0xffff; + res.offset_2 = (descriptor.offset >> 16) & 0xffff; + + res.type = descriptor.type; + res.size = 1; + res.desc_priv = 0; + res.present = 1; + + return res; +} + +static void create_idt(void) +{ + for (int i = 0; i < IDT_NB_ENTRIES; ++i) + { + struct idt_entry entry = create_idt_entry(idt_entries_descriptors[i]); + idt.entries[i] = entry; + } +} + + +static void load_idt(void) +{ + struct idt_r idtr; + idtr.addr = (uint32_t)&idt; + idtr.limit = IDT_SIZE - 1; + + asm volatile("lidt %0\n" + : + : "m" (idtr) + : "memory"); +} + +void init_idt(void) +{ + create_idt(); + load_idt(); +} diff --git a/k/idt.h b/k/idt.h new file mode 100644 index 0000000..2d6c276 --- /dev/null +++ b/k/idt.h @@ -0,0 +1,51 @@ +#ifndef IDT_H +#define IDT_H + +#include +#include "gdt.h" +#include "isr.h" + +#define IDT_NB_ENTRIES 32 +#define IDT_SIZE (IDT_NB_ENTRIES * sizeof(struct idt_entry)) + +#define INTERRUPT_TYPE 0x6 +#define TRAP_TYPE 0x7 + +struct idt_entry +{ + uint16_t offset_1 : 16; + struct segment_selector selector; + + uint8_t zero_1 : 8; // unused, set to 0 + uint8_t type : 3; // gate type + uint8_t size : 1; + uint8_t zero_2 : 1; // set to 0 for interrupt and trap gates + uint8_t desc_priv : 2; // Descriptor privilege + uint8_t present : 1; + + uint16_t offset_2 : 16; +} __attribute__ ((packed)); + +struct idt +{ + struct idt_entry entries[IDT_NB_ENTRIES]; +}; + +struct idt_r +{ + uint16_t limit; + uint32_t addr; +} __attribute__ ((packed)); + +struct idt_entry_descriptor +{ + uint32_t offset; + struct segment_selector selector; + char type; +}; + +void init_idt(void); + +void interrupt_handler(struct isr_param *isr_param); + +#endif /* !IDT_H */ diff --git a/k/isr.S b/k/isr.S new file mode 100644 index 0000000..09ff49c --- /dev/null +++ b/k/isr.S @@ -0,0 +1,129 @@ +.section .text + +isr: + pushal + pushl %esp + add $32, (%esp) + call interrupt_handler + add $4, %esp + popal + add $8, %esp + iret + +.global isr_divide +isr_divide: + pushl $0 // error code padding + pushl $0 // int vector + jmp isr + +.global isr_debug +isr_debug: + pushl $0 // error code padding + pushl $1 // int vector + jmp isr + +.global isr_nmi +isr_nmi: + pushl $0 // error code padding + pushl $2 // int vector + jmp isr + +.global isr_breakpoint +isr_breakpoint: + pushl $0 // error code padding + pushl $3 // int vector + jmp isr + +.global isr_overflow +isr_overflow: + pushl $0 // error code padding + pushl $4 // int vector + jmp isr + +.global isr_bound_range_exceeded +isr_bound_range_exceeded: + pushl $0 // error code padding + pushl $5 // int vector + jmp isr + +.global isr_invalid_opcode +isr_invalid_opcode: + pushl $0 // error code padding + pushl $6 // int vector + jmp isr + +.global isr_device_not_available +isr_device_not_available: + pushl $0 // error code padding + pushl $7 // int vector + jmp isr + +.global isr_double_fault +isr_double_fault: + pushl $8 // int vector + jmp isr + +.global isr_coprocessor_segment_overrun +isr_coprocessor_segment_overrun: + pushl $0 // error code padding + pushl $9 // int vector + jmp isr + +.global isr_invalid_tss +isr_invalid_tss: + pushl $10 // int vector + jmp isr + +.global isr_segment_not_present +isr_segment_not_present: + pushl $11 // int vector + jmp isr + +.global isr_stack_segment_fault +isr_stack_segment_fault: + pushl $12 // int vector + jmp isr + +.global isr_general_protection +isr_general_protection: + pushl $13 // int vector + jmp isr + +.global isr_page_fault +isr_page_fault: + pushl $14 // int vector + jmp isr + +.global isr_fpu_floating_point_error +isr_fpu_floating_point_error: + pushl $0 // error code padding + pushl $16 // int vector + jmp isr + +.global isr_alignment_check +isr_alignment_check: + pushl $17 // int vector + jmp isr + +.global isr_machine_check +isr_machine_check: + pushl $0 // error code padding + pushl $18 // int vector + jmp isr + +.global isr_simd_floating_point_exception +isr_simd_floating_point_exception: + pushl $0 // error code padding + pushl $19 // int vector + jmp isr + +.global isr_virtualization_exception +isr_virtualization_exception: + pushl $0 // error code padding + pushl $20 // int vector + jmp isr + +.global isr_control_protection_exception +isr_control_protection_exception: + pushl $21 // int vector + jmp isr diff --git a/k/isr.h b/k/isr.h new file mode 100644 index 0000000..1d5c8a6 --- /dev/null +++ b/k/isr.h @@ -0,0 +1,32 @@ +#ifndef ISR_H +#define ISR_H + +struct isr_param +{ + uint32_t int_vector; + uint32_t error_code; +} __attribute__ ((packed)); + +void isr_divide(void); +void isr_debug(void); +void isr_nmi(void); +void isr_breakpoint(void); +void isr_overflow(void); +void isr_bound_range_exceeded(void); +void isr_invalid_opcode(void); +void isr_device_not_available(void); +void isr_double_fault(void); +void isr_coprocessor_segment_overrun(void); +void isr_invalid_tss(void); +void isr_segment_not_present(void); +void isr_stack_segment_fault(void); +void isr_general_protection(void); +void isr_page_fault(void); +void isr_fpu_floating_point_error(void); +void isr_alignment_check(void); +void isr_machine_check(void); +void isr_simd_floating_point_exception(void); +void isr_virtualization_exception(void); +void isr_control_protection_exception(void); + +#endif /* !ISR_H */ diff --git a/k/k.c b/k/k.c index 40a4ae5..5e7c1f4 100644 --- a/k/k.c +++ b/k/k.c @@ -23,15 +23,17 @@ */ #include -#include "multiboot.h" -#include "stdio.h" -#include "serial.h" #include "gdt.h" +#include "idt.h" +#include "multiboot.h" +#include "serial.h" +#include "stdio.h" static void k_init(void) { init_serial(); init_gdt(); + init_idt(); } void k_main(unsigned long magic, multiboot_info_t *info) @@ -43,8 +45,14 @@ void k_main(unsigned long magic, multiboot_info_t *info) char *fb = (void *)0xb8000; k_init(); - + asm volatile("int $3\n" + : + : + :); printf("bonjour\r\n"); + + + for (unsigned i = 0; ; ) { *fb = star[i++ % 4]; }