diff --git a/include/allocator.h b/include/allocator.h new file mode 100644 index 0000000..a9c0699 --- /dev/null +++ b/include/allocator.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +void initialize_allocator(void *bottom, void *top); + +void *allocate_from_bottom(size_t size); + +void *allocate_from_top(size_t size); \ No newline at end of file diff --git a/include/context.h b/include/context.h new file mode 100644 index 0000000..792966c --- /dev/null +++ b/include/context.h @@ -0,0 +1,8 @@ +#pragma once + +#include "pageallocator.h" +#include "process.h" + +void *initialize_context(void *task_entry, struct page_stack_t *page_stack); + +void load_context(struct process_state_t *context) __attribute__((noreturn)); diff --git a/include/elf.h b/include/elf.h index 6605add..24146ea 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1,10 +1,9 @@ #pragma once +#include "pageallocator.h" #include "types/physaddr.h" #include -const uint32_t elf_magic_number = 0x464c457f; - enum elf_endianness_t { ELF_LITTLE_ENDIAN = 1, @@ -107,11 +106,13 @@ struct elf_section_header_t }; #if defined __i386__ - static const elf_isa_t HOST_ISA = ELF_ISA_x86; + static const enum elf_isa_t HOST_ISA = ELF_ISA_x86; #elif defined __x86_64__ - static const elf_isa_t HOST_ISA = ELF_ISA_x86_64; + static const enum elf_isa_t HOST_ISA = ELF_ISA_x86_64; #elif defined __arm__ - static const elf_isa_t HOST_ISA = ELF_ISA_ARM; + static const enum elf_isa_t HOST_ISA = ELF_ISA_ARM; #elif defined __aarch64__ - static const elf_isa_t HOST_ISA = ELF_ISA_AARCH64; + static const enum elf_isa_t HOST_ISA = ELF_ISA_AARCH64; #endif + +int load_program(struct elf_file_header_t *elf, struct page_stack_t *page_stack); diff --git a/include/kernel.h b/include/kernel.h index 9f6da99..be6095d 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -1,18 +1,31 @@ #pragma once +#include "pageallocator.h" #include "priorityqueue.h" +#include "resource.h" #include "module.h" +#include "process.h" #include +enum syscall_id_t +{ + SYSCALL_YIELD = 1 +}; + struct kernel_t { + struct page_stack_t *page_stack; struct priority_queue_t *priority_queue; + struct process_t *active_process; + struct resource_table_t *resource_table; }; -extern struct kernel_t kernel; +extern struct kernel_t kernel_state; -int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3); +size_t do_syscall(struct kernel_t *kernel, enum syscall_id_t id, size_t arg1, size_t arg2, size_t arg3); int load_module(struct kernel_t *kernel, struct module_t *module); +struct process_state_t *next_process(struct kernel_t *kernel, struct process_state_t *prev_state) __attribute__((noreturn)); + void panic(const char *message) __attribute__ ((noreturn)); diff --git a/include/mmgr.h b/include/mmgr.h index dc80161..12e86c8 100644 --- a/include/mmgr.h +++ b/include/mmgr.h @@ -3,6 +3,15 @@ #include "pageallocator.h" #include "types/physaddr.h" +enum page_flag_t +{ + PAGE_RW = 1, + PAGE_EXECUTABLE = 1 << 1, + PAGE_USERMODE = 1 << 2 +}; + +extern const size_t page_size; + /** * @brief Create a new top-level page table and map the kernel in it. * @@ -19,6 +28,15 @@ physaddr_t create_address_space(struct page_stack_t *page_stack); */ void load_address_space(physaddr_t table); +/** + * @brief Returns the physical address of the top-level page table currently in + * use. + * + * @param table + * @return physaddr_t + */ +physaddr_t current_address_space(); + /** * @brief Maps a single page with the specified flags. * @@ -36,4 +54,4 @@ int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int * @param page * @return physaddr_t */ -physaddr_t unmap_page(void *page); \ No newline at end of file +physaddr_t unmap_page(void *page); diff --git a/include/pageallocator.h b/include/pageallocator.h index 5b52d54..3bb71d3 100644 --- a/include/pageallocator.h +++ b/include/pageallocator.h @@ -72,4 +72,4 @@ size_t free_page_count(struct page_stack_t *stack); * @param stack * @param map */ -int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size); +int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map); diff --git a/include/priorityqueue.h b/include/priorityqueue.h index 85aed7a..d259ef6 100644 --- a/include/priorityqueue.h +++ b/include/priorityqueue.h @@ -43,7 +43,7 @@ struct process_t *extract_min(struct priority_queue_t *queue); * @param process * @return int */ -int insert(struct priority_queue_t *queue, struct process_t *process); +int queue_insert(struct priority_queue_t *queue, struct process_t *process); /** * @brief @@ -52,4 +52,4 @@ int insert(struct priority_queue_t *queue, struct process_t *process); * @param process * @return int */ -int remove(struct priority_queue_t *queue, struct process_t *process); +int queue_remove(struct priority_queue_t *queue, struct process_t *process); diff --git a/include/process.h b/include/process.h index be2bdbf..8f545fb 100644 --- a/include/process.h +++ b/include/process.h @@ -1,5 +1,6 @@ #pragma once +#include "types/physaddr.h" #include struct process_state_t; @@ -7,6 +8,6 @@ struct process_state_t; struct process_t { size_t priority; - struct process_state_t *state; + physaddr_t page_table; }; \ No newline at end of file diff --git a/include/resource.h b/include/resource.h new file mode 100644 index 0000000..47c3d2e --- /dev/null +++ b/include/resource.h @@ -0,0 +1,27 @@ +#pragma once + +#include "process.h" +#include + +enum resource_type_t +{ + RESOURCE_UNAVAILABLE = 0, + RESOURCE_PROCESS +}; + +struct resource_t +{ + size_t type; + union + { + struct process_t process; + }; +}; + +struct resource_table_t +{ + struct resource_t *array; + size_t capacity; +}; + +int find_resource_slot(struct resource_table_t *table); diff --git a/include/stdio.h b/include/stdio.h index 3c086ee..e669124 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -2,6 +2,8 @@ #include +int initialize_screen(); + int putchar(int c); int puts(const char *str); diff --git a/src/Makefile.am b/src/Makefile.am index e696654..e55eca4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = quark-kernel -quark_kernel_SOURCES = kernel.c memorymap.c pageallocator.c priorityqueue.c stdio.c string.c +quark_kernel_SOURCES = kernel.c memorymap.c pageallocator.c priorityqueue.c stdio.c string.c elf.c resource.c allocator.c quark_kernel_LDADD = -lgcc quark_kernel_CFLAGS = -I$(top_srcdir)/include -ffreestanding -mgeneral-regs-only -O0 -Wall -ggdb quark_kernel_LDFLAGS = -nostdlib @@ -12,6 +12,7 @@ quark_kernel_SOURCES += x86/mmgr.c \ x86/apic.c \ x86/isr.c \ x86/msr.c \ + x86/context.c \ x86/quark_x86.c \ x86/entry.S quark_kernel_LDFLAGS += -T x86/linker.ld diff --git a/src/allocator.c b/src/allocator.c new file mode 100644 index 0000000..574b195 --- /dev/null +++ b/src/allocator.c @@ -0,0 +1,34 @@ +#include "allocator.h" + +struct linear_allocator_t +{ + void *bottom; + void *top; +} allocator; + +void initialize_allocator(void *bottom, void *top) +{ + allocator.bottom = bottom; + allocator.top = top; +} + +void *allocate_from_bottom(size_t size) +{ + if((size_t)allocator.bottom + size <= (size_t)allocator.top) + { + void *ptr = allocator.bottom; + allocator.bottom += size; + return ptr; + } + return (void*)NULL; +} + +void *allocate_from_top(size_t size) +{ + if((size_t)allocator.top - size >= (size_t)allocator.bottom) + { + allocator.top -= size; + return allocator.top; + } + return (void*)NULL; +} diff --git a/src/allocator.cpp b/src/allocator.cpp deleted file mode 100644 index b7c5bbe..0000000 --- a/src/allocator.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "allocator.hpp" - -#define AVAIL 0 -#define UNAVAIL -1 - -inline size_t ilog2(size_t n) -{ - size_t m = n; - size_t count = 0; - bool isPowerOfTwo = true; - while(m) - { - if((m & 1) == 1 && m > 1) - { - isPowerOfTwo = false; - } - count++; - m >>= 1; - } - return count - (isPowerOfTwo ? 1 : 0); -} - -kernelns::Allocator::Allocator() -{ - -} - -kernelns::Allocator::Allocator(void* base, size_t heapSize, size_t blockSize) -{ - this->base = (char*) base; - this->heapSize = heapSize; - this->blockSize = blockSize; - this->treeHeight = ilog2(heapSize / blockSize); - size_t headerSize = (heapSize / blockSize) << 1; - for(size_t i = 1; i < (heapSize / blockSize) * 2; i++) - this->base[i] = UNAVAIL; - for(size_t i = 0; i < heapSize / blockSize; i++) - { - if(blockSize * i >= headerSize) - { - size_t index = i + (1 << treeHeight); - this->base[index] = AVAIL; - for(; index > 1 && this->base[index ^ 1] == 0; index >>= 1) - { - this->base[index] = UNAVAIL; - this->base[index ^ 1] = UNAVAIL; - this->base[index >> 1] = AVAIL; - } - } - else - { - this->base[i + (1 << treeHeight)] = 1; - } - } -} - -void* kernelns::Allocator::allocate(size_t size) -{ - size += blockSize - 1; - size -= size % blockSize; - size_t height = ilog2(size / blockSize); - size_t index = findFreeBlock(height); - if(index) - { - base[index] = height + 1; - return (void*) ((size_t) base + (blockSize << height) * (index - (1 << (treeHeight - height)))); - } - return NULL; -} - -void kernelns::Allocator::free(void* location) -{ - size_t offset = (size_t) location - (size_t) base; - size_t index = (offset / blockSize) + (1 << treeHeight); - for(; index > 0 && base[index] == UNAVAIL; index >>= 1); - base[index] = AVAIL; - for(; index > 1 && base[index ^ 1] == AVAIL; index >>= 1) - { - base[index] = UNAVAIL; - base[index ^ 1] = UNAVAIL; - base[index >> 1] = AVAIL; - } -} - -size_t kernelns::Allocator::findFreeBlock(size_t height) -{ - if(height > treeHeight) - return 0; - for(size_t index = 1 << (treeHeight - height); index < 1 << (treeHeight - height + 1); index++) - { - if(base[index] == AVAIL) - return index; - } - size_t index = findFreeBlock(height + 1); - if(index) - { - base[index] = UNAVAIL; - base[index << 1] = AVAIL; - base[(index << 1) ^ 1] = AVAIL; - } - return index << 1; -} \ No newline at end of file diff --git a/src/allocator.hpp b/src/allocator.hpp deleted file mode 100644 index d910ff8..0000000 --- a/src/allocator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef ALLOCATOR_H -#define ALLOCATOR_H - -#include - -namespace kernelns -{ - -class Allocator -{ -public: - - Allocator(); - - /** - * @param base A pointer to the start of the heap. - * @param heapSize The size of the heap, in bytes. Must be a power of two. - * @param blockSize The smallest unit of allocation, in bytes. Must be a power of two less than or equal to heapSize. - */ - Allocator(void* base, size_t heapSize, size_t blockSize); - - void* allocate(size_t size); - - void free(void* location); - -private: - - size_t findFreeBlock(size_t height); - - char* base; - - size_t heapSize; - - size_t blockSize; - - size_t treeHeight; - -}; - -} - -#endif \ No newline at end of file diff --git a/src/elf.c b/src/elf.c new file mode 100644 index 0000000..586fb21 --- /dev/null +++ b/src/elf.c @@ -0,0 +1,40 @@ +#include "elf.h" +#include "pageallocator.h" +#include "mmgr.h" +#include "string.h" +#include "types/status.h" + +const uint32_t elf_magic_number = 0x464c457f; + +int load_program(struct elf_file_header_t *elf, struct page_stack_t *page_stack) +{ + struct elf_program_header_t *program_header = (struct elf_program_header_t*)((void*)elf + elf->phoffset); + unsigned int count = elf->phcount; + while(count > 0) + { + if(program_header->type == ELF_LOAD) + { + void *d = program_header->vaddr, *s = (void*)elf + program_header->offset; + for(size_t n = 0; n < program_header->memsize; n += page_size) + { + physaddr_t page = reserve_page(page_stack); + if(page == S_OUT_OF_MEMORY) + { + return S_OUT_OF_MEMORY; + } + int status = map_page(page_stack, d, page, PAGE_RW | PAGE_USERMODE | PAGE_EXECUTABLE); + switch(status) + { + case S_OUT_OF_MEMORY: + return status; + case S_OUT_OF_BOUNDS: + return status; + case S_OK: + memcpy(d, s, page_size); + } + } + } + count--; + program_header = (struct elf_program_header_t*)((void*)program_header + elf->phsize); + } +} \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c index cf049dc..a4755d5 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,11 +1,84 @@ #include "kernel.h" +#include "mmgr.h" +#include "stdio.h" +#include "elf.h" +#include "context.h" +#include "types/status.h" -int do_syscall(struct kernel_t *kernel, size_t id, size_t arg1, size_t arg2, size_t arg3) +size_t do_syscall(struct kernel_t *kernel, enum syscall_id_t id, size_t arg1, size_t arg2, size_t arg3) { } int load_module(struct kernel_t *kernel, struct module_t *module) { + physaddr_t module_address_space = create_address_space(kernel->page_stack); + load_address_space(module_address_space); + void *const load_base = (void*)0x80000000; + size_t load_offset = 0; + for(physaddr_t p = module->start & ~(page_size - 1); p < module->end; p += page_size) + { + int status = map_page(kernel->page_stack, load_base + load_offset, p, PAGE_RW); + switch(status) + { + case S_OUT_OF_MEMORY: + panic("ran out of memory while mapping module"); + case S_OUT_OF_BOUNDS: + panic("got out-of-bounds error while mapping module"); + } + load_offset += page_size; + } + int status = load_program(load_base, kernel->page_stack); + switch(status) + { + case S_OUT_OF_MEMORY: + panic("ran out of memory while reading ELF file"); + case S_OUT_OF_BOUNDS: + panic("got out-of-bounds error while reading ELF file"); + } + void *module_entry = ((struct elf_file_header_t*)load_base)->entry; + void *module_context = initialize_context(module_entry, kernel->page_stack); + printf("loaded module with entry point %08x\n", (unsigned int)module_entry); + load_offset = 0; + for(physaddr_t p = module->start & ~(page_size - 1); p < module->end; p += page_size) + { + int status = unmap_page(load_base + load_offset); + switch(status) + { + case S_OUT_OF_MEMORY: + panic("ran out of memory while unmapping module"); + case S_OUT_OF_BOUNDS: + panic("got out-of-bounds error while unmapping module"); + } + load_offset += page_size; + } + int index = find_resource_slot(kernel); + if(index < 0) + { + panic("no space left in resource table for module"); + } + kernel->resource_table->array[index].type = RESOURCE_PROCESS; + kernel->resource_table->array[index].process.priority = 1; + kernel->resource_table->array[index].process.state = module_context; + kernel->resource_table->array[index].process.page_table = current_address_space(); + queue_insert(kernel->priority_queue, &kernel->resource_table->array[index].process); + return S_OK; +} -} \ No newline at end of file +struct process_state_t *next_process(struct kernel_t *kernel, struct process_state_t *prev_state) +{ + if(prev_state != NULL) + { + kernel->active_process->state = prev_state; + queue_insert(kernel->priority_queue, kernel->active_process); + } + kernel->active_process = extract_min(kernel->priority_queue); + load_context(kernel->active_process->state); +} + +void panic(const char *message) +{ + printf("panic: %s", message); + asm("cli"); + while(1) asm("hlt"); +} diff --git a/src/memorymap.c b/src/memorymap.c index 2adef20..ed32e6c 100644 --- a/src/memorymap.c +++ b/src/memorymap.c @@ -66,36 +66,36 @@ int trim_map(struct memory_map_t *map, int index) { return -1; } - struct memory_region_t left = map->array[index]; - struct memory_region_t right = map->array[index + 1]; - if(region_overlaps(&left, &right)) + struct memory_region_t *left = &map->array[index]; + struct memory_region_t *right = &map->array[index + 1]; + if(region_overlaps(left, right)) { - if(left.type == right.type) + if(left->type == right->type) { - left.size = (right.location + right.size > left.location + left.size ? right.location + right.size : left.location + left.size) - left.location; + left->size = (right->location + right->size > left->location + left->size ? right->location + right->size : left->location + left->size) - left->location; remove_map_entry(map, index + 1); return index; } - else if(left.type < right.type) + else if(left->type < right->type) { - if(region_contains(&right, &left)) + if(region_contains(right, left)) { remove_map_entry(map, index); return index; } - else if(left.location + left.size <= right.location + right.size) + else if(left->location + left->size <= right->location + right->size) { - left.size = (right.location > left.location) ? right.location - left.location : 0; + left->size = (right->location > left->location) ? right->location - left->location : 0; return index + 1; } else { struct memory_region_t new_right = { - .location = right.location + right.size, - .size = (left.location + left.size) - (right.location + right.size), - .type = left.type}; - left.size = (right.location > left.location) ? right.location - left.location : 0; - if(left.size == 0) + .location = right->location + right->size, + .size = (left->location + left->size) - (right->location + right->size), + .type = left->type}; + left->size = (right->location > left->location) ? right->location - left->location : 0; + if(left->size == 0) remove_map_entry(map, index); insert_map_entry(map, new_right.location, new_right.size, new_right.type); return index + 2; @@ -103,22 +103,22 @@ int trim_map(struct memory_map_t *map, int index) } else { - if(region_contains(&left, &right)) + if(region_contains(left, right)) { remove_map_entry(map, index + 1); return index; } else { - right.size = (right.location + right.size) - (left.location + left.size); - right.location = left.location + left.size; + right->size = (right->location + right->size) - (left->location + left->size); + right->location = left->location + left->size; return index + 1; } } } - else if((left.location + left.size == right.location) && left.type == right.type) + else if((left->location + left->size == right->location) && left->type == right->type) { - left.size = right.location + right.size - left.location; + left->size = right->location + right->size - left->location; remove_map_entry(map, index + 1); return index; } diff --git a/src/pageallocator.c b/src/pageallocator.c index 6289809..51135bf 100644 --- a/src/pageallocator.c +++ b/src/pageallocator.c @@ -1,4 +1,6 @@ #include "pageallocator.h" +#include "mmgr.h" +#include "allocator.h" #include "types/status.h" physaddr_t reserve_page(struct page_stack_t *stack) @@ -15,12 +17,25 @@ physaddr_t reserve_page(struct page_stack_t *stack) int free_page(struct page_stack_t *stack, physaddr_t location) { + void *new_limit; if(stack->stack_pointer > stack->limit_pointer) { stack->stack_pointer--; *stack->stack_pointer = location; return S_OK; } + else if((new_limit = allocate_from_top(page_size)) != NULL) + { + switch(map_page(stack, new_limit, location, PAGE_RW)) + { + case S_OUT_OF_MEMORY: + return S_OUT_OF_MEMORY; + case S_OUT_OF_BOUNDS: + return S_OUT_OF_BOUNDS; + case S_OK: + stack->limit_pointer = new_limit; + } + } return S_OUT_OF_MEMORY; } @@ -29,7 +44,7 @@ size_t free_page_count(struct page_stack_t *stack) return stack->base_pointer - stack->stack_pointer; } -int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size) +int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map) { stack->total_pages = 0; for(int i = 0; i < map->size; i++) diff --git a/src/priorityqueue.c b/src/priorityqueue.c index 5ab2873..66a4960 100644 --- a/src/priorityqueue.c +++ b/src/priorityqueue.c @@ -36,7 +36,7 @@ struct process_t *extract_min(struct priority_queue_t *queue) return p; } -int insert(struct priority_queue_t *queue, struct process_t *process) +int queue_insert(struct priority_queue_t *queue, struct process_t *process) { if(queue->size == queue->capacity) return S_OUT_OF_MEMORY; @@ -51,7 +51,7 @@ int insert(struct priority_queue_t *queue, struct process_t *process) return S_OK; } -int remove(struct priority_queue_t *queue, struct process_t *process) +int queue_remove(struct priority_queue_t *queue, struct process_t *process) { for(size_t i = 0; i < queue->size; i++) { diff --git a/src/resource.c b/src/resource.c new file mode 100644 index 0000000..7867800 --- /dev/null +++ b/src/resource.c @@ -0,0 +1,13 @@ +#include "resource.h" + +int find_resource_slot(struct resource_table_t *table) +{ + for(int i = 0; i < table->capacity; i++) + { + if(table->array[i].type == RESOURCE_UNAVAILABLE) + { + return i; + } + } + return -1; +} diff --git a/src/x86/apic.c b/src/x86/apic.c index 9d6d113..9698e55 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,8 +1,43 @@ +#include "mmgr.h" +#include "allocator.h" #include "apic.h" +#include "msr.h" +#include "stdio.h" +#include -void apic_enable() +extern int _kernel_end; + +struct apic_registers_t volatile *apic_registers; + +void apic_enable(struct page_stact_t *page_stack) { - + // Remap and mask 8259 PIC + asm volatile( + "mov $0x11, %%al;" + "outb %%al, $0x20;" + "outb %%al, $0xA0;" + "mov $0x20, %%al;" + "outb %%al, $0x21;" + "mov $0x28, %%al;" + "outb %%al, $0xA1;" + "mov $4, %%al;" + "outb %%al, $0x21;" + "mov $2, %%al;" + "outb %%al, $0xA1;" + "mov $0x01, %%al;" + "outb %%al, $0x21;" + "outb %%al, $0xA1;" + "mov $0xFF, %%al;" + "outb %%al, $0xA1;" + "outb %%al, $0x21;" + ::: "al" + ); + struct msr_apic_base_t msr; + read_msr(MSR_APIC_BASE, (uint64_t*)&msr); + apic_registers = (struct apic_registers_t*)allocate_from_bottom(page_size); + map_page(page_stack, apic_registers, msr.apic_base << 12, PAGE_RW); + printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); + apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100; } void apic_eoi() @@ -32,4 +67,4 @@ void apic_send_ipi( uint32_t *icr_addr = (uint32_t*)&apic_registers->interrput_command; icr_addr[4] = value_addr[4]; icr_addr[0] = value_addr[0]; -} \ No newline at end of file +} diff --git a/src/x86/context.c b/src/x86/context.c new file mode 100644 index 0000000..c7262d0 --- /dev/null +++ b/src/x86/context.c @@ -0,0 +1,32 @@ +#include "context.h" +#include "pageallocator.h" +#include "mmgr.h" + +void *initialize_context(void *task_entry, struct page_stack_t *page_stack) +{ + physaddr_t stack0 = reserve_page(page_stack); + map_page(page_stack, (void*)0xFF7FF000, stack0, PAGE_RW); + map_page(page_stack, (void*)0xFF7FD000, stack0, PAGE_RW | PAGE_USERMODE); + unmap_page((void*)0xFF7FE000); + unmap_page((void*)0xFF7FC000); + uint32_t flags; + uint32_t *stack = (uint32_t*)((void*)stack0 - 20); + asm("pushf; " + "mov (%%esp), %0; " + "popf; " + : "=r"(flags)); + stack[0] = (uint32_t)task_entry; + stack[1] = 27; + stack[2] = flags; + stack[3] = 0xFF7FE000; + stack[4] = 35; + return (void*)stack; +} + +void load_context(struct process_state_t *context) +{ + asm("mov %0, %%esp; " + "popal; " + "iret; " + :: "r"(context)); +} \ No newline at end of file diff --git a/src/x86/entry.S b/src/x86/entry.S index 6ec1c8b..24aad6a 100755 --- a/src/x86/entry.S +++ b/src/x86/entry.S @@ -30,7 +30,7 @@ .set tagEntryType, 3 .set tagEntrySize, 12 -.set tagEntryAddress, _start - (0xFF900000 - 0x100000) +.set tagEntryAddress, _start - (0xFF800000 - 0x100000) .set tagModuleAlignType, 6 .set tagModuleAlignSize, 8 @@ -93,23 +93,6 @@ _multibootInfoTagEnd: .long 8 _multibootHeaderEnd: - -.section .rodata - -gdt: -.long 0, 0 -.short 0xFFFF -.short 0x0000 -.short 0x9A00 -.short 0x00CF -.short 0xFFFF -.short 0x0000 -.short 0x9200 -.short 0x00CF - -gdt_info: -.short 23 -.long gdt .section .bss @@ -125,19 +108,6 @@ _tempIdentityMap: .skip 4096 _tempPgTable: .skip 4096 - -_bootCmdLine: -.skip 64 - -.align 64 -.global system_info -system_info: -.skip 16 - -.align 64 -.global memory_map -memory_map: -.skip 16 * 16 .section .text .global _start @@ -169,19 +139,26 @@ _start: sub $BASE_DIFF, %eax push %eax + # Push ending physical address to map + mov (%ebx), %eax + add %ebx, %eax + push %eax + + # Push starting physical address to map + mov $PHYSICAL_BASE, %eax + push %eax + # Load physical address of startPaging() - mov $startPaging, %eax + mov $start_paging, %eax sub $BASE_DIFF, %eax # Initialize paging call *%eax - + # Jump into mapped kernel binary lea 1f, %eax jmp *%eax 1: - # Delete PDE corresponding to identity map. We shouldn't need it anymore. - movl $0, (_tempIdentityMap) # Flush TLB mov %cr3, %eax @@ -190,22 +167,9 @@ _start: # Initialize stack in virtual memory mov $stackTop, %esp - # Load GPT - lgdt gdt_info - - # Load segment registers - jmp $8, $.ldcs -.ldcs: - mov $16, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %gs - mov %ax, %fs - mov %ax, %ss - # Change EBX to point to the virtual address of the multiboot info # If the new pointer is out-of-bounds, error - add $0xFF800000, %ebx + add $0xFF700000, %ebx cmp $0xFF800000, %ebx jl .err cmp $0xFFC00000, %ebx diff --git a/src/x86/interrupts.c b/src/x86/interrupts.c index aadce4a..37fe8b6 100644 --- a/src/x86/interrupts.c +++ b/src/x86/interrupts.c @@ -1,14 +1,85 @@ #include "interrupts.h" +#include "isr.h" +#include "string.h" +#include -struct idt_info_t +#define idt_size 256 +#define gdt_size 6 + +enum segment_type_t +{ + SEGMENT_KERNEL_CODE, + SEGMENT_KERNEL_DATA, + SEGMENT_USER_CODE, + SEGMENT_USER_DATA, + SEGMENT_TSS +}; + +struct gdt_entry_t +{ + unsigned int limit_low : 16; + unsigned int base_low : 24; + unsigned int accessed : 1; + unsigned int read_write : 1; + unsigned int conforming_expand_down : 1; + unsigned int code : 1; + unsigned int code_data_segment : 1; + unsigned int dpl : 2; + unsigned int present : 1; + unsigned int limit_high : 4; + unsigned int available : 1; + unsigned int long_mode : 1; + unsigned int big : 1; + unsigned int gran : 1; + unsigned int base_high : 8; +} __attribute__ ((packed)); + +struct tss_t +{ + +}; + +struct interrupt_descriptor_t +{ + uint16_t offset_1; + uint16_t selector; + uint16_t zero : 8; + uint16_t type : 4; + uint16_t storage : 1; + uint16_t dpl : 2; + uint16_t present : 1; + uint16_t offset_2; +}; + +struct descriptor_table_info_t { uint16_t size; void *location; } __attribute__ ((packed)); -void lidt(struct interrupt_descriptor_t *idt) +struct tss_t tss; + +void load_gdt(struct gdt_entry_t *gdt) { - struct idt_info_t idt_info; + struct descriptor_table_info_t gdt_info; + gdt_info.size = sizeof(struct gdt_entry_t) * 6 - 1; + gdt_info.location = (void *)gdt; + asm("lgdt (%0);" + "jmp $8, $.ldcs;" + ".ldcs:;" + "mov $16, %%ax;" + "mov %%ax, %%ds;" + "mov %%ax, %%es;" + "mov %%ax, %%gs;" + "mov %%ax, %%fs;" + "mov %%ax, %%ss;" + : + : "r"(&gdt_info)); +} + +void load_idt(struct interrupt_descriptor_t *idt) +{ + struct descriptor_table_info_t idt_info; idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1; idt_info.location = (void *)idt; asm("lidt (%0)" @@ -27,3 +98,104 @@ void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void descriptor->dpl = privilage; descriptor->present = 1; } + +void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size_t limit, enum segment_type_t type) +{ + descriptor->limit_low = limit; + descriptor->limit_high = (limit & (0xf << 16)) >> 16; + descriptor->base_low = base; + descriptor->base_high = (base & (0xff << 24)) >> 24; + descriptor->present = 1; + switch(type) + { + case SEGMENT_KERNEL_CODE: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 1; + descriptor->code_data_segment = 1; + descriptor->dpl = 0; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_KERNEL_DATA: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 0; + descriptor->code_data_segment = 1; + descriptor->dpl = 0; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_USER_CODE: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 1; + descriptor->code_data_segment = 1; + descriptor->dpl = 3; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_USER_DATA: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 0; + descriptor->code_data_segment = 1; + descriptor->dpl = 3; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_TSS: + descriptor->accessed = 1; + descriptor->read_write = 0; + descriptor->conforming_expand_down = 0; + descriptor->code = 1; + descriptor->code_data_segment = 0; + descriptor->dpl = 3; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 0; + descriptor->gran = 0; + } +} + +void initialize_gdt() +{ + static struct gdt_entry_t gdt[gdt_size]; + memset(gdt, 0, sizeof(struct gdt_entry_t) * gdt_size); + create_segment_descriptor(&gdt[1], 0, 0xFFFFF, SEGMENT_KERNEL_CODE); + create_segment_descriptor(&gdt[2], 0, 0xFFFFF, SEGMENT_KERNEL_DATA); + create_segment_descriptor(&gdt[3], 0, 0xFFFFF, SEGMENT_USER_CODE); + create_segment_descriptor(&gdt[4], 0, 0xFFFFF, SEGMENT_USER_DATA); + //create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_t), SEGMENT_TSS); + load_gdt(gdt); +} + +void initialize_idt() +{ + static struct interrupt_descriptor_t idt[idt_size]; + memset(idt, 0, sizeof(struct interrupt_descriptor_t) * idt_size); + for(int i = 0; i < idt_size; i++) + { + create_interrupt_descriptor(&idt[i], (void*)isr_generic, INTERRPUT_INT32, 0); + } + create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0); + load_idt(idt); +} diff --git a/src/x86/interrupts.h b/src/x86/interrupts.h index d8ff3b9..13c01a8 100644 --- a/src/x86/interrupts.h +++ b/src/x86/interrupts.h @@ -24,6 +24,7 @@ enum interrupt_code_t EXCEPTION_SIMD_FLOATING_POINT = 19, EXCEPTION_VIRTUALIZATION = 20, EXCEPTION_SECURITY = 30, + ISR_APIC_TIMER = 64, ISR_AP_START = 127, ISR_SYSCALL = 128 }; @@ -37,18 +38,6 @@ enum isr_type_t INTERRPUT_INT16 = 6 }; -struct interrupt_descriptor_t -{ - uint16_t offset_1; - uint16_t selector; - uint16_t zero : 8; - uint16_t type : 4; - uint16_t storage : 1; - uint16_t dpl : 2; - uint16_t present : 1; - uint16_t offset_2; -}; +void initialize_gdt(); -void lidt(struct interrupt_descriptor_t *idt); - -void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage); +void initialize_idt(); diff --git a/src/x86/isr.c b/src/x86/isr.c index 8d36841..81dbc4e 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -1,31 +1,58 @@ +#include "kernel.h" #include "isr.h" #include "stdio.h" +#include "apic.h" + +void isr_generic(void* frame) +{ + printf("Generic interrupt.\n"); +} -__attribute__ ((interrupt)) void isr_division_by_zero(void* frame) { printf("Exception: Division by zero\n"); } -__attribute__ ((interrupt)) void isr_gp_fault(void* frame, unsigned int error) { - -} - -__attribute__ ((interrupt)) -void isr_page_fault(void* frame, unsigned int error) -{ - -} - -__attribute__ ((interrupt)) -void isr_double_fault(void* frame, unsigned int error) -{ + asm("cli"); + printf("Exception: GP fault, code %08x\n", error); asm("hlt"); } -__attribute__ ((naked)) +void isr_page_fault(void* frame, unsigned int error) +{ + size_t addr; + asm("mov %%cr2, %0" + : "=r"(addr)); + printf("Exception: Page fault, code %08x, linear address %08x\n", error, addr); + asm("hlt"); +} + +void isr_double_fault(void* frame, unsigned int error) +{ + asm("cli"); + + printf("Exception: Double fault (!!), code %08x\n", error); + asm("hlt"); +} + +void isr_timer(void* frame) +{ + printf("Timer tick.\n"); + apic_eoi(); +} + +void isr_preempt(void* frame) +{ + asm("pushal;" + "mov %esp, %ebp"); + struct process_state_t *process_state; + asm("mov %%ebp, %0" + : "=r"(process_state)); + next_process(&kernel_state, process_state); +} + void isr_ap_start(void* frame) { asm(".code16"); @@ -34,7 +61,6 @@ void isr_ap_start(void* frame) // do something useful } -__attribute__ ((interrupt)) void isr_syscall(void* frame) { diff --git a/src/x86/isr.h b/src/x86/isr.h index 1725d53..b4d8d9b 100644 --- a/src/x86/isr.h +++ b/src/x86/isr.h @@ -1,5 +1,8 @@ #pragma once +__attribute__ ((interrupt)) +void isr_generic(void* frame); + __attribute__ ((interrupt)) void isr_division_by_zero(void* frame); @@ -12,6 +15,12 @@ void isr_page_fault(void* frame, unsigned int error); __attribute__ ((interrupt)) void isr_double_fault(void* frame, unsigned int error); +__attribute__ ((interrupt)) +void isr_timer(void* frame); + +__attribute__ ((naked)) +void isr_preempt(void* frame); + __attribute__ ((naked)) void isr_ap_start(void* frame); diff --git a/src/x86/linker.ld b/src/x86/linker.ld index bf01f37..f13451d 100755 --- a/src/x86/linker.ld +++ b/src/x86/linker.ld @@ -2,7 +2,7 @@ ENTRY(_start) SECTIONS { - . = 0xFF900000; + . = 0xFF800000; VIRTUAL_BASE = .; PHYSICAL_BASE = 0x100000; BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; @@ -34,9 +34,8 @@ SECTIONS BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE); IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096; - _pageMapLocation = 0xFF800000; - _heapLocation = 0xFFB00000; - _heapSize = 0x100000; - _kernelStart = VIRTUAL_BASE; + _kernel_pstart = PHYSICAL_BASE; + _kernel_pend = PHYSICAL_BASE + (4096 * IMAGE_SIZE); + _kernel_start = VIRTUAL_BASE; _kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE); } diff --git a/src/x86/mmgr.c b/src/x86/mmgr.c index a12be9f..572abc2 100644 --- a/src/x86/mmgr.c +++ b/src/x86/mmgr.c @@ -11,34 +11,51 @@ const size_t page_bits = 12; struct page_table_entry_t { uint32_t present : 1; - uint32_t rw : 1; - uint32_t usermode : 1; - - uint32_t writeThrough : 1; - - uint32_t cacheDisable : 1; - + uint32_t write_through : 1; + uint32_t cache_disable : 1; uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t pat : 1; - uint32_t global : 1; - uint32_t shared : 1; - uint32_t ignored : 2; - - uint32_t physicalAddress : 20; + uint32_t physical_address : 20; }; struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000; struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000; +int start_paging(physaddr_t start, physaddr_t end, uint32_t *directory, uint32_t *table, uint32_t *identity_table) +{ + physaddr_t p = start; + size_t count = 0; + while(p < end) + { + uint32_t table_entry = p + 3; + int index = p / page_size; + table[index - start / page_size] = table_entry; + identity_table[index] = table_entry; + p += page_size; + count++; + } + directory[0] = ((uint32_t)identity_table) + 3; + directory[1022] = ((uint32_t)table) + 3; + directory[1023] = ((uint32_t)directory) + 3; + asm("mov %0, %%cr3" + : + : "r"(directory)); + asm("mov %%cr0, %%eax \n" + "or $0x80010000, %%eax \n" + "mov %%eax, %%cr0" + : + : + : "eax"); + return count; +} + physaddr_t create_address_space(struct page_stack_t *page_stack) { physaddr_t table = reserve_page(page_stack); @@ -47,12 +64,14 @@ physaddr_t create_address_space(struct page_stack_t *page_stack) return S_OUT_OF_MEMORY; } struct page_table_entry_t buffer = page_directory[0]; - page_directory[0].physicalAddress = table >> page_bits; + page_directory[0].physical_address = table >> page_bits; asm volatile("invlpg 0xFFC00000" :: : "memory"); memset((void *)page_tables, 0, 1022 * 4); page_tables[1022] = page_directory[1022]; - page_tables[1023] = page_directory[1023]; + page_tables[1023].physical_address = table >> page_bits; + page_tables[1023].present = 1; + page_tables[1023].rw = 1; page_directory[0] = buffer; asm volatile("invlpg 0xFFC00000" :: : "memory"); @@ -67,6 +86,11 @@ void load_address_space(physaddr_t table) : "memory"); } +physaddr_t current_address_space() +{ + return page_directory[1023].physical_address << 12; +} + int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int flags) { if ((size_t)page % page_size != 0 || frame % page_size != 0) @@ -82,15 +106,15 @@ int map_page(struct page_stack_t *page_stack, void *page, physaddr_t frame, int { return S_OUT_OF_MEMORY; } - page_directory[directory_index].physicalAddress = new_table >> page_bits; + page_directory[directory_index].physical_address = new_table >> page_bits; page_directory[directory_index].present = 1; - page_directory[directory_index].usermode = 0; + page_directory[directory_index].usermode = (directory_index < 1022) ? 1 : 0; page_directory[directory_index].rw = 1; } - page_tables[table_index].physicalAddress = frame >> 12; + page_tables[table_index].physical_address = frame >> 12; page_tables[table_index].present = 1; - page_tables[table_index].usermode = 1; - page_tables[table_index].rw = 1; + page_tables[table_index].usermode = (flags & PAGE_USERMODE) ? 1 : 0; + page_tables[table_index].rw = (flags & PAGE_RW) ? 1 : 0; asm volatile("invlpg (%0)" : : "r"(page) @@ -112,7 +136,7 @@ physaddr_t unmap_page(void *page) } else { - physaddr_t frame = page_tables[table_index].physicalAddress << page_bits; + physaddr_t frame = page_tables[table_index].physical_address << page_bits; memset(&page_tables[table_index], 0, sizeof(struct page_table_entry_t)); asm volatile("invlpg (%0)" : diff --git a/src/x86/multiboot2.c b/src/x86/multiboot2.c index c692b5f..c8fff69 100644 --- a/src/x86/multiboot2.c +++ b/src/x86/multiboot2.c @@ -36,10 +36,6 @@ void *read_multiboot_table(struct boot_info_t *boot_info, void *table) M_UNAVAILABLE); boot_info->module_count++; } - else - { - printf("WARNING: Too many modules, must skip one.\n"); - } break; case MB_BOOT_COMMAND: strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str); diff --git a/src/x86/putc.c b/src/x86/putc.c index 854751f..fad6f72 100644 --- a/src/x86/putc.c +++ b/src/x86/putc.c @@ -1,4 +1,6 @@ #include "stdio.h" +#include "mmgr.h" +#include "allocator.h" #include enum vga_color_t { @@ -28,12 +30,18 @@ struct cell_t char bg : 4; }; -struct cell_t *screen = (struct cell_t*)0xFF8B8000; +struct cell_t *screen = (struct cell_t*)NULL; size_t cursor = 0; const size_t tab_width = 4; const size_t line_width = 80; +int initialize_screen() +{ + screen = allocate_from_bottom(page_size); + map_page(NULL, screen, 0x000B8000, PAGE_RW); +} + int putchar(int c) { switch(c) diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 0b6ec8c..7f8d281 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -1,49 +1,31 @@ #include "kernel.h" #include "pageallocator.h" +#include "allocator.h" +#include "mmgr.h" #include "multiboot2.h" #include "memorymap.h" #include "apic.h" #include "interrupts.h" -#include "msr.h" #include "stdio.h" #include "string.h" #include "module.h" -#include "isr.h" +#include "config.h" #include #include +extern int _kernel_pstart; +extern int _kernel_pend; +extern int _kernel_start; extern int _kernel_end; -struct apic_registers_t volatile *apic_registers; - -int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) -{ - for (int i = 0; i < 1024; i++) - { - uint32_t pte = i * 4096 + 3; - table[i] = pte; - identityTable[i] = pte; - } - directory[0] = ((uint32_t)identityTable) + 3; - directory[1022] = ((uint32_t)table) + 3; - directory[1023] = ((uint32_t)directory) + 3; - asm("mov %0, %%cr3" - : - : "r"(directory)); - asm("mov %%cr0, %%eax \n" - "or $0x80010000, %%eax \n" - "mov %%eax, %%cr0" - : - : - : "eax"); - return 0; -} +struct kernel_t kernel_state; int initialize(void *multiboot_info) { - static struct interrupt_descriptor_t idt[256]; + initialize_gdt(); + initialize_idt(); + initialize_allocator(&_kernel_end, (void*)0xFFC00000); static struct page_stack_t page_stack; - static struct kernel_t kernel; struct memory_region_t map_array[16]; char bootloader_name[64]; char kernel_parameters[64]; @@ -55,12 +37,19 @@ int initialize(void *multiboot_info) .array = map_array, .size = 0, .capacity = 16}}; + void *multiboot_end = multiboot_info + *(uint32_t*)multiboot_info; multiboot_info += 8; while (multiboot_info != NULL) { multiboot_info = read_multiboot_table(&boot_info, multiboot_info); } - insert_region(&boot_info.map, 0, 1 << 22, M_UNAVAILABLE); + insert_region(&boot_info.map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend, M_UNAVAILABLE); + for(void *p = (void*)&_kernel_end; p < multiboot_end; p += page_size) + { + unmap_page(p); + } + initialize_screen(); + printf("***%s***\n", PACKAGE_STRING); printf("Type\t\tLocation\t\tSize\n"); for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++) { @@ -68,35 +57,25 @@ int initialize(void *multiboot_info) } page_stack.base_pointer = (physaddr_t*)0xFFC00000; page_stack.stack_pointer = (physaddr_t*)0xFFC00000; - page_stack.limit_pointer = (physaddr_t*)0xFF900000; - initialize_page_stack(&page_stack, &boot_info.map, 4096); + page_stack.limit_pointer = (physaddr_t*)0xFFC00000; + initialize_page_stack(&page_stack, &boot_info.map); + apic_enable(page_stack); + apic_registers->divide_config.value = APIC_DIVIDE_128; + apic_registers->lvt_timer.vector = ISR_APIC_TIMER; + apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC; + apic_registers->initial_count.value = 1024*1024*1024; + apic_registers->lvt_timer.mask = 0; + + kernel_state.page_stack = &page_stack; for(int i = 0; i < boot_info.module_count; i++) { - load_module(&kernel, &boot_info.modules[i]); + load_module(&kernel_state, &boot_info.modules[i]); } - // TODO: setup IDT - memset(idt, 0, sizeof(struct interrupt_descriptor_t) * 256); - create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0); - lidt(idt); - // TODO: setup APIC - asm volatile( - "mov $0xFF, %%al;" - "outb %%al, $0xA1;" - "outb %%al, $0x21;" - ::: "al" - ); - apic_enable(); - struct msr_apic_base_t msr; - read_msr(MSR_APIC_BASE, (uint64_t*)&msr); - msr.apic_base = (size_t) &_kernel_end >> 12; - write_msr(MSR_APIC_BASE, (uint64_t*)&msr); - printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); - apic_registers = (struct apic_registers_t*) (msr.apic_base << 12); - // TODO: enter first process + asm("sti"); + while(1) + { + asm("hlt"); + } + // next_process(&kernel_state, NULL); }