diff --git a/kernel/boot/k_bootstrap.cc b/kernel/boot/k_bootstrap.cc index 699039a..a306806 100644 --- a/kernel/boot/k_bootstrap.cc +++ b/kernel/boot/k_bootstrap.cc @@ -1,84 +1,84 @@ - -#include "k_bootstrap.h" -#include "k_main.h" -#include "hos_types.h" -#include "hos_defines.h" -#include "multiboot.h" -#include "sys/cpu.h" -#include "k_early_panic.h" -#include "mm/mm.h" -#include "lang/kio.h" -#include "isr/interrupts.h" - -#define DEBUG_LETTER(col,chr) *(u16_t *)(KERNEL_OFFSET + CONSOLE_MEMORY \ - + 160 * 8 + (col) * 2) \ - = 0x0700 | (chr) -extern "C" { - -u8_t bootstrap_stack[4096]; - -/************************************************************************** - * Multiboot header data block * - *************************************************************************/ -u32_t mb_header[] __attribute__ ((section (".multiboot_header") )) = { - MB_HEADER_MAGIC, /* magic */ - MB_HEADER_FLAGS, /* flags */ - -(MB_HEADER_MAGIC + MB_HEADER_FLAGS) /* checksum */ -}; - -/************************************************************************** - * This function is invoked to bootstrap the kernel. * - *************************************************************************/ -void k_bootstrap(mb_info_t * mb_info, u32_t mb_magic) -{ - DEBUG_LETTER(1, 'b'); - - if (mb_magic != MB_BOOTLOADER_MAGIC) - { - k_early_panic("Bad multiboot magic identifier!"); - } - - if ( ! (mb_info->flags & MB_BOOTLOADER_MMAP) ) - { - k_early_panic("No memory map provided by bootloader!"); - } - - for (mb_mmap_t * mmap = (mb_mmap_t *) (mb_info->mmap_addr + KERNEL_OFFSET), - * end = (mb_mmap_t *) ((u32_t)mmap + mb_info->mmap_length); - mmap < end; - mmap = (mb_mmap_t *) (((u32_t)mmap) + mmap->size + 4)) - { -// kprintf(" ** size: %d, type: %d ", mmap->size, mmap->type); - mm_record_mmap_entry(mmap); - } - - DEBUG_LETTER(2, 'c'); - - /* - * These functions could destroy the multiboot information block and - * associated structures, so we must be finished reading those structures - * before calling them. - */ - mm_bootstrap(); - DEBUG_LETTER(3, 'd'); - interrupts_bootstrap(); - DEBUG_LETTER(4, 'e'); - kio_bootstrap(); - DEBUG_LETTER(5, 'f'); - - /* begin using the permanent stack */ - write_esp(KERNEL_STACK_TOP); - k_main(); - - idle_loop(); -} - -void idle_loop() -{ - for (;;) - { - __asm__ __volatile__ ("hlt"); - } -} - -} /* extern "C" */ + +#include "k_bootstrap.h" +#include "k_main.h" +#include "hos_types.h" +#include "hos_defines.h" +#include "multiboot.h" +#include "sys/cpu.h" +#include "k_early_panic.h" +#include "mm/mm.h" +#include "lang/kio.h" +#include "isr/interrupts.h" + +#define DEBUG_LETTER(col,chr) *(u16_t *)(KERNEL_OFFSET + CONSOLE_MEMORY \ + + 160 * 8 + (col) * 2) \ + = 0x0700 | (chr) +extern "C" { + +u8_t bootstrap_stack[4096]; + +/************************************************************************** + * Multiboot header data block * + *************************************************************************/ +u32_t mb_header[] __attribute__ ((section (".multiboot_header") )) = { + MB_HEADER_MAGIC, /* magic */ + MB_HEADER_FLAGS, /* flags */ + -(MB_HEADER_MAGIC + MB_HEADER_FLAGS) /* checksum */ +}; + +/************************************************************************** + * This function is invoked to bootstrap the kernel. * + *************************************************************************/ +void k_bootstrap(mb_info_t * mb_info, u32_t mb_magic) +{ + DEBUG_LETTER(1, 'b'); + + if (mb_magic != MB_BOOTLOADER_MAGIC) + { + k_early_panic("Bad multiboot magic identifier!"); + } + + if ( ! (mb_info->flags & MB_BOOTLOADER_MMAP) ) + { + k_early_panic("No memory map provided by bootloader!"); + } + + for (mb_mmap_t * mmap = (mb_mmap_t *) (mb_info->mmap_addr + KERNEL_OFFSET), + * end = (mb_mmap_t *) ((u32_t)mmap + mb_info->mmap_length); + mmap < end; + mmap = (mb_mmap_t *) (((u32_t)mmap) + mmap->size + 4)) + { +// kprintf(" ** size: %d, type: %d ", mmap->size, mmap->type); + mm_record_mmap_entry(mmap); + } + + DEBUG_LETTER(2, 'c'); + + /* + * These functions could destroy the multiboot information block and + * associated structures, so we must be finished reading those structures + * before calling them. + */ + mm_bootstrap(); + DEBUG_LETTER(3, 'd'); + interrupts_bootstrap(); + DEBUG_LETTER(4, 'e'); + kio_bootstrap(); + DEBUG_LETTER(5, 'f'); + + /* begin using the permanent stack */ + write_esp(KERNEL_STACK_TOP); + k_main(); + + idle_loop(); +} + +void idle_loop() +{ + for (;;) + { + __asm__ __volatile__ ("hlt"); + } +} + +} /* extern "C" */ diff --git a/kernel/boot/k_early_panic.c b/kernel/boot/k_early_panic.c index ada7f05..a541c70 100644 --- a/kernel/boot/k_early_panic.c +++ b/kernel/boot/k_early_panic.c @@ -1,18 +1,18 @@ - -#include "hos_types.h" -#include "hos_defines.h" -#include "k_early_panic.h" - -void k_early_panic(const char * msg) -{ - char * dest = (char *) (CONSOLE_MEMORY + KERNEL_OFFSET); - while (*msg) - { - *dest++ = *msg++; - *dest++ = 0x04; /* red error message */ - } - - /* infinite loop */ - for (;;) - ; -} + +#include "hos_types.h" +#include "hos_defines.h" +#include "k_early_panic.h" + +void k_early_panic(const char * msg) +{ + char * dest = (char *) (CONSOLE_MEMORY + KERNEL_OFFSET); + while (*msg) + { + *dest++ = *msg++; + *dest++ = 0x04; /* red error message */ + } + + /* infinite loop */ + for (;;) + ; +} diff --git a/kernel/boot/k_early_panic.h b/kernel/boot/k_early_panic.h index 4963af0..feb4f31 100644 --- a/kernel/boot/k_early_panic.h +++ b/kernel/boot/k_early_panic.h @@ -1,15 +1,15 @@ - -#ifndef K_EARLY_PANIC_H -#define K_EARLY_PANIC_H - -#ifdef __cplusplus -extern "C" { -#endif - -void k_early_panic(const char * msg); - -#ifdef __cplusplus -} -#endif - -#endif + +#ifndef K_EARLY_PANIC_H +#define K_EARLY_PANIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +void k_early_panic(const char * msg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/include/hos_defines.h b/kernel/include/hos_defines.h index 2ad5a37..c853081 100644 --- a/kernel/include/hos_defines.h +++ b/kernel/include/hos_defines.h @@ -1,49 +1,49 @@ - -#ifndef HOS_DEFINES_H -#define HOS_DEFINES_H - -#include "hos_types.h" - -#define KERNEL_OFFSET 0x00000000 - -#define PAGE_LOG_SIZE 12 -#define PAGE_SIZE (1 << PAGE_LOG_SIZE) -#define PAGE_HIGH_MASK (0xFFFFFFFFu << PAGE_LOG_SIZE) -#define PAGE_LOW_MASK (0xFFFFFFFFu >> (32 - PAGE_LOG_SIZE)) - -#define CONSOLE_MEMORY 0xB8000 - -#define KERNEL_CODE (&_code) -#define KERNEL_DATA (&_data) -#define KERNEL_BSS (&_bss) -#define KERNEL_END (&_end) - -#define KERNEL_PHYSICAL_ADDRESS ((u32_t)(KERNEL_CODE - KERNEL_OFFSET)) -#define KERNEL_VIRTUAL_ADDRESS ((u32_t)KERNEL_CODE) -#define KERNEL_SIZE ((u32_t)(KERNEL_END - KERNEL_CODE)) - -#define KERNEL_STACK_TOP 0x20000000 - -#define KERNEL_TIMER_FREQ 1000 - -#define BUILD_BUG_ON(condition) \ - do { \ - typedef struct { int negative_width_test : ((condition)?-1:1); } \ - BUILD_BUG_ON_DUMMY_STRUCT; \ - } \ - while(0) - -#ifdef __cplusplus -extern "C" { -#endif - -extern u8_t _code; -extern u8_t _data; -extern u8_t _bss; -extern u8_t _end; - -#ifdef __cplusplus -} -#endif - -#endif + +#ifndef HOS_DEFINES_H +#define HOS_DEFINES_H + +#include "hos_types.h" + +#define KERNEL_OFFSET 0x00000000 + +#define PAGE_LOG_SIZE 12 +#define PAGE_SIZE (1 << PAGE_LOG_SIZE) +#define PAGE_HIGH_MASK (0xFFFFFFFFu << PAGE_LOG_SIZE) +#define PAGE_LOW_MASK (0xFFFFFFFFu >> (32 - PAGE_LOG_SIZE)) + +#define CONSOLE_MEMORY 0xB8000 + +#define KERNEL_CODE (&_code) +#define KERNEL_DATA (&_data) +#define KERNEL_BSS (&_bss) +#define KERNEL_END (&_end) + +#define KERNEL_PHYSICAL_ADDRESS ((u32_t)(KERNEL_CODE - KERNEL_OFFSET)) +#define KERNEL_VIRTUAL_ADDRESS ((u32_t)KERNEL_CODE) +#define KERNEL_SIZE ((u32_t)(KERNEL_END - KERNEL_CODE)) + +#define KERNEL_STACK_TOP 0x20000000 + +#define KERNEL_TIMER_FREQ 1000 + +#define BUILD_BUG_ON(condition) \ + do { \ + typedef struct { int negative_width_test : ((condition)?-1:1); } \ + BUILD_BUG_ON_DUMMY_STRUCT; \ + } \ + while(0) + +#ifdef __cplusplus +extern "C" { +#endif + +extern u8_t _code; +extern u8_t _data; +extern u8_t _bss; +extern u8_t _end; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/include/hos_types.h b/kernel/include/hos_types.h index c1fd456..076d91f 100644 --- a/kernel/include/hos_types.h +++ b/kernel/include/hos_types.h @@ -1,55 +1,55 @@ - -#ifndef HOS_TYPES_H -#define HOS_TYPES_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned char u8_t; -typedef signed char s8_t; -typedef unsigned short u16_t; -typedef signed short s16_t; -typedef unsigned int u32_t; -typedef signed int s32_t; -typedef unsigned long long u64_t; -typedef signed long long s64_t; - -typedef struct -{ - u32_t gs; - u32_t fs; - u32_t es; - u32_t ds; - - u32_t edi; - u32_t esi; - u32_t ebp; - u32_t esp_junk; /* the esp value saved by 'pusha' */ - u32_t ebx; - u32_t edx; - u32_t ecx; - u32_t eax; - - u32_t error; /* valid on exceptions 8, 10-14 */ - - u32_t eip; - u32_t cs; - u32_t eflags; - u32_t esp; /* present if privilege transition */ - u32_t ss; -} int_stack_t; - -typedef struct -{ - u16_t limit; - u32_t base; -} __attribute__ ((packed)) gdtr_t; - -typedef gdtr_t idtr_t; - -#ifdef __cplusplus -} -#endif - -#endif + +#ifndef HOS_TYPES_H +#define HOS_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned int u32_t; +typedef signed int s32_t; +typedef unsigned long long u64_t; +typedef signed long long s64_t; + +typedef struct +{ + u32_t gs; + u32_t fs; + u32_t es; + u32_t ds; + + u32_t edi; + u32_t esi; + u32_t ebp; + u32_t esp_junk; /* the esp value saved by 'pusha' */ + u32_t ebx; + u32_t edx; + u32_t ecx; + u32_t eax; + + u32_t error; /* valid on exceptions 8, 10-14 */ + + u32_t eip; + u32_t cs; + u32_t eflags; + u32_t esp; /* present if privilege transition */ + u32_t ss; +} int_stack_t; + +typedef struct +{ + u16_t limit; + u32_t base; +} __attribute__ ((packed)) gdtr_t; + +typedef gdtr_t idtr_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/include/portio.h b/kernel/include/portio.h index 9a9f762..2ef84d1 100644 --- a/kernel/include/portio.h +++ b/kernel/include/portio.h @@ -1,37 +1,37 @@ - -#ifndef PORTIO_H -#define PORTIO_H - -#include "hos_types.h" - -#define outportb(port, val) \ - __asm__ __volatile__ ("outb %%al, %%dx" : : "a" (val), "d" (port)); - -#define outportw(port, val) \ - __asm__ __volatile__ ("outw %%ax, %%dx" : : "a" (val), "d" (port)); - -#define outportd(port, val) \ - __asm__ __volatile__ ("outl %%eax, %%dx" : : "a" (val), "d" (port)); - -static inline u8_t inportb(u16_t port) -{ - u8_t val; - __asm__ __volatile__ ("inb %%dx, %%al" : "=a" (val) : "d" (port)); - return val; -} - -static inline u16_t inportw(u16_t port) -{ - u16_t val; - __asm__ __volatile__ ("inw %%dx, %%al" : "=a" (val) : "d" (port)); - return val; -} - -static inline u32_t inportd(u16_t port) -{ - u32_t val; - __asm__ __volatile__ ("inl %%dx, %%al" : "=a" (val) : "d" (port)); - return val; -} - -#endif + +#ifndef PORTIO_H +#define PORTIO_H + +#include "hos_types.h" + +#define outportb(port, val) \ + __asm__ __volatile__ ("outb %%al, %%dx" : : "a" (val), "d" (port)); + +#define outportw(port, val) \ + __asm__ __volatile__ ("outw %%ax, %%dx" : : "a" (val), "d" (port)); + +#define outportd(port, val) \ + __asm__ __volatile__ ("outl %%eax, %%dx" : : "a" (val), "d" (port)); + +static inline u8_t inportb(u16_t port) +{ + u8_t val; + __asm__ __volatile__ ("inb %%dx, %%al" : "=a" (val) : "d" (port)); + return val; +} + +static inline u16_t inportw(u16_t port) +{ + u16_t val; + __asm__ __volatile__ ("inw %%dx, %%al" : "=a" (val) : "d" (port)); + return val; +} + +static inline u32_t inportd(u16_t port) +{ + u32_t val; + __asm__ __volatile__ ("inl %%dx, %%al" : "=a" (val) : "d" (port)); + return val; +} + +#endif diff --git a/kernel/isr/interrupts.cc b/kernel/isr/interrupts.cc index f35b190..6c301df 100644 --- a/kernel/isr/interrupts.cc +++ b/kernel/isr/interrupts.cc @@ -1,107 +1,107 @@ - -#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" { - -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; - } -} - -} /* extern "C" */ - -void interrupts_bootstrap() -{ - u32_t idt_base = mm_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)"); -} + +#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" { + +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; + } +} + +} /* extern "C" */ + +void interrupts_bootstrap() +{ + u32_t idt_base = mm_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 93eb147..9718d6e 100644 --- a/kernel/isr/interrupts.h +++ b/kernel/isr/interrupts.h @@ -1,79 +1,79 @@ - -#ifndef INTERRUPTS_H -#define INTERRUPTS_H - -#ifdef __cplusplus -extern "C" { -#endif - -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 + +#ifndef INTERRUPTS_H +#define INTERRUPTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +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 d57917c..e91a7b4 100644 --- a/kernel/isr/isr.asm +++ b/kernel/isr/isr.asm @@ -1,56 +1,56 @@ - -; C ISR routine -[extern isr] - - -; Macro for creating a single ISR label -; We need to push a junk value on the stack first -; if the interrupt number is not 8 or 10-14. -; This is to properly align the stack for both exceptions -; having and not having error codes. -%macro isr_label 1 -[global isr_%1] -isr_%1: - %if ( (%1 != 8) && (%1 < 10 || %1 > 14) ) - push eax ; junk value to take error code stack space - %endif - pusha ; eax, ecx, edx, ebx, esp, ebp, esi, edi - mov al, %1 ; save interrupt number in al - %if ($ - isr_common) < 127 ; do a short jump and save 3 bytes if we can - jmp short isr_common - %else - jmp isr_common - %endif -%endmacro - - -; The common ISR routine -isr_common: - push ds - push es - push fs - push gs - - push esp ; pointer to interrupt stack - push eax ; interrupt number - call isr - pop eax ; restore stack pointer (this is shorter - pop eax ; than "add esp, 8" and "lea esp, [esp+8]") - - pop gs - pop fs - pop es - pop ds - popa ; edi, esi, ebp, , ebx, edx, ecx, eax - lea esp, [esp+4] ; bypass error code - - iret - - -; Loop to create all of our ISR entry points -%assign i 0 -%rep 50 - isr_label i - %assign i i+1 -%endrep - + +; C ISR routine +[extern isr] + + +; Macro for creating a single ISR label +; We need to push a junk value on the stack first +; if the interrupt number is not 8 or 10-14. +; This is to properly align the stack for both exceptions +; having and not having error codes. +%macro isr_label 1 +[global isr_%1] +isr_%1: + %if ( (%1 != 8) && (%1 < 10 || %1 > 14) ) + push eax ; junk value to take error code stack space + %endif + pusha ; eax, ecx, edx, ebx, esp, ebp, esi, edi + mov al, %1 ; save interrupt number in al + %if ($ - isr_common) < 127 ; do a short jump and save 3 bytes if we can + jmp short isr_common + %else + jmp isr_common + %endif +%endmacro + + +; The common ISR routine +isr_common: + push ds + push es + push fs + push gs + + push esp ; pointer to interrupt stack + push eax ; interrupt number + call isr + pop eax ; restore stack pointer (this is shorter + pop eax ; than "add esp, 8" and "lea esp, [esp+8]") + + pop gs + pop fs + pop es + pop ds + popa ; edi, esi, ebp, , ebx, edx, ecx, eax + lea esp, [esp+4] ; bypass error code + + iret + + +; Loop to create all of our ISR entry points +%assign i 0 +%rep 50 + isr_label i + %assign i i+1 +%endrep + diff --git a/kernel/lang/kio.cc b/kernel/lang/kio.cc index 9edaefd..3715226 100644 --- a/kernel/lang/kio.cc +++ b/kernel/lang/kio.cc @@ -1,317 +1,317 @@ - -#include "hos_types.h" -#include "hos_defines.h" -#include "kio.h" -#include "string.h" -#include "portio.h" - -#include -#include /* va_*() */ - -static void fmt_d2a(char * buf, int val); -static void fmt_u2a(char * buf, unsigned int val); -static void fmt_ll2a(char * buf, long long val); -static void fmt_ull2a(char * buf, unsigned long long val); -static void fmt_x2a(char * buf, unsigned int val); -static void fmt_xl2a(char * buf, unsigned long long val); -static void fmt_o2a(char * buf, unsigned int val); - -static int cursor_x, cursor_y; - -static void writeCursorPosition(int x, int y) -{ - u16_t pos = 80 * y + x; - outportb(0x3D4, 0x0E); - outportb(0x3D5, pos >> 8); - outportb(0x3D4, 0x0F); - outportb(0x3D5, pos); -} - -extern "C" { - -void kio_bootstrap() -{ - cursor_x = 0; - cursor_y = 9; - writeCursorPosition(cursor_x, cursor_y); -} - -void kprintf(const char * fmt, ...) -{ - va_list args; - va_start(args, fmt); - - kvprintf(fmt, args); - - va_end(args); -} - -void kvprintf(const char * fmt, va_list args) -{ - char tmpbuf[25]; - for ( ; *fmt; fmt++) - { - if (*fmt == '%') - { - fmt++; - if (*fmt) - { - int width = 0; - char pad_char = ' '; - bool pad_right = false; - if (*fmt == '0') - { - pad_char = '0'; - fmt++; - } - else if (*fmt == '-') - { - pad_right = true; - fmt++; - } - for ( ; '0' <= *fmt && *fmt <= '9'; fmt++) - { - if (width == 0) - { - width = *fmt - '0'; - } - else - { - width *= 10; - width += *fmt - '0'; - } - } - switch (*fmt) - { - case 'c': - kputc(va_arg(args, int)); - break; - case 'd': - fmt_d2a(tmpbuf, va_arg(args, int)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case 'l': - fmt_ll2a(tmpbuf, va_arg(args, long long)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case 'L': - fmt_ull2a(tmpbuf, va_arg(args, unsigned long long)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case 'o': - fmt_o2a(tmpbuf, va_arg(args, unsigned int)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case 's': - kputs_pad(va_arg(args, char *), - width, pad_char, pad_right); - break; - case 'u': - fmt_u2a(tmpbuf, va_arg(args, unsigned int)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case 'x': - fmt_x2a(tmpbuf, va_arg(args, unsigned int)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case 'X': - fmt_xl2a(tmpbuf, va_arg(args, unsigned long long)); - kputs_pad(tmpbuf, width, pad_char, pad_right); - break; - case '%': - kputc('%'); - break; - } - } - } - else - { - kputc(*fmt); - } - if (!*fmt) - { - break; - } - } -} - -void kputc(char c) -{ - u16_t * console_memory = (u16_t *) CONSOLE_MEMORY; - console_memory += 80 * cursor_y + cursor_x; - switch (c) - { - case '\t': - { - int to_advance = 8 - (cursor_x & 0x3); - while (to_advance--) - { - *console_memory++ = 0x0720; - } - } - break; - case '\n': - cursor_x = 0; - cursor_y++; - break; - default: - *console_memory = 0x0700 | (c & 0xFF); - cursor_x++; - break; - } - if (cursor_x >= 80) - { - cursor_x = 0; - cursor_y++; - } - if (cursor_y >= 25) - { - memcpy((u8_t *) CONSOLE_MEMORY, - (u8_t *) (CONSOLE_MEMORY + 80 * 2), - 2 * 80 * 24); - memsetw((u16_t *) (CONSOLE_MEMORY + 2 * 80 * 24), 0x0720, 80); - cursor_y = 24; - } - writeCursorPosition(cursor_x, cursor_y); -} - -void kputs(const char * s) -{ - while (*s) - { - kputc(*s); - s++; - } -} - -void kputs_pad(const char * s, int width, char pad_char, bool pad_right) -{ - int len = strlen(s); - if (pad_right) - { - kputs(s); - } - int num_pad_chars = width - len; - for (int i = 0; i < num_pad_chars; i++) - { - kputc(pad_char); - } - if (!pad_right) - { - kputs(s); - } -} - -} /* extern "C" */ - -static void fmt_d2a(char * buf, int val) -{ - if (val < 0) - { - *buf++ = '-'; - val = -val; - } - fmt_u2a(buf, (unsigned int) val); -} - -static void fmt_u2a(char * buf, unsigned int val) -{ - bool printing = false; - for (unsigned int div = 1000000000; div >= 1; div /= 10) - { - unsigned int n = val / div; - if (n || div == 1) - { - printing = true; - } - if (printing) - { - *buf++ = '0' + n; - } - val -= n * div; - } - *buf = '\0'; -} - -static void fmt_ll2a(char * buf, long long val) -{ - if (val < 0) - { - *buf++ = '-'; - val = -val; - } - fmt_ull2a(buf, (unsigned long long) val); -} - -static void fmt_ull2a(char * buf, unsigned long long val) -{ - bool printing = false; - for (unsigned long long div = 10000000000000000000ull; div >= 1; div /= 10) - { - unsigned long long n = val / div; - if (n || div == 1) - { - printing = true; - } - if (printing) - { - *buf++ = '0' + n; - } - val -= n * div; - } - *buf = '\0'; -} - -static void fmt_x2a(char * buf, unsigned int val) -{ - bool printing = false; - for (int s = 28; s >= 0; s -= 4) - { - unsigned int n = (val >> s) & 0xF; - if (n || s == 0) - { - printing = true; - } - if (printing) - { - *buf++ = "0123456789abcdef"[n]; - } - } - *buf = '\0'; -} - -static void fmt_xl2a(char * buf, unsigned long long val) -{ - bool printing = false; - for (int s = 60; s >= 0; s -= 4) - { - unsigned int n = (val >> s) & 0xF; - if (n || s == 0) - { - printing = true; - } - if (printing) - { - *buf++ = "0123456789abcdef"[n]; - } - } - *buf = '\0'; -} - -static void fmt_o2a(char * buf, unsigned int val) -{ - bool printing = false; - for (int s = 30; s >= 0; s -= 3) - { - unsigned int n = (val >> s) & 0x7; - if (n || s == 0) - { - printing = true; - } - if (printing) - { - *buf++ = "01234567"[n]; - } - } - *buf = '\0'; -} + +#include "hos_types.h" +#include "hos_defines.h" +#include "kio.h" +#include "string.h" +#include "portio.h" + +#include +#include /* va_*() */ + +static void fmt_d2a(char * buf, int val); +static void fmt_u2a(char * buf, unsigned int val); +static void fmt_ll2a(char * buf, long long val); +static void fmt_ull2a(char * buf, unsigned long long val); +static void fmt_x2a(char * buf, unsigned int val); +static void fmt_xl2a(char * buf, unsigned long long val); +static void fmt_o2a(char * buf, unsigned int val); + +static int cursor_x, cursor_y; + +static void writeCursorPosition(int x, int y) +{ + u16_t pos = 80 * y + x; + outportb(0x3D4, 0x0E); + outportb(0x3D5, pos >> 8); + outportb(0x3D4, 0x0F); + outportb(0x3D5, pos); +} + +extern "C" { + +void kio_bootstrap() +{ + cursor_x = 0; + cursor_y = 9; + writeCursorPosition(cursor_x, cursor_y); +} + +void kprintf(const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + + kvprintf(fmt, args); + + va_end(args); +} + +void kvprintf(const char * fmt, va_list args) +{ + char tmpbuf[25]; + for ( ; *fmt; fmt++) + { + if (*fmt == '%') + { + fmt++; + if (*fmt) + { + int width = 0; + char pad_char = ' '; + bool pad_right = false; + if (*fmt == '0') + { + pad_char = '0'; + fmt++; + } + else if (*fmt == '-') + { + pad_right = true; + fmt++; + } + for ( ; '0' <= *fmt && *fmt <= '9'; fmt++) + { + if (width == 0) + { + width = *fmt - '0'; + } + else + { + width *= 10; + width += *fmt - '0'; + } + } + switch (*fmt) + { + case 'c': + kputc(va_arg(args, int)); + break; + case 'd': + fmt_d2a(tmpbuf, va_arg(args, int)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case 'l': + fmt_ll2a(tmpbuf, va_arg(args, long long)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case 'L': + fmt_ull2a(tmpbuf, va_arg(args, unsigned long long)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case 'o': + fmt_o2a(tmpbuf, va_arg(args, unsigned int)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case 's': + kputs_pad(va_arg(args, char *), + width, pad_char, pad_right); + break; + case 'u': + fmt_u2a(tmpbuf, va_arg(args, unsigned int)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case 'x': + fmt_x2a(tmpbuf, va_arg(args, unsigned int)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case 'X': + fmt_xl2a(tmpbuf, va_arg(args, unsigned long long)); + kputs_pad(tmpbuf, width, pad_char, pad_right); + break; + case '%': + kputc('%'); + break; + } + } + } + else + { + kputc(*fmt); + } + if (!*fmt) + { + break; + } + } +} + +void kputc(char c) +{ + u16_t * console_memory = (u16_t *) CONSOLE_MEMORY; + console_memory += 80 * cursor_y + cursor_x; + switch (c) + { + case '\t': + { + int to_advance = 8 - (cursor_x & 0x3); + while (to_advance--) + { + *console_memory++ = 0x0720; + } + } + break; + case '\n': + cursor_x = 0; + cursor_y++; + break; + default: + *console_memory = 0x0700 | (c & 0xFF); + cursor_x++; + break; + } + if (cursor_x >= 80) + { + cursor_x = 0; + cursor_y++; + } + if (cursor_y >= 25) + { + memcpy((u8_t *) CONSOLE_MEMORY, + (u8_t *) (CONSOLE_MEMORY + 80 * 2), + 2 * 80 * 24); + memsetw((u16_t *) (CONSOLE_MEMORY + 2 * 80 * 24), 0x0720, 80); + cursor_y = 24; + } + writeCursorPosition(cursor_x, cursor_y); +} + +void kputs(const char * s) +{ + while (*s) + { + kputc(*s); + s++; + } +} + +void kputs_pad(const char * s, int width, char pad_char, bool pad_right) +{ + int len = strlen(s); + if (pad_right) + { + kputs(s); + } + int num_pad_chars = width - len; + for (int i = 0; i < num_pad_chars; i++) + { + kputc(pad_char); + } + if (!pad_right) + { + kputs(s); + } +} + +} /* extern "C" */ + +static void fmt_d2a(char * buf, int val) +{ + if (val < 0) + { + *buf++ = '-'; + val = -val; + } + fmt_u2a(buf, (unsigned int) val); +} + +static void fmt_u2a(char * buf, unsigned int val) +{ + bool printing = false; + for (unsigned int div = 1000000000; div >= 1; div /= 10) + { + unsigned int n = val / div; + if (n || div == 1) + { + printing = true; + } + if (printing) + { + *buf++ = '0' + n; + } + val -= n * div; + } + *buf = '\0'; +} + +static void fmt_ll2a(char * buf, long long val) +{ + if (val < 0) + { + *buf++ = '-'; + val = -val; + } + fmt_ull2a(buf, (unsigned long long) val); +} + +static void fmt_ull2a(char * buf, unsigned long long val) +{ + bool printing = false; + for (unsigned long long div = 10000000000000000000ull; div >= 1; div /= 10) + { + unsigned long long n = val / div; + if (n || div == 1) + { + printing = true; + } + if (printing) + { + *buf++ = '0' + n; + } + val -= n * div; + } + *buf = '\0'; +} + +static void fmt_x2a(char * buf, unsigned int val) +{ + bool printing = false; + for (int s = 28; s >= 0; s -= 4) + { + unsigned int n = (val >> s) & 0xF; + if (n || s == 0) + { + printing = true; + } + if (printing) + { + *buf++ = "0123456789abcdef"[n]; + } + } + *buf = '\0'; +} + +static void fmt_xl2a(char * buf, unsigned long long val) +{ + bool printing = false; + for (int s = 60; s >= 0; s -= 4) + { + unsigned int n = (val >> s) & 0xF; + if (n || s == 0) + { + printing = true; + } + if (printing) + { + *buf++ = "0123456789abcdef"[n]; + } + } + *buf = '\0'; +} + +static void fmt_o2a(char * buf, unsigned int val) +{ + bool printing = false; + for (int s = 30; s >= 0; s -= 3) + { + unsigned int n = (val >> s) & 0x7; + if (n || s == 0) + { + printing = true; + } + if (printing) + { + *buf++ = "01234567"[n]; + } + } + *buf = '\0'; +} diff --git a/kernel/lang/kio.h b/kernel/lang/kio.h index 5e577a6..ae86048 100644 --- a/kernel/lang/kio.h +++ b/kernel/lang/kio.h @@ -1,27 +1,27 @@ - -#ifndef KIO_H -#define KIO_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void kio_bootstrap(); - -void kprintf(const char * fmt, ...); - -void kvprintf(const char * fmt, va_list args); - -void kputc(char c); - -void kputs(const char * s); - -void kputs_pad(const char * s, int width, char pad_char, bool pad_right); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif + +#ifndef KIO_H +#define KIO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void kio_bootstrap(); + +void kprintf(const char * fmt, ...); + +void kvprintf(const char * fmt, va_list args); + +void kputc(char c); + +void kputs(const char * s); + +void kputs_pad(const char * s, int width, char pad_char, bool pad_right); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/kernel/lang/string.cc b/kernel/lang/string.cc index ec0a726..a88e697 100644 --- a/kernel/lang/string.cc +++ b/kernel/lang/string.cc @@ -1,73 +1,73 @@ - -#include "string.h" - -extern "C" { - -void strcpy(char * dst, const char * src) -{ - while (*src) - { - *dst++ = *src++; - } - *dst = '\0'; -} - -u32_t strlen(const char * s) -{ - u32_t len = 0; - while (*s++) - { - len++; - } - return len; -} - -void memcpy(u8_t * dst, u8_t * src, u32_t size) -{ - for (u32_t n = 0; n < size; n++) - { - *dst++ = *src++; - } -} - -void memcpyw(u16_t * dst, u16_t * src, u32_t size) -{ - for (u32_t n = 0; n < size; n++) - { - *dst++ = *src++; - } -} - -void memcpyd(u32_t * dst, u32_t * src, u32_t size) -{ - for (u32_t n = 0; n < size; n++) - { - *dst++ = *src++; - } -} - -void memset(u8_t * dst, u8_t val, u32_t size) -{ - for (u32_t n = 0; n < size; n++) - { - *dst++ = val; - } -} - -void memsetw(u16_t * dst, u16_t val, u32_t size) -{ - for (u32_t n = 0; n < size; n++) - { - *dst++ = val; - } -} - -void memsetd(u32_t * dst, u32_t val, u32_t size) -{ - for (u32_t n = 0; n < size; n++) - { - *dst++ = val; - } -} - -} /* extern "C" */ + +#include "string.h" + +extern "C" { + +void strcpy(char * dst, const char * src) +{ + while (*src) + { + *dst++ = *src++; + } + *dst = '\0'; +} + +u32_t strlen(const char * s) +{ + u32_t len = 0; + while (*s++) + { + len++; + } + return len; +} + +void memcpy(u8_t * dst, u8_t * src, u32_t size) +{ + for (u32_t n = 0; n < size; n++) + { + *dst++ = *src++; + } +} + +void memcpyw(u16_t * dst, u16_t * src, u32_t size) +{ + for (u32_t n = 0; n < size; n++) + { + *dst++ = *src++; + } +} + +void memcpyd(u32_t * dst, u32_t * src, u32_t size) +{ + for (u32_t n = 0; n < size; n++) + { + *dst++ = *src++; + } +} + +void memset(u8_t * dst, u8_t val, u32_t size) +{ + for (u32_t n = 0; n < size; n++) + { + *dst++ = val; + } +} + +void memsetw(u16_t * dst, u16_t val, u32_t size) +{ + for (u32_t n = 0; n < size; n++) + { + *dst++ = val; + } +} + +void memsetd(u32_t * dst, u32_t val, u32_t size) +{ + for (u32_t n = 0; n < size; n++) + { + *dst++ = val; + } +} + +} /* extern "C" */ diff --git a/kernel/lang/string.h b/kernel/lang/string.h index 12c25c0..7d54e5b 100644 --- a/kernel/lang/string.h +++ b/kernel/lang/string.h @@ -1,27 +1,27 @@ - -#ifndef STRING_H -#define STRING_H - -#include "hos_defines.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void strcpy(char * dst, const char * src); - -u32_t strlen(const char * s); - -void memcpy(u8_t * dst, u8_t * src, u32_t size); -void memcpyw(u16_t * dst, u16_t * src, u32_t size); -void memcpyd(u32_t * dst, u32_t * src, u32_t size); - -void memset(u8_t * dst, u8_t val, u32_t size); -void memsetw(u16_t * dst, u16_t val, u32_t size); -void memsetd(u32_t * dst, u32_t val, u32_t size); - -#ifdef __cplusplus -} -#endif - -#endif + +#ifndef STRING_H +#define STRING_H + +#include "hos_defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void strcpy(char * dst, const char * src); + +u32_t strlen(const char * s); + +void memcpy(u8_t * dst, u8_t * src, u32_t size); +void memcpyw(u16_t * dst, u16_t * src, u32_t size); +void memcpyd(u32_t * dst, u32_t * src, u32_t size); + +void memset(u8_t * dst, u8_t val, u32_t size); +void memsetw(u16_t * dst, u16_t val, u32_t size); +void memsetd(u32_t * dst, u32_t val, u32_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/link.ld b/kernel/link.ld index 299ac63..51bc925 100644 --- a/kernel/link.ld +++ b/kernel/link.ld @@ -1,34 +1,34 @@ -OUTPUT_FORMAT(elf32-i386) -ENTRY(start) -virt = 0x00100000; -phys = 0x00100000; -SECTIONS -{ - .text virt : AT(phys) { - code = .; _code = .; __code = .; - *(.multiboot_header*) - *(.text*) - *(.gnu.linkonce*) - . = ALIGN(4096); - } - .rodata : { - *(.rodata*) - . = ALIGN(4096); - } - .other : { - *(.eh_*) - *(.rel*) - . = ALIGN(4096); - } - .data : { - data = .; _data = .; __data = .; - *(.data*) - . = ALIGN(4096); - } - .bss : { - bss = .; _bss = .; __bss = .; - *(.bss*) - . = ALIGN(4096); - } - end = .; _end = .; __end = .; -} +OUTPUT_FORMAT(elf32-i386) +ENTRY(start) +virt = 0x00100000; +phys = 0x00100000; +SECTIONS +{ + .text virt : AT(phys) { + code = .; _code = .; __code = .; + *(.multiboot_header*) + *(.text*) + *(.gnu.linkonce*) + . = ALIGN(4096); + } + .rodata : { + *(.rodata*) + . = ALIGN(4096); + } + .other : { + *(.eh_*) + *(.rel*) + . = ALIGN(4096); + } + .data : { + data = .; _data = .; __data = .; + *(.data*) + . = ALIGN(4096); + } + .bss : { + bss = .; _bss = .; __bss = .; + *(.bss*) + . = ALIGN(4096); + } + end = .; _end = .; __end = .; +} diff --git a/kernel/mm/mm.cc b/kernel/mm/mm.cc index 93956b3..6e5a894 100644 --- a/kernel/mm/mm.cc +++ b/kernel/mm/mm.cc @@ -1,320 +1,320 @@ - -#include - -#include "mm.h" -#include "stack.h" -#include "boot/k_early_panic.h" -#include "lang/string.h" -#include "lang/kio.h" -#include "sys/cpu.h" - -#define MM_MAX_MMAP_ENTRIES 64 - -static pagedirectory_entry_t * page_directory; -static mm_mem_range_t mm_mmap_entries[MM_MAX_MMAP_ENTRIES]; -static int mm_mmap_num_entries = 0; -static int mm_num_free_pages = 0; -static int mm_num_total_pages = 0; -gdtr_t mm_gdtr; -static u64_t * mm_gdt; -static u32_t mm_heap_base; - -/* physical addresses of page allocation pages to map in before the heap */ -static u32_t page_alloc_page_numbers[1025]; /* supports 4GB physical memory */ -static u32_t num_page_alloc_pages = 0; -static mm_page_alloc_page_t * current_page_alloc_page = NULL; -static u32_t page_alloc_page_index = 0; -static mm_page_alloc_page_t * page_alloc_pages; - -/************************************************************************** - * Internal Functions * - *************************************************************************/ -static void record_phys_page(u32_t base_address); - -/************************************************************************** - * This function is run in segmented memory before paging is in effect. * - *************************************************************************/ -void mm_record_mmap_entry(mb_mmap_t * mmap) -{ - if (mm_mmap_num_entries < MM_MAX_MMAP_ENTRIES) - { - if (mmap->type == MB_MMAP_TYPE_RAM) - { - mm_mmap_entries[mm_mmap_num_entries].base = mmap->base; - mm_mmap_entries[mm_mmap_num_entries].length = mmap->length; - mm_mmap_num_entries++; - } - } - else - { - k_early_panic("Too many mmap_entries!"); - } -} - -/************************************************************************** - * This function is run in segmented memory before paging is in effect. * - * It is run after the bootloader information has been read, so we can * - * overwrite that memory now. * - *************************************************************************/ -void mm_bootstrap() -{ - u32_t max_ram_address = KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE - 1; - /* this function requires a big enough initial stack to run */ - BUILD_BUG_ON((STACK_INITIAL_SIZE * PAGE_SIZE) < 8000); - - /* check that a mm_page_alloc_page_t fits exactly in a page */ - BUILD_BUG_ON(sizeof(mm_page_alloc_page_t) != PAGE_SIZE); - - if (mm_mmap_num_entries < 1) - { - k_early_panic("No mmap entries read from bootloader!"); - } - - mm_heap_base = (u32_t) KERNEL_END; - page_alloc_pages = (mm_page_alloc_page_t *) mm_heap_base; - - for (int mmap_idx = 0; mmap_idx < mm_mmap_num_entries; mmap_idx++) - { - u32_t base_address = mm_mmap_entries[mmap_idx].base; - u32_t address_limit = base_address + mm_mmap_entries[mmap_idx].length; - - if (base_address & PAGE_LOW_MASK) - { - /* start of this mmap range is not page-aligned */ - base_address = (base_address & PAGE_HIGH_MASK) + PAGE_SIZE; - } - if (address_limit & PAGE_LOW_MASK) - { - /* end of this mmap range is not page-aligned */ - address_limit &= PAGE_HIGH_MASK; - } - - /* record the highest RAM address found */ - if ((address_limit - 1) > max_ram_address) - { - max_ram_address = (address_limit - 1); - } - - /* - * loop through every page in the mmap range and add - * pages into the free page linked list - */ - for (; base_address < address_limit; base_address += PAGE_SIZE) - { - /* check to make sure the page doesn't overlap the kernel */ - if ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS - || base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE ) - { - record_phys_page(base_address); - mm_num_free_pages++; - } - mm_num_total_pages++; - } - } - - for (unsigned int i = 0; i < num_page_alloc_pages; i++) - { - mm_early_map(mm_heap_base, page_alloc_page_numbers[i], 0, 1); - current_page_alloc_page = (mm_page_alloc_page_t *) mm_heap_base; - /* move the heap back to after the page allocation pages */ - mm_heap_base += PAGE_SIZE; - } - - if (mm_num_free_pages < 10) - { - k_early_panic("Not enough free pages of RAM!"); - } - - /* ok, now mm_page_alloc() should be functional */ - - /* allocate the page directory */ - u32_t page_directory_phys = mm_page_alloc(); - page_directory = (pagedirectory_entry_t *) page_directory_phys; - pagedirectory_entry_t * page_dir_virt = - (pagedirectory_entry_t *) (page_directory_phys + KERNEL_OFFSET); - - /* Clear the page directory */ - for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++) - { - page_dir_virt[i] = 0; - } - - /* now map the kernel's virtual address space into RAM */ - for (u32_t page_base = KERNEL_VIRTUAL_ADDRESS; - page_base < KERNEL_VIRTUAL_ADDRESS + KERNEL_SIZE; - page_base += PAGE_SIZE) - { - /* map page_base to page_base - KERNEL_OFFSET */ - mm_early_map(page_base, page_base - KERNEL_OFFSET, 0, 1); - } - - /* set up the global descriptor table */ - u32_t gdt_base = mm_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); /* 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; - - __asm__ __volatile__ ( - "lgdt (mm_gdtr);\n" - "jmp $0x08, $42f;\n" - "42:\n" - "mov $0x10, %%cx\n" - "mov %%cx, %%ss\n" - "mov %%cx, %%ds\n" - "mov %%cx, %%es\n" - "mov %%cx, %%fs\n" - "mov %%cx, %%gs\n" - : /* no outputs */ - : /* no inputs */ - : "ecx"); - - /* set the page directory base register */ - write_cr3(page_directory); - - /* turn on paging */ - write_cr0(read_cr0() | (1 << 31)); - - stack_bootstrap(); -} - -static void record_phys_page(u32_t base_address) -{ - if (page_alloc_page_index == 0) - { - /* allocate a new page alloc page */ - mm_page_alloc_page_t * old_page_alloc_page = current_page_alloc_page; - current_page_alloc_page = (mm_page_alloc_page_t *) - (base_address + KERNEL_OFFSET); - current_page_alloc_page->next = old_page_alloc_page; - page_alloc_page_index = - sizeof(current_page_alloc_page->pages) - / sizeof(current_page_alloc_page->pages[0]) - 1; - page_alloc_page_numbers[num_page_alloc_pages++] = base_address; - } - else - { - current_page_alloc_page->pages[page_alloc_page_index--] = base_address; - } -} - -/************************************************************************** - * Map virtual_address to physical_address. * - * Both addresses should be page-aligned. * - * This 'early' version can be used during segmented bootstrapping * - *************************************************************************/ -int mm_early_map(u32_t virtual_address, u32_t physical_address, - u32_t user_mode, u32_t writable) -{ - u32_t directory_index = (virtual_address >> 22) & 0x3FF; - u32_t table_index = (virtual_address >> 12) & 0x3FF; - pagedirectory_entry_t * page_dir = page_directory; - page_dir = (pagedirectory_entry_t *)((u32_t)page_dir + KERNEL_OFFSET); - - if (page_dir[directory_index] == 0) - { - /* allocate a new page table */ - u32_t page_table_address = mm_page_alloc(); - if (page_table_address == 0) - { - return 0; - } - page_dir[directory_index] = page_table_address - | 0x1 << 2 /* PTs can be user mode */ - | 0x1 << 1 /* writable */ - | 0x1; /* present */ - } - u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK; - - u32_t * page_table = (u32_t *) page_table_address; - page_table = (u32_t *)((u32_t)page_table + (u32_t)KERNEL_OFFSET); - - page_table[table_index] = (physical_address & PAGE_HIGH_MASK) - | (user_mode & 0x1) << 2 - | (writable & 0x1) << 1 - | 0x1; /* present */ - - return 1; -} - -/************************************************************************** - * Map virtual_address to physical_address. * - * Both addresses should be page-aligned. * - *************************************************************************/ -int mm_map(u32_t virtual_address, u32_t physical_address, - u32_t user_mode, u32_t writable) -{ - u32_t directory_index = (virtual_address >> 22) & 0x3FF; - u32_t table_index = (virtual_address >> 12) & 0x3FF; - pagedirectory_entry_t * page_dir = page_directory; - - if (page_dir[directory_index] == 0) - { - /* allocate a new page table */ - u32_t page_table_address = mm_page_alloc(); - if (page_table_address == 0) - { - return 0; - } - page_dir[directory_index] = page_table_address - | 0x1 << 2 /* PTs can be user mode */ - | 0x1 << 1 /* writable */ - | 0x1; /* present */ - } - u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK; - - u32_t * page_table = (u32_t *) page_table_address; - - page_table[table_index] = (physical_address & PAGE_HIGH_MASK) - | (user_mode & 0x1) << 2 - | (writable & 0x1) << 1 - | 0x1; /* present */ - - return 1; -} - -/************************************************************************** - * Returns the physical base address of a page in RAM * - * or 0 if no pages were available * - *************************************************************************/ -u32_t mm_page_alloc() -{ - u32_t page_address = 0; - if (current_page_alloc_page != NULL) - { - if (page_alloc_page_index == sizeof(current_page_alloc_page->pages) - / sizeof(current_page_alloc_page->pages[0]) - 1) - { - page_address = ((u32_t) current_page_alloc_page) - KERNEL_OFFSET; - current_page_alloc_page = current_page_alloc_page->next; - page_alloc_page_index = 0; - } - else - { - page_alloc_page_index++; - page_address = - current_page_alloc_page->pages[page_alloc_page_index]; - } - mm_num_free_pages--; - } - return page_address; -} - -void mm_print_memory_map() -{ - kprintf("Bootloader provided memory map:\n"); - kprintf(" Base Address Length\n"); - for (int i = 0; i < mm_mmap_num_entries; i++) - { - kprintf(" 0x%016X 0x%016X (%l bytes / %l KB / %l MB)\n", - mm_mmap_entries[i].base, - mm_mmap_entries[i].length, - mm_mmap_entries[i].length, - mm_mmap_entries[i].length >> 10, - mm_mmap_entries[i].length >> 20); - } - kprintf("Used pages: %d\n", mm_num_total_pages - mm_num_free_pages); - kprintf("Free pages: %d\n", mm_num_free_pages); -} + +#include + +#include "mm.h" +#include "stack.h" +#include "boot/k_early_panic.h" +#include "lang/string.h" +#include "lang/kio.h" +#include "sys/cpu.h" + +#define MM_MAX_MMAP_ENTRIES 64 + +static pagedirectory_entry_t * page_directory; +static mm_mem_range_t mm_mmap_entries[MM_MAX_MMAP_ENTRIES]; +static int mm_mmap_num_entries = 0; +static int mm_num_free_pages = 0; +static int mm_num_total_pages = 0; +gdtr_t mm_gdtr; +static u64_t * mm_gdt; +static u32_t mm_heap_base; + +/* physical addresses of page allocation pages to map in before the heap */ +static u32_t page_alloc_page_numbers[1025]; /* supports 4GB physical memory */ +static u32_t num_page_alloc_pages = 0; +static mm_page_alloc_page_t * current_page_alloc_page = NULL; +static u32_t page_alloc_page_index = 0; +static mm_page_alloc_page_t * page_alloc_pages; + +/************************************************************************** + * Internal Functions * + *************************************************************************/ +static void record_phys_page(u32_t base_address); + +/************************************************************************** + * This function is run in segmented memory before paging is in effect. * + *************************************************************************/ +void mm_record_mmap_entry(mb_mmap_t * mmap) +{ + if (mm_mmap_num_entries < MM_MAX_MMAP_ENTRIES) + { + if (mmap->type == MB_MMAP_TYPE_RAM) + { + mm_mmap_entries[mm_mmap_num_entries].base = mmap->base; + mm_mmap_entries[mm_mmap_num_entries].length = mmap->length; + mm_mmap_num_entries++; + } + } + else + { + k_early_panic("Too many mmap_entries!"); + } +} + +/************************************************************************** + * This function is run in segmented memory before paging is in effect. * + * It is run after the bootloader information has been read, so we can * + * overwrite that memory now. * + *************************************************************************/ +void mm_bootstrap() +{ + u32_t max_ram_address = KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE - 1; + /* this function requires a big enough initial stack to run */ + BUILD_BUG_ON((STACK_INITIAL_SIZE * PAGE_SIZE) < 8000); + + /* check that a mm_page_alloc_page_t fits exactly in a page */ + BUILD_BUG_ON(sizeof(mm_page_alloc_page_t) != PAGE_SIZE); + + if (mm_mmap_num_entries < 1) + { + k_early_panic("No mmap entries read from bootloader!"); + } + + mm_heap_base = (u32_t) KERNEL_END; + page_alloc_pages = (mm_page_alloc_page_t *) mm_heap_base; + + for (int mmap_idx = 0; mmap_idx < mm_mmap_num_entries; mmap_idx++) + { + u32_t base_address = mm_mmap_entries[mmap_idx].base; + u32_t address_limit = base_address + mm_mmap_entries[mmap_idx].length; + + if (base_address & PAGE_LOW_MASK) + { + /* start of this mmap range is not page-aligned */ + base_address = (base_address & PAGE_HIGH_MASK) + PAGE_SIZE; + } + if (address_limit & PAGE_LOW_MASK) + { + /* end of this mmap range is not page-aligned */ + address_limit &= PAGE_HIGH_MASK; + } + + /* record the highest RAM address found */ + if ((address_limit - 1) > max_ram_address) + { + max_ram_address = (address_limit - 1); + } + + /* + * loop through every page in the mmap range and add + * pages into the free page linked list + */ + for (; base_address < address_limit; base_address += PAGE_SIZE) + { + /* check to make sure the page doesn't overlap the kernel */ + if ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS + || base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE ) + { + record_phys_page(base_address); + mm_num_free_pages++; + } + mm_num_total_pages++; + } + } + + for (unsigned int i = 0; i < num_page_alloc_pages; i++) + { + mm_early_map(mm_heap_base, page_alloc_page_numbers[i], 0, 1); + current_page_alloc_page = (mm_page_alloc_page_t *) mm_heap_base; + /* move the heap back to after the page allocation pages */ + mm_heap_base += PAGE_SIZE; + } + + if (mm_num_free_pages < 10) + { + k_early_panic("Not enough free pages of RAM!"); + } + + /* ok, now mm_page_alloc() should be functional */ + + /* allocate the page directory */ + u32_t page_directory_phys = mm_page_alloc(); + page_directory = (pagedirectory_entry_t *) page_directory_phys; + pagedirectory_entry_t * page_dir_virt = + (pagedirectory_entry_t *) (page_directory_phys + KERNEL_OFFSET); + + /* Clear the page directory */ + for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++) + { + page_dir_virt[i] = 0; + } + + /* now map the kernel's virtual address space into RAM */ + for (u32_t page_base = KERNEL_VIRTUAL_ADDRESS; + page_base < KERNEL_VIRTUAL_ADDRESS + KERNEL_SIZE; + page_base += PAGE_SIZE) + { + /* map page_base to page_base - KERNEL_OFFSET */ + mm_early_map(page_base, page_base - KERNEL_OFFSET, 0, 1); + } + + /* set up the global descriptor table */ + u32_t gdt_base = mm_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); /* 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; + + __asm__ __volatile__ ( + "lgdt (mm_gdtr);\n" + "jmp $0x08, $42f;\n" + "42:\n" + "mov $0x10, %%cx\n" + "mov %%cx, %%ss\n" + "mov %%cx, %%ds\n" + "mov %%cx, %%es\n" + "mov %%cx, %%fs\n" + "mov %%cx, %%gs\n" + : /* no outputs */ + : /* no inputs */ + : "ecx"); + + /* set the page directory base register */ + write_cr3(page_directory); + + /* turn on paging */ + write_cr0(read_cr0() | (1 << 31)); + + stack_bootstrap(); +} + +static void record_phys_page(u32_t base_address) +{ + if (page_alloc_page_index == 0) + { + /* allocate a new page alloc page */ + mm_page_alloc_page_t * old_page_alloc_page = current_page_alloc_page; + current_page_alloc_page = (mm_page_alloc_page_t *) + (base_address + KERNEL_OFFSET); + current_page_alloc_page->next = old_page_alloc_page; + page_alloc_page_index = + sizeof(current_page_alloc_page->pages) + / sizeof(current_page_alloc_page->pages[0]) - 1; + page_alloc_page_numbers[num_page_alloc_pages++] = base_address; + } + else + { + current_page_alloc_page->pages[page_alloc_page_index--] = base_address; + } +} + +/************************************************************************** + * Map virtual_address to physical_address. * + * Both addresses should be page-aligned. * + * This 'early' version can be used during segmented bootstrapping * + *************************************************************************/ +int mm_early_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable) +{ + u32_t directory_index = (virtual_address >> 22) & 0x3FF; + u32_t table_index = (virtual_address >> 12) & 0x3FF; + pagedirectory_entry_t * page_dir = page_directory; + page_dir = (pagedirectory_entry_t *)((u32_t)page_dir + KERNEL_OFFSET); + + if (page_dir[directory_index] == 0) + { + /* allocate a new page table */ + u32_t page_table_address = mm_page_alloc(); + if (page_table_address == 0) + { + return 0; + } + page_dir[directory_index] = page_table_address + | 0x1 << 2 /* PTs can be user mode */ + | 0x1 << 1 /* writable */ + | 0x1; /* present */ + } + u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK; + + u32_t * page_table = (u32_t *) page_table_address; + page_table = (u32_t *)((u32_t)page_table + (u32_t)KERNEL_OFFSET); + + page_table[table_index] = (physical_address & PAGE_HIGH_MASK) + | (user_mode & 0x1) << 2 + | (writable & 0x1) << 1 + | 0x1; /* present */ + + return 1; +} + +/************************************************************************** + * Map virtual_address to physical_address. * + * Both addresses should be page-aligned. * + *************************************************************************/ +int mm_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable) +{ + u32_t directory_index = (virtual_address >> 22) & 0x3FF; + u32_t table_index = (virtual_address >> 12) & 0x3FF; + pagedirectory_entry_t * page_dir = page_directory; + + if (page_dir[directory_index] == 0) + { + /* allocate a new page table */ + u32_t page_table_address = mm_page_alloc(); + if (page_table_address == 0) + { + return 0; + } + page_dir[directory_index] = page_table_address + | 0x1 << 2 /* PTs can be user mode */ + | 0x1 << 1 /* writable */ + | 0x1; /* present */ + } + u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK; + + u32_t * page_table = (u32_t *) page_table_address; + + page_table[table_index] = (physical_address & PAGE_HIGH_MASK) + | (user_mode & 0x1) << 2 + | (writable & 0x1) << 1 + | 0x1; /* present */ + + return 1; +} + +/************************************************************************** + * Returns the physical base address of a page in RAM * + * or 0 if no pages were available * + *************************************************************************/ +u32_t mm_page_alloc() +{ + u32_t page_address = 0; + if (current_page_alloc_page != NULL) + { + if (page_alloc_page_index == sizeof(current_page_alloc_page->pages) + / sizeof(current_page_alloc_page->pages[0]) - 1) + { + page_address = ((u32_t) current_page_alloc_page) - KERNEL_OFFSET; + current_page_alloc_page = current_page_alloc_page->next; + page_alloc_page_index = 0; + } + else + { + page_alloc_page_index++; + page_address = + current_page_alloc_page->pages[page_alloc_page_index]; + } + mm_num_free_pages--; + } + return page_address; +} + +void mm_print_memory_map() +{ + kprintf("Bootloader provided memory map:\n"); + kprintf(" Base Address Length\n"); + for (int i = 0; i < mm_mmap_num_entries; i++) + { + kprintf(" 0x%016X 0x%016X (%l bytes / %l KB / %l MB)\n", + mm_mmap_entries[i].base, + mm_mmap_entries[i].length, + mm_mmap_entries[i].length, + mm_mmap_entries[i].length >> 10, + mm_mmap_entries[i].length >> 20); + } + kprintf("Used pages: %d\n", mm_num_total_pages - mm_num_free_pages); + kprintf("Free pages: %d\n", mm_num_free_pages); +} diff --git a/kernel/mm/mm.h b/kernel/mm/mm.h index 10fb84c..baa9dc2 100644 --- a/kernel/mm/mm.h +++ b/kernel/mm/mm.h @@ -1,64 +1,64 @@ - -#ifndef MM_H -#define MM_H MM_H - -#include "hos_types.h" -#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)) - -typedef pagedirectory_entry_t pagedirectory_t[NUM_PAGETABLE_ENTRIES]; - -typedef struct -{ - u64_t base; - u64_t length; -} mm_mem_range_t; - -typedef struct mm_page_alloc_page_s -{ - u32_t pages[PAGE_SIZE / sizeof(u32_t) - 1]; - mm_page_alloc_page_s * next; -} mm_page_alloc_page_t; - -/* 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 */ -/* normal: 0: TSS/LDT/call gate; 1: code/data segment */ -/* code_seg: 0: data segment; 1: code segment */ -#define MAKE_DESCRIPTOR(base, limit, granularity, dpl, normal, code_seg) \ - (u64_t) ( ( (((u64_t) base) & 0xFF000000ull) << 32 ) /* base 31:24 */ \ - | ( (((u64_t) granularity) & 0x1ull) << 55 ) /* granularity */ \ - | ( ( (u64_t) 0x1ull) << 54 ) /* 32-bit */ \ - | ( (((u64_t) limit) & 0xF0000ull) << 32 ) /* limit 19:16 */ \ - | ( ( (u64_t) 0x1ull) << 47 ) /* present */ \ - | ( (((u64_t) dpl) & 0x3ull) << 45 ) /* dpl */ \ - | ( (((u64_t) normal) & 0x1ull) << 44 ) /* normal */ \ - | ( (((u64_t) code_seg) & 0x1ull) << 43 ) /* code seg */ \ - | ( ( (u64_t) 0x2ull) << 40 ) /* ? */ \ - | ( (((u64_t) base) & 0x00FFFFFFull) << 16) /* base 23:00 */ \ - | ( (((u64_t) limit) & 0x0000FFFFull) ) ) /* limit 15:00 */ - -typedef u64_t descriptor_t; - -void mm_record_mmap_entry(mb_mmap_t * mmap); -void mm_bootstrap(); - -int mm_early_map(u32_t virtual_address, u32_t physical_address, - u32_t user_mode, u32_t writable); -int mm_map(u32_t virtual_address, u32_t physical_address, - u32_t user_mode, u32_t writable); - -u32_t mm_early_page_alloc(); -u32_t mm_page_alloc(); - -void mm_print_memory_map(); - -#endif - + +#ifndef MM_H +#define MM_H MM_H + +#include "hos_types.h" +#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)) + +typedef pagedirectory_entry_t pagedirectory_t[NUM_PAGETABLE_ENTRIES]; + +typedef struct +{ + u64_t base; + u64_t length; +} mm_mem_range_t; + +typedef struct mm_page_alloc_page_s +{ + u32_t pages[PAGE_SIZE / sizeof(u32_t) - 1]; + mm_page_alloc_page_s * next; +} mm_page_alloc_page_t; + +/* 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 */ +/* normal: 0: TSS/LDT/call gate; 1: code/data segment */ +/* code_seg: 0: data segment; 1: code segment */ +#define MAKE_DESCRIPTOR(base, limit, granularity, dpl, normal, code_seg) \ + (u64_t) ( ( (((u64_t) base) & 0xFF000000ull) << 32 ) /* base 31:24 */ \ + | ( (((u64_t) granularity) & 0x1ull) << 55 ) /* granularity */ \ + | ( ( (u64_t) 0x1ull) << 54 ) /* 32-bit */ \ + | ( (((u64_t) limit) & 0xF0000ull) << 32 ) /* limit 19:16 */ \ + | ( ( (u64_t) 0x1ull) << 47 ) /* present */ \ + | ( (((u64_t) dpl) & 0x3ull) << 45 ) /* dpl */ \ + | ( (((u64_t) normal) & 0x1ull) << 44 ) /* normal */ \ + | ( (((u64_t) code_seg) & 0x1ull) << 43 ) /* code seg */ \ + | ( ( (u64_t) 0x2ull) << 40 ) /* ? */ \ + | ( (((u64_t) base) & 0x00FFFFFFull) << 16) /* base 23:00 */ \ + | ( (((u64_t) limit) & 0x0000FFFFull) ) ) /* limit 15:00 */ + +typedef u64_t descriptor_t; + +void mm_record_mmap_entry(mb_mmap_t * mmap); +void mm_bootstrap(); + +int mm_early_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable); +int mm_map(u32_t virtual_address, u32_t physical_address, + u32_t user_mode, u32_t writable); + +u32_t mm_early_page_alloc(); +u32_t mm_page_alloc(); + +void mm_print_memory_map(); + +#endif + diff --git a/kernel/mm/stack.cc b/kernel/mm/stack.cc index 84dec05..ec34d1a 100644 --- a/kernel/mm/stack.cc +++ b/kernel/mm/stack.cc @@ -1,19 +1,19 @@ - -#include "stack.h" -#include "mm.h" -#include "hos_defines.h" - -void stack_bootstrap() -{ - /* - * running from our temporary stack while segmentation is enabled, - * set up the "permanent" stack for use while paging - */ - u32_t stack_page_virt = KERNEL_STACK_TOP - PAGE_SIZE; - for (int i = 0; i < STACK_INITIAL_SIZE; i++) - { - u32_t stack_page_phys = mm_page_alloc(); - mm_early_map(stack_page_virt, stack_page_phys, 0, 1); - stack_page_virt -= PAGE_SIZE; - } -} + +#include "stack.h" +#include "mm.h" +#include "hos_defines.h" + +void stack_bootstrap() +{ + /* + * running from our temporary stack while segmentation is enabled, + * set up the "permanent" stack for use while paging + */ + u32_t stack_page_virt = KERNEL_STACK_TOP - PAGE_SIZE; + for (int i = 0; i < STACK_INITIAL_SIZE; i++) + { + u32_t stack_page_phys = mm_page_alloc(); + mm_early_map(stack_page_virt, stack_page_phys, 0, 1); + stack_page_virt -= PAGE_SIZE; + } +} diff --git a/kernel/mm/stack.h b/kernel/mm/stack.h index d704079..fab25bb 100644 --- a/kernel/mm/stack.h +++ b/kernel/mm/stack.h @@ -1,9 +1,9 @@ - -#ifndef STACK_H -#define STACK_H - -#define STACK_INITIAL_SIZE 2 /* number of initial stack pages */ - -void stack_bootstrap(); - -#endif + +#ifndef STACK_H +#define STACK_H + +#define STACK_INITIAL_SIZE 2 /* number of initial stack pages */ + +void stack_bootstrap(); + +#endif diff --git a/kernel/subdir.mak b/kernel/subdir.mak index 78b78df..cf69eb6 100644 --- a/kernel/subdir.mak +++ b/kernel/subdir.mak @@ -1,54 +1,54 @@ - -ASMOBJS := $(patsubst %.asm,%.o,$(wildcard *.asm)) -COBJS := $(patsubst %.c,%.o,$(wildcard *.c)) -CXXOBJS := $(patsubst %.cc,%.o,$(wildcard *.cc)) -CDEPS := $(COBJS:.o=.dep) -CXXDEPS := $(CXXOBJS:.o=.dep) -DEPS := $(CDEPS) $(CXXDEPS) -OUTPUT_FILE := $(SUBDIR)_all.o - -ifdef SUBDIRS -SUBDIRS_clean := $(SUBDIRS:%=%.clean) -endif - -all: $(OUTPUT_FILE) - -$(OUTPUT_FILE): $(ASMOBJS) $(COBJS) $(CXXOBJS) $(SUBDIRS) - $(LD) -r -o $@ $(ASMOBJS) $(COBJS) $(CXXOBJS) $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o) - -%.o: %.asm - $(NASM) -f elf -o $@ -l $<.lst $< - -%.o: %.c - $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $< - -%.o: %.cc - $(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $< - -ifdef SUBDIRS -.PHONY: $(SUBDIRS) -$(SUBDIRS): - $(MAKE) -C $@ SUBDIR=$@ -endif - -# Make dependency files -%.dep: %.c - @set -e; rm -f $@; \ - $(CC) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ - -%.dep: %.cc - @set -e; rm -f $@; \ - $(CXX) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ - -clean: $(SUBDIRS_clean) - -rm -f *.o *.dep *.lst *~ - -ifdef SUBDIRS -%.clean: - $(MAKE) -C $* clean clean=1 -endif - -# Include dependency files -ifndef clean --include $(DEPS) -endif + +ASMOBJS := $(patsubst %.asm,%.o,$(wildcard *.asm)) +COBJS := $(patsubst %.c,%.o,$(wildcard *.c)) +CXXOBJS := $(patsubst %.cc,%.o,$(wildcard *.cc)) +CDEPS := $(COBJS:.o=.dep) +CXXDEPS := $(CXXOBJS:.o=.dep) +DEPS := $(CDEPS) $(CXXDEPS) +OUTPUT_FILE := $(SUBDIR)_all.o + +ifdef SUBDIRS +SUBDIRS_clean := $(SUBDIRS:%=%.clean) +endif + +all: $(OUTPUT_FILE) + +$(OUTPUT_FILE): $(ASMOBJS) $(COBJS) $(CXXOBJS) $(SUBDIRS) + $(LD) -r -o $@ $(ASMOBJS) $(COBJS) $(CXXOBJS) $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o) + +%.o: %.asm + $(NASM) -f elf -o $@ -l $<.lst $< + +%.o: %.c + $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $< + +%.o: %.cc + $(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $< + +ifdef SUBDIRS +.PHONY: $(SUBDIRS) +$(SUBDIRS): + $(MAKE) -C $@ SUBDIR=$@ +endif + +# Make dependency files +%.dep: %.c + @set -e; rm -f $@; \ + $(CC) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ + +%.dep: %.cc + @set -e; rm -f $@; \ + $(CXX) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ + +clean: $(SUBDIRS_clean) + -rm -f *.o *.dep *.lst *~ + +ifdef SUBDIRS +%.clean: + $(MAKE) -C $* clean clean=1 +endif + +# Include dependency files +ifndef clean +-include $(DEPS) +endif