diff --git a/kernel/Makefile b/kernel/Makefile index 6ed77b6..df7ef58 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,7 +15,7 @@ export CXXFLAGS := -Wall -O2 -fno-rtti -fno-exceptions export LDFLAGS := -T $(LDSCRIPT) -Map $(KERNEL).map export LDLIBS := `$(CC) -print-libgcc-file-name` -SUBDIRS := boot mm lang isr +SUBDIRS := boot mm lang isr sys SUBDIRS_clean := $(SUBDIRS:%=%.clean) .PHONY: all diff --git a/kernel/boot/k_bootstrap.cc b/kernel/boot/k_bootstrap.cc index 2607fd1..a5d573a 100644 --- a/kernel/boot/k_bootstrap.cc +++ b/kernel/boot/k_bootstrap.cc @@ -6,6 +6,7 @@ #include "mm/mm.h" #include "mm/stack.h" #include "lang/kio.h" +#include "isr/interrupts.h" #define DEBUG_LETTER(col,chr) *(u16_t *)(KERNEL_OFFSET + CONSOLE_MEMORY \ + 160 * 8 + (col) * 2) \ @@ -48,6 +49,7 @@ u32_t k_bootstrap(mb_info_t * mb_info, u32_t mb_magic) */ mm_bootstrap(); stack_bootstrap(); + interrupts_bootstrap(); kio_bootstrap(); return 0; diff --git a/kernel/boot/k_main.cc b/kernel/boot/k_main.cc index b9d4639..5ced9a7 100644 --- a/kernel/boot/k_main.cc +++ b/kernel/boot/k_main.cc @@ -1,12 +1,27 @@ #include "lang/kio.h" #include "mm/mm.h" +#include "sys/timer.h" +#include "sys/pic.h" +#include "isr/interrupts.h" extern "C" { void k_main() { + kprintf("Kernel load address: 0x%08x\n", KERNEL_CODE); + kprintf("Kernel code size: %d KB (%d bytes)\n", + (KERNEL_DATA - KERNEL_CODE) >> 10, KERNEL_DATA - KERNEL_CODE); + kprintf("Kernel data size: %d KB (%d bytes)\n", + (KERNEL_BSS - KERNEL_DATA) >> 10, KERNEL_BSS - KERNEL_DATA); + kprintf("Kernel bss size: %d KB (%d bytes)\n", + (KERNEL_END - KERNEL_BSS) >> 10, KERNEL_END - KERNEL_BSS); mm_print_memory_map(); + timer_init(KERNEL_TIMER_FREQ); + pic_remap(0x20, 0x28); + pic_mask1(0x0); + pic_mask2(0x0); + interrupts_enable(); } } /* extern "C" */ diff --git a/kernel/include/hos_defines.h b/kernel/include/hos_defines.h index 5ce31f6..42f9b55 100644 --- a/kernel/include/hos_defines.h +++ b/kernel/include/hos_defines.h @@ -18,10 +18,12 @@ extern "C" { #define CONSOLE_MEMORY 0xB8000 extern u8_t _code; +extern u8_t _data; extern u8_t _bss; extern u8_t _end; #define KERNEL_CODE (&_code) +#define KERNEL_DATA (&_data) #define KERNEL_BSS (&_bss) #define KERNEL_END (&_end) @@ -31,6 +33,8 @@ extern u8_t _end; #define KERNEL_STACK_TOP 0xF0000000 +#define KERNEL_TIMER_FREQ 1000 + #ifdef __cplusplus } #endif diff --git a/kernel/include/hos_types.h b/kernel/include/hos_types.h index 9048d78..c1fd456 100644 --- a/kernel/include/hos_types.h +++ b/kernel/include/hos_types.h @@ -42,8 +42,8 @@ typedef struct typedef struct { - u16_t length; - u32_t phys_addr; + u16_t limit; + u32_t base; } __attribute__ ((packed)) gdtr_t; typedef gdtr_t idtr_t; diff --git a/kernel/include/portio.h b/kernel/include/portio.h old mode 100755 new mode 100644 diff --git a/kernel/isr/Makefile b/kernel/isr/Makefile old mode 100755 new mode 100644 diff --git a/kernel/isr/interrupts.cc b/kernel/isr/interrupts.cc old mode 100755 new mode 100644 index 43e71d4..9b243b1 --- a/kernel/isr/interrupts.cc +++ b/kernel/isr/interrupts.cc @@ -1,13 +1,47 @@ #include "hos_types.h" #include "interrupts.h" +#include "mm/mm.h" +#include "lang/kio.h" +#include "sys/pic.h" +#include "sys/cpu.h" extern "C" { -void isr(u8_t int_num, int_stack_t * int_stack) +idtr_t idtr; + +void isr(u8_t int_num, int_stack_t * istack) { switch (int_num) { + case 0x20: /* timer interrupt */ + (*(u16_t *)CONSOLE_MEMORY)++; + pic_eoi(); + break; + case 0x21: + /* TODO: keyboard hook */ + pic_eoi(); + break; + default: + kputs("--------------------------------------------------------------------------------"); + kprintf("Unhandled Interrupt #%d\n", int_num); + kprintf(" ds: 0x%08x es: 0x%08x fs: 0x%08x gs: 0x%08x\n", + istack->ds, istack->es, istack->fs, istack->gs); + kprintf(" eax: 0x%08x ebx: 0x%08x ecx: 0x%08x edx: 0x%08x\n", + istack->eax, istack->ebx, istack->ecx, istack->edx); + kprintf(" ebp: 0x%08x esi: 0x%08x edi: 0x%08x eflags: 0x%08x\n", + istack->ebp, istack->esi, istack->edi, istack->eflags); + kprintf(" cs: 0x%08x eip: 0x%08x ss: 0x%08x esp: 0x%08x\n", + istack->cs, istack->eip, istack->ss, istack->esp); + kprintf(" cr0: 0x%08x cr2: 0x%08x cr3: 0x%08x\n", + read_cr0(), read_cr2(), read_cr3()); + kprintf(" Error: 0x%08x (%d)\n", istack->error, istack->error); + kputs("--------------------------------------------------------------------------------"); + + kprintf("Halting!\n"); + for (;;) + ; + break; } } @@ -15,5 +49,59 @@ void isr(u8_t int_num, int_stack_t * int_stack) void interrupts_bootstrap() { - /* TODO: set up IDTR, IDT */ + u32_t idt_base = mm_early_page_alloc(); + u64_t * idt = (u64_t *) (idt_base + KERNEL_OFFSET); + idt[0] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_0, 0); + idt[1] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_1, 0); + idt[2] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_2, 0); + idt[3] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_3, 0); + idt[4] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_4, 0); + idt[5] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_5, 0); + idt[6] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_6, 0); + idt[7] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_7, 0); + idt[8] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_8, 0); + idt[9] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_9, 0); + idt[10] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_10, 0); + idt[11] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_11, 0); + idt[12] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_12, 0); + idt[13] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_13, 0); + idt[14] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_14, 0); + idt[15] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_15, 0); + idt[16] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_16, 0); + idt[17] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_17, 0); + idt[18] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_18, 0); + idt[19] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_19, 0); + idt[20] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_20, 0); + idt[21] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_21, 0); + idt[22] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_22, 0); + idt[23] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_23, 0); + idt[24] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_24, 0); + idt[25] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_25, 0); + idt[26] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_26, 0); + idt[27] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_27, 0); + idt[28] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_28, 0); + idt[29] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_29, 0); + idt[30] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_30, 0); + idt[31] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_31, 0); + idt[32] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_32, 0); + idt[33] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_33, 0); + idt[34] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_34, 0); + idt[35] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_35, 0); + idt[36] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_36, 0); + idt[37] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_37, 0); + idt[38] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_38, 0); + idt[39] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_39, 0); + idt[40] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_40, 0); + idt[41] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_41, 0); + idt[42] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_42, 0); + idt[43] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_43, 0); + idt[44] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_44, 0); + idt[45] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_45, 0); + idt[46] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_46, 0); + idt[47] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_47, 0); + idt[48] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_48, 0); + idt[49] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_49, 0); + idtr.base = idt_base; + idtr.limit = 49 * sizeof(idt[0]) - 1; + __asm__ __volatile__ ("lidt (idtr)"); } diff --git a/kernel/isr/interrupts.h b/kernel/isr/interrupts.h index 608de31..93eb147 100644 --- a/kernel/isr/interrupts.h +++ b/kernel/isr/interrupts.h @@ -8,10 +8,72 @@ extern "C" { void isr(u8_t int_num, int_stack_t * int_stack); +extern void isr_0(); +extern void isr_1(); +extern void isr_2(); +extern void isr_3(); +extern void isr_4(); +extern void isr_5(); +extern void isr_6(); +extern void isr_7(); +extern void isr_8(); +extern void isr_9(); +extern void isr_10(); +extern void isr_11(); +extern void isr_12(); +extern void isr_13(); +extern void isr_14(); +extern void isr_15(); +extern void isr_16(); +extern void isr_17(); +extern void isr_18(); +extern void isr_19(); +extern void isr_20(); +extern void isr_21(); +extern void isr_22(); +extern void isr_23(); +extern void isr_24(); +extern void isr_25(); +extern void isr_26(); +extern void isr_27(); +extern void isr_28(); +extern void isr_29(); +extern void isr_30(); +extern void isr_31(); +extern void isr_32(); +extern void isr_33(); +extern void isr_34(); +extern void isr_35(); +extern void isr_36(); +extern void isr_37(); +extern void isr_38(); +extern void isr_39(); +extern void isr_40(); +extern void isr_41(); +extern void isr_42(); +extern void isr_43(); +extern void isr_44(); +extern void isr_45(); +extern void isr_46(); +extern void isr_47(); +extern void isr_48(); +extern void isr_49(); + #ifdef __cplusplus } #endif +#define MAKE_IDT_DESCRIPTOR(selector, offset, dpl) \ + (u64_t) ( ( (((u64_t) offset) & 0xFFFF0000ull) << 32 ) /* offset 31:16 */ \ + | ( ( (u64_t) 0x1ull) << 47 ) /* present */ \ + | ( (((u64_t) dpl) & 0x3) << 45 ) /* DPL */ \ + | ( ( (u64_t) 0xEull) << 40 ) /* TODO: gate? */ \ + | ( (((u64_t) selector) & 0xFFFFull) << 16 ) /* selector */ \ + | ( (((u64_t) offset) & 0x0000FFFFull) ) ) /* offset 15:0 */ + void interrupts_bootstrap(); +#define interrupts_enable() __asm__ __volatile__ ("sti"); +#define interrupts_disable() __asm__ __volatile__ ("cli"); + #endif diff --git a/kernel/isr/isr.asm b/kernel/isr/isr.asm index 4c3a8cc..d57917c 100644 --- a/kernel/isr/isr.asm +++ b/kernel/isr/isr.asm @@ -33,8 +33,7 @@ isr_common: push esp ; pointer to interrupt stack push eax ; interrupt number -; TODO: uncomment when isr() is defined so the build won't break -; call isr + call isr pop eax ; restore stack pointer (this is shorter pop eax ; than "add esp, 8" and "lea esp, [esp+8]") diff --git a/kernel/link.ld b/kernel/link.ld index 60a6108..c9c17cc 100644 --- a/kernel/link.ld +++ b/kernel/link.ld @@ -12,6 +12,11 @@ SECTIONS *(.rodata*) . = ALIGN(4096); } + .other : { + *(.eh_*) + *(.rel*) + . = ALIGN(4096); + } .data : { data = .; _data = .; __data = .; *(.data*) diff --git a/kernel/mm/mm.cc b/kernel/mm/mm.cc index fc61054..e8422ff 100644 --- a/kernel/mm/mm.cc +++ b/kernel/mm/mm.cc @@ -6,6 +6,7 @@ #include "boot/k_early_panic.h" #include "lang/string.h" #include "lang/kio.h" +#include "sys/cpu.h" #define MM_MAX_MMAP_ENTRIES 64 @@ -148,10 +149,10 @@ void mm_bootstrap() u32_t gdt_base = mm_early_page_alloc(); mm_gdt = (u64_t *) ((u32_t) gdt_base + (u32_t) KERNEL_OFFSET); mm_gdt[0] = 0x0ull; - mm_gdt[1] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 1); - mm_gdt[2] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 0); - mm_gdtr.length = 3*sizeof(mm_gdt[0]) - 1; - mm_gdtr.phys_addr = gdt_base; + mm_gdt[1] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 1); /* kernel code */ + mm_gdt[2] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 0); /* kernel data */ + mm_gdtr.limit = 3 * sizeof(mm_gdt[0]) - 1; + mm_gdtr.base = gdt_base; /* set the page directory base register */ set_cr3(page_directory); diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index cd6af87..a5111bf 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -6,6 +6,9 @@ #include "hos_defines.h" #include "multiboot.h" +#define KERNEL_CODE_SEGMENT 0x08 +#define KERNEL_DATA_SEGMENT 0x10 + typedef u32_t pagedirectory_entry_t; #define NUM_PAGETABLE_ENTRIES (PAGE_SIZE / sizeof(pagedirectory_entry_t)) @@ -29,9 +32,6 @@ int mm_map(u32_t virtual_address, u32_t physical_address, u32_t mm_early_page_alloc(); u32_t mm_page_alloc(); -#define set_cr3(address) \ - __asm__ __volatile__ ("movl %0, %%cr3" : : "r" (address)); - /* http://courses.ece.illinois.edu/ece391/references/descriptors.pdf */ /* granularity: 0: limit in bytes; 1: limit in pages */ /* dpl: 0: system mode; 3: user mode */ diff --git a/kernel/mm/stack.cc b/kernel/mm/stack.cc old mode 100755 new mode 100644 diff --git a/kernel/mm/stack.h b/kernel/mm/stack.h old mode 100755 new mode 100644 diff --git a/kernel/sys/Makefile b/kernel/sys/Makefile new file mode 100644 index 0000000..cae81d7 --- /dev/null +++ b/kernel/sys/Makefile @@ -0,0 +1,2 @@ + +include $(HOS_TOPLEVEL)/subdir.mak diff --git a/kernel/sys/cpu.h b/kernel/sys/cpu.h new file mode 100644 index 0000000..76ff655 --- /dev/null +++ b/kernel/sys/cpu.h @@ -0,0 +1,34 @@ + +#ifndef CPU_H +#define CPU_H + +#include "hos_types.h" + +static u32_t read_cr0() +{ + u32_t val; + __asm__ __volatile__ ("movl %%cr0, %0" : "=r" (val)); + return val; +} + +static u32_t read_cr2() +{ + u32_t val; + __asm__ __volatile__ ("movl %%cr2, %0" : "=r" (val)); + return val; +} + +static u32_t read_cr3() +{ + u32_t val; + __asm__ __volatile__ ("movl %%cr3, %0" : "=r" (val)); + return val; +} + +#define set_cr0(val) \ + __asm__ __volatile__ ("movl %0, %%cr0" : : "r" (val)); + +#define set_cr3(val) \ + __asm__ __volatile__ ("movl %0, %%cr3" : : "r" (val)); + +#endif diff --git a/kernel/sys/pic.cc b/kernel/sys/pic.cc new file mode 100644 index 0000000..320e26e --- /dev/null +++ b/kernel/sys/pic.cc @@ -0,0 +1,29 @@ + +#include "pic.h" +#include "portio.h" + +/* + * Re-maps the Programmable Interrupr Controllers + * so IRQ0->pic1 base address, IRG8->pic2 base address + */ +void pic_remap(u8_t base1, u8_t base2) +{ + u8_t a1, a2; + + a1 = inportb(PIC1_DATA); /* 0x21 */ + a2 = inportb(PIC2_DATA); /* 0xA1 */ + + outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); /* 0x20, 0x10+0x01 00010001b */ + outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); /* 0xA0, 0x10+0x01 00010001b */ + outportb(PIC1_DATA, base1); /* 0x21, pic1 */ + outportb(PIC2_DATA, base2); /* 0xA1, pic2 */ + outportb(PIC1_DATA, 4); /* 0x21, 0x04 00000100b */ + outportb(PIC2_DATA, 2); /* 0xA1, 0x02 00000010b */ + outportb(PIC1_DATA, ICW4_8086); /* 0x21, 0x01 00000001b */ + outportb(PIC2_DATA, ICW4_8086); /* 0xA1, 0x01 00000001b */ + + outportb(PIC1_DATA, a1); /* 0x21 */ + outportb(PIC2_DATA, a2); /* 0xA1 */ +} + + diff --git a/kernel/sys/pic.h b/kernel/sys/pic.h new file mode 100644 index 0000000..1b793a9 --- /dev/null +++ b/kernel/sys/pic.h @@ -0,0 +1,46 @@ + +#ifndef PIC_H +#define PIC_H + +#include "hos_types.h" +#include "portio.h" + +#define PIC1 0x20 +#define PIC2 0xA0 +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) +#define PIC_EOI 0x20 + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +void pic_remap(u8_t base1, u8_t base2); + +/* Masks interrupts on first Programmable Interrupt Controller */ +#define pic_mask1(mask) outportb(PIC1_DATA, mask) /* 0x21, maskfield *OCW1* */ + +/* Masks interrupts on second Programmable Interrupt Controller */ +#define pic_mask2(mask) outportb(PIC2_DATA, mask) /* 0xA1, maskfield *OCW1* */ + +/* Signals an End Of Interrupt signal to the first PIC */ +#define pic_eoi() outportb(0x20, 0x20) + +/* Signals an End Of Interrupt signal to both the second and first PIC unit */ +static inline void pic_eoi2() +{ + outportb(0xA0, 0x20); + outportb(0x20, 0x20); +} + +#endif diff --git a/kernel/sys/timer.cc b/kernel/sys/timer.cc new file mode 100644 index 0000000..baa002b --- /dev/null +++ b/kernel/sys/timer.cc @@ -0,0 +1,12 @@ + +#include "timer.h" +#include "portio.h" + +void timer_init(u32_t freq) +{ + /* how many ticks the PIT must wait before issuing an interrupt */ + u32_t wait = 1193180 / freq; + outportb(0x43, 0x34); + outportb(0x40, wait); /* LSB */ + outportb(0x40, wait >> 8); /* MSB */ +} diff --git a/kernel/sys/timer.h b/kernel/sys/timer.h new file mode 100644 index 0000000..c2e76af --- /dev/null +++ b/kernel/sys/timer.h @@ -0,0 +1,9 @@ + +#ifndef TIMER_H +#define TIMER_H + +#include "hos_types.h" + +void timer_init(u32_t freq); + +#endif