From 5c4a756176e7a8065d32b9b00e1d63d739930cf2 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 04:24:23 -0500 Subject: [PATCH 01/18] Fixed fatal error while loading modules strcpy() was called with a char instead of a char*, obviously causing a crash --- src/x86/multiboot2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86/multiboot2.c b/src/x86/multiboot2.c index c8fff69..d1f8a2f 100644 --- a/src/x86/multiboot2.c +++ b/src/x86/multiboot2.c @@ -29,7 +29,7 @@ void *read_multiboot_table(struct boot_info_t *boot_info, void *table) { boot_info->modules[boot_info->module_count].start = ((struct multiboot2_module_t*) table)->start; boot_info->modules[boot_info->module_count].end = ((struct multiboot2_module_t*) table)->end; - strcpy(boot_info->modules[boot_info->module_count].str, ((struct multiboot2_module_t*) table)->str); + strcpy(boot_info->modules[boot_info->module_count].str, &((struct multiboot2_module_t*) table)->str); insert_region(&boot_info->map, ((struct multiboot2_module_t*) table)->start, ((struct multiboot2_module_t*) table)->end - ((struct multiboot2_module_t*) table)->start, From 55c5db056ece5a2f53f4e34db563d9403281387b Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 04:56:22 -0500 Subject: [PATCH 02/18] Fixed crash in initialize_context() Function tried to dereference a physical address, causing page fault --- src/x86/context.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/x86/context.c b/src/x86/context.c index c7262d0..9be0f1a 100644 --- a/src/x86/context.c +++ b/src/x86/context.c @@ -4,13 +4,12 @@ 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); + map_page(page_stack, (void*)0xFF7FF000, reserve_page(page_stack), PAGE_RW); + map_page(page_stack, (void*)0xFF7FD000, reserve_page(page_stack), PAGE_RW | PAGE_USERMODE); unmap_page((void*)0xFF7FE000); unmap_page((void*)0xFF7FC000); uint32_t flags; - uint32_t *stack = (uint32_t*)((void*)stack0 - 20); + uint32_t *stack = (uint32_t*)((void*)0xFF800000 - 20); asm("pushf; " "mov (%%esp), %0; " "popf; " From 7c0c5cd8ce052f111c3c9dcb428d8cb45494923e Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 04:57:12 -0500 Subject: [PATCH 03/18] Fixed calculation of kernel binary size in initialize() --- src/x86/quark_x86.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 7f8d281..af3293c 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -26,7 +26,7 @@ int initialize(void *multiboot_info) initialize_idt(); initialize_allocator(&_kernel_end, (void*)0xFFC00000); static struct page_stack_t page_stack; - struct memory_region_t map_array[16]; + struct memory_region_t map_array[24]; char bootloader_name[64]; char kernel_parameters[64]; struct boot_info_t boot_info = { @@ -36,14 +36,14 @@ int initialize(void *multiboot_info) .map = { .array = map_array, .size = 0, - .capacity = 16}}; + .capacity = 24}}; 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, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend, M_UNAVAILABLE); + insert_region(&boot_info.map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend - (physaddr_t)&_kernel_pstart, M_UNAVAILABLE); for(void *p = (void*)&_kernel_end; p < multiboot_end; p += page_size) { unmap_page(p); From a28e58613948613bea79ad00caf227eee7e259a0 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 04:58:02 -0500 Subject: [PATCH 04/18] Fixed missing return in free_page() Method would report "out of memory" when that was not the case --- src/pageallocator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pageallocator.c b/src/pageallocator.c index 51135bf..775a928 100644 --- a/src/pageallocator.c +++ b/src/pageallocator.c @@ -34,6 +34,7 @@ int free_page(struct page_stack_t *stack, physaddr_t location) return S_OUT_OF_BOUNDS; case S_OK: stack->limit_pointer = new_limit; + return S_OK; } } return S_OUT_OF_MEMORY; From 2a5dcd4a0f0706304999d0a29c0f238f74f1ed26 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 04:59:39 -0500 Subject: [PATCH 05/18] Improved get_free_resource_slot() Table now tries to expand itself when no available slots are left --- include/resource.h | 5 +++-- src/kernel.c | 2 +- src/resource.c | 22 ++++++++++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/resource.h b/include/resource.h index 47c3d2e..e841dca 100644 --- a/include/resource.h +++ b/include/resource.h @@ -1,5 +1,6 @@ #pragma once +#include "pageallocator.h" #include "process.h" #include @@ -21,7 +22,7 @@ struct resource_t struct resource_table_t { struct resource_t *array; - size_t capacity; + struct resource_t *limit; }; -int find_resource_slot(struct resource_table_t *table); +int get_free_resource_slot(struct resource_table_t *table, struct page_stack_t *page_stack); diff --git a/src/kernel.c b/src/kernel.c index a4755d5..da597c7 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -52,7 +52,7 @@ int load_module(struct kernel_t *kernel, struct module_t *module) } load_offset += page_size; } - int index = find_resource_slot(kernel); + int index = get_free_resource_slot(kernel, kernel->page_stack); if(index < 0) { panic("no space left in resource table for module"); diff --git a/src/resource.c b/src/resource.c index 7867800..5d32147 100644 --- a/src/resource.c +++ b/src/resource.c @@ -1,13 +1,31 @@ #include "resource.h" +#include "mmgr.h" +#include "allocator.h" +#include "types/status.h" -int find_resource_slot(struct resource_table_t *table) +int get_free_resource_slot(struct resource_table_t *table, struct page_stack_t *page_stack) { - for(int i = 0; i < table->capacity; i++) + if(table == NULL) + { + return -1; + } + size_t capacity = table->limit - table->array; + for(int i = 0; i < capacity; i++) { if(table->array[i].type == RESOURCE_UNAVAILABLE) { return i; } } + void *new_limit = allocate_from_bottom(page_size); + if(new_limit != NULL) + { + if(map_page(page_stack, new_limit, reserve_page(page_stack), PAGE_RW) != S_OK) + { + return -1; + } + table->limit = (struct resource_t*)(new_limit + page_size); + return get_free_resource_slot(table, page_stack); + } return -1; } From 291ed652489af3e261ea8a362c2bcbecf1721306 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 06:25:11 -0500 Subject: [PATCH 06/18] Fixed wrong pointer type in load_module() Kernel passed a pointer to its own state to get_free_resource_slot(), causing its state to be corrupted. next_process() also now loads the address space of the next process before entering it. --- src/kernel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/kernel.c b/src/kernel.c index da597c7..4412f8f 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -52,7 +52,7 @@ int load_module(struct kernel_t *kernel, struct module_t *module) } load_offset += page_size; } - int index = get_free_resource_slot(kernel, kernel->page_stack); + int index = get_free_resource_slot(kernel->resource_table, kernel->page_stack); if(index < 0) { panic("no space left in resource table for module"); @@ -73,6 +73,7 @@ struct process_state_t *next_process(struct kernel_t *kernel, struct process_sta queue_insert(kernel->priority_queue, kernel->active_process); } kernel->active_process = extract_min(kernel->priority_queue); + load_address_space(kernel->active_process->page_table); load_context(kernel->active_process->state); } From 7dd19d0c2a9b52ba2f92c288fec93bc9236a4d84 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 06:25:46 -0500 Subject: [PATCH 07/18] Added constructors for heap and resource table --- include/priorityqueue.h | 3 +++ include/resource.h | 2 ++ src/priorityqueue.c | 18 ++++++++++++++++++ src/resource.c | 20 ++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/include/priorityqueue.h b/include/priorityqueue.h index d259ef6..b15b45f 100644 --- a/include/priorityqueue.h +++ b/include/priorityqueue.h @@ -1,5 +1,6 @@ #pragma once +#include "pageallocator.h" #include "process.h" #include @@ -28,6 +29,8 @@ struct priority_queue_t size_t capacity; }; +int construct_priority_queue(struct priority_queue_t *queue, struct page_stack_t *page_stack); + /** * @brief * diff --git a/include/resource.h b/include/resource.h index e841dca..dcf041c 100644 --- a/include/resource.h +++ b/include/resource.h @@ -25,4 +25,6 @@ struct resource_table_t struct resource_t *limit; }; +int construct_resource_table(struct resource_table_t *table, struct page_stack_t *page_stack); + int get_free_resource_slot(struct resource_table_t *table, struct page_stack_t *page_stack); diff --git a/src/priorityqueue.c b/src/priorityqueue.c index 66a4960..ed57038 100644 --- a/src/priorityqueue.c +++ b/src/priorityqueue.c @@ -1,4 +1,6 @@ #include "priorityqueue.h" +#include "allocator.h" +#include "mmgr.h" #include "types/status.h" void heapify(struct priority_queue_t *queue, size_t i) @@ -25,6 +27,22 @@ void heapify(struct priority_queue_t *queue, size_t i) } } +int construct_priority_queue(struct priority_queue_t *queue, struct page_stack_t *page_stack) +{ + queue->heap = allocate_from_bottom(page_size); + if(queue->heap == NULL) + { + return S_OUT_OF_MEMORY; + } + int status = map_page(page_stack, queue->heap, reserve_page(page_stack), PAGE_RW); + if(status == S_OK) + { + queue->capacity = page_size / sizeof(struct process_t*); + queue->size = 0; + } + return status; +} + struct process_t *extract_min(struct priority_queue_t *queue) { if(queue->size == 0) diff --git a/src/resource.c b/src/resource.c index 5d32147..dc5b8b3 100644 --- a/src/resource.c +++ b/src/resource.c @@ -3,6 +3,26 @@ #include "allocator.h" #include "types/status.h" +int construct_resource_table(struct resource_table_t *table, struct page_stack_t *page_stack) +{ + if(table == NULL) + { + return S_NULL_POINTER; + } + void *table_ptr = allocate_from_bottom(page_size); + if(table_ptr == NULL) + { + return S_OUT_OF_MEMORY; + } + int status = map_page(page_stack, table_ptr, reserve_page(page_stack), PAGE_RW); + if(status == S_OK) + { + table->array = (struct resource_t*)table_ptr; + table->limit = (struct resource_t*)(table_ptr + page_size); + } + return status; +} + int get_free_resource_slot(struct resource_table_t *table, struct page_stack_t *page_stack) { if(table == NULL) From a68a4dff1150ae362259392d5dbf6943a8692deb Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 06:26:03 -0500 Subject: [PATCH 08/18] Added new 'null pointer' status code --- include/types/status.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/types/status.h b/include/types/status.h index 232f39b..4e45672 100644 --- a/include/types/status.h +++ b/include/types/status.h @@ -5,5 +5,6 @@ enum status_t S_OK = 0, S_BAD_SYSCALL, S_OUT_OF_MEMORY, - S_OUT_OF_BOUNDS + S_OUT_OF_BOUNDS, + S_NULL_POINTER }; \ No newline at end of file From 461194fdfd7fbbf531d99ec1836985ad5749660a Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 06:26:56 -0500 Subject: [PATCH 09/18] Fixed initialize_context() Function did not take 'popal' instruction into account when initializing stack --- src/x86/context.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/x86/context.c b/src/x86/context.c index 9be0f1a..9da0bb2 100644 --- a/src/x86/context.c +++ b/src/x86/context.c @@ -1,6 +1,24 @@ #include "context.h" #include "pageallocator.h" #include "mmgr.h" +#include "string.h" + +struct process_state_t +{ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp_temp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t eip; + uint32_t cs; + uint32_t flags; + uint32_t esp; + uint32_t ss; +}; void *initialize_context(void *task_entry, struct page_stack_t *page_stack) { @@ -9,16 +27,18 @@ void *initialize_context(void *task_entry, struct page_stack_t *page_stack) unmap_page((void*)0xFF7FE000); unmap_page((void*)0xFF7FC000); uint32_t flags; - uint32_t *stack = (uint32_t*)((void*)0xFF800000 - 20); + struct process_state_t *stack = (struct process_state_t*)((void*)0xFF800000 - 20 - 8*4); 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; + memset(stack, 0, sizeof(*stack)); + stack->eip = (uint32_t)task_entry; + stack->cs = 27; + stack->flags = flags; + stack->esp = 0xFF7FE000; + stack->ss = 35; + stack->esp_temp = &stack->eax; return (void*)stack; } From b615a8d28602de53ab8d4248d92cc65622d020ed Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 06:27:55 -0500 Subject: [PATCH 10/18] More process in initialize() Function now constructs kernel state and enters a process --- include/allocator.h | 2 +- src/x86/quark_x86.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/allocator.h b/include/allocator.h index a9c0699..ad6172e 100644 --- a/include/allocator.h +++ b/include/allocator.h @@ -6,4 +6,4 @@ 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 +void *allocate_from_top(size_t size); diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index af3293c..cd03450 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -2,6 +2,7 @@ #include "pageallocator.h" #include "allocator.h" #include "mmgr.h" +#include "priorityqueue.h" #include "multiboot2.h" #include "memorymap.h" #include "apic.h" @@ -66,11 +67,20 @@ int initialize(void *multiboot_info) apic_registers->initial_count.value = 1024*1024*1024; apic_registers->lvt_timer.mask = 0; + + static struct priority_queue_t priority_queue; + construct_priority_queue(&priority_queue, &page_stack); + static struct resource_table_t resource_table; + construct_resource_table(&resource_table, &page_stack); kernel_state.page_stack = &page_stack; + kernel_state.resource_table = &resource_table; + kernel_state.priority_queue = &priority_queue; + kernel_state.active_process = NULL; for(int i = 0; i < boot_info.module_count; i++) { load_module(&kernel_state, &boot_info.modules[i]); } + next_process(&kernel_state, NULL); asm("sti"); while(1) From 979344e9420fe409315281d7092e40b5f06cb250 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 06:30:00 -0500 Subject: [PATCH 11/18] next_process() checks if a next process exists Panics if not --- src/kernel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/kernel.c b/src/kernel.c index 4412f8f..f84c88f 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -73,8 +73,12 @@ struct process_state_t *next_process(struct kernel_t *kernel, struct process_sta queue_insert(kernel->priority_queue, kernel->active_process); } kernel->active_process = extract_min(kernel->priority_queue); - load_address_space(kernel->active_process->page_table); - load_context(kernel->active_process->state); + if(kernel->active_process != NULL) + { + load_address_space(kernel->active_process->page_table); + load_context(kernel->active_process->state); + } + panic("no processes available to enter!"); } void panic(const char *message) From 0b84658a6175ae416c2704b8001b65303459ab5c Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sun, 18 Apr 2021 02:07:00 -0500 Subject: [PATCH 12/18] TSS is created and TR loaded in initialize_gdt() --- src/x86/interrupts.c | 69 ++++++++++++++++++++++++++++++++++---------- src/x86/interrupts.h | 1 + 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/x86/interrupts.c b/src/x86/interrupts.c index 37fe8b6..4b02a3c 100644 --- a/src/x86/interrupts.c +++ b/src/x86/interrupts.c @@ -30,13 +30,39 @@ struct gdt_entry_t unsigned int available : 1; unsigned int long_mode : 1; unsigned int big : 1; - unsigned int gran : 1; + unsigned int granularity : 1; unsigned int base_high : 8; } __attribute__ ((packed)); -struct tss_t +struct tss_entry_t { - + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; }; struct interrupt_descriptor_t @@ -49,7 +75,7 @@ struct interrupt_descriptor_t uint16_t dpl : 2; uint16_t present : 1; uint16_t offset_2; -}; +} __attribute__ ((packed)); struct descriptor_table_info_t { @@ -57,8 +83,6 @@ struct descriptor_table_info_t void *location; } __attribute__ ((packed)); -struct tss_t tss; - void load_gdt(struct gdt_entry_t *gdt) { struct descriptor_table_info_t gdt_info; @@ -87,6 +111,15 @@ void load_idt(struct interrupt_descriptor_t *idt) : "r"(&idt_info)); } +void load_tr(uint16_t gdt_offset) +{ + gdt_offset |= 3; + asm("mov %0, %%ax; " + "ltr %%ax; " + : + : "r"(gdt_offset)); +} + void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage) { descriptor->offset_1 = (uint32_t) isr & 0xFFFF; @@ -118,7 +151,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_KERNEL_DATA: descriptor->accessed = 0; @@ -130,7 +163,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_USER_CODE: descriptor->accessed = 0; @@ -142,7 +175,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_USER_DATA: descriptor->accessed = 0; @@ -154,7 +187,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_TSS: descriptor->accessed = 1; @@ -166,20 +199,25 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 0; - descriptor->gran = 0; + descriptor->granularity = 0; } } void initialize_gdt() { static struct gdt_entry_t gdt[gdt_size]; + static struct tss_entry_t tss; 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); + create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS); + memset(&tss, 0, sizeof(tss)); + tss.esp0 = 0xFF800000; + tss.ss0 = 0x10; load_gdt(gdt); + load_tr(5 * sizeof(struct gdt_entry_t)); } void initialize_idt() @@ -191,9 +229,10 @@ void initialize_idt() 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[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_TRAP32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_TRAP32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_TRAP32, 0); + create_interrupt_descriptor(&idt[ISR_PREEMPT], (void*)isr_preempt, 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); diff --git a/src/x86/interrupts.h b/src/x86/interrupts.h index 13c01a8..3b78343 100644 --- a/src/x86/interrupts.h +++ b/src/x86/interrupts.h @@ -25,6 +25,7 @@ enum interrupt_code_t EXCEPTION_VIRTUALIZATION = 20, EXCEPTION_SECURITY = 30, ISR_APIC_TIMER = 64, + ISR_PREEMPT = 65, ISR_AP_START = 127, ISR_SYSCALL = 128 }; From 1171aa2ca3c6b84648b831a315abdf64376c154e Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sun, 18 Apr 2021 02:07:45 -0500 Subject: [PATCH 13/18] Spurious interrupt vector set to 0xFF --- src/x86/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86/apic.c b/src/x86/apic.c index 9698e55..0f990f8 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -37,7 +37,7 @@ void apic_enable(struct page_stact_t *page_stack) 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; + apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x1FF; } void apic_eoi() From c39cbb79cdf58e243db962da45ddc5420c875c55 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sun, 18 Apr 2021 02:10:03 -0500 Subject: [PATCH 14/18] Task contexts now load segment registers correctly Interrupt enable bit set in saved EFLAGS register --- include/context.h | 2 +- src/x86/context.c | 13 +++++++++---- src/x86/isr.c | 24 ++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/include/context.h b/include/context.h index 792966c..c65932e 100644 --- a/include/context.h +++ b/include/context.h @@ -5,4 +5,4 @@ void *initialize_context(void *task_entry, struct page_stack_t *page_stack); -void load_context(struct process_state_t *context) __attribute__((noreturn)); +void load_context(struct process_state_t *context) __attribute__((naked)); diff --git a/src/x86/context.c b/src/x86/context.c index 9da0bb2..69e1481 100644 --- a/src/x86/context.c +++ b/src/x86/context.c @@ -35,7 +35,7 @@ void *initialize_context(void *task_entry, struct page_stack_t *page_stack) memset(stack, 0, sizeof(*stack)); stack->eip = (uint32_t)task_entry; stack->cs = 27; - stack->flags = flags; + stack->flags = flags | 0x200; stack->esp = 0xFF7FE000; stack->ss = 35; stack->esp_temp = &stack->eax; @@ -44,8 +44,13 @@ void *initialize_context(void *task_entry, struct page_stack_t *page_stack) void load_context(struct process_state_t *context) { - asm("mov %0, %%esp; " + asm("mov $0x10, %%ax; " + "mov %%ax, %%ds; " + "mov %%ax, %%es; " + "mov %%ax, %%fs; " + "mov %%ax, %%gs; " + ::: "ax"); + asm("mov 4(%esp), %esp; " "popal; " - "iret; " - :: "r"(context)); + "iret; "); } \ No newline at end of file diff --git a/src/x86/isr.c b/src/x86/isr.c index 81dbc4e..2e95102 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -16,6 +16,12 @@ void isr_division_by_zero(void* frame) void isr_gp_fault(void* frame, unsigned int error) { asm("cli"); + asm("mov $0x10, %%ax; " + "mov %%ax, %%ds; " + "mov %%ax, %%es; " + "mov %%ax, %%fs; " + "mov %%ax, %%gs; " + ::: "ax"); printf("Exception: GP fault, code %08x\n", error); asm("hlt"); } @@ -25,6 +31,12 @@ void isr_page_fault(void* frame, unsigned int error) size_t addr; asm("mov %%cr2, %0" : "=r"(addr)); + asm("mov $0x10, %%ax; " + "mov %%ax, %%ds; " + "mov %%ax, %%es; " + "mov %%ax, %%fs; " + "mov %%ax, %%gs; " + ::: "ax"); printf("Exception: Page fault, code %08x, linear address %08x\n", error, addr); asm("hlt"); } @@ -45,11 +57,19 @@ void isr_timer(void* frame) void isr_preempt(void* frame) { - asm("pushal;" - "mov %esp, %ebp"); + asm("pushal; " + "mov %esp, %ebp; "); + asm("mov $0x10, %%ax; " + "mov %%ax, %%ds; " + "mov %%ax, %%es; " + "mov %%ax, %%fs; " + "mov %%ax, %%gs; " + ::: "ax"); struct process_state_t *process_state; asm("mov %%ebp, %0" : "=r"(process_state)); + printf("Preempted process %08x.\n", kernel_state.active_process); + apic_eoi(); next_process(&kernel_state, process_state); } From 625bbb04a8f6d9d29e002c0b99c24280b6efeefa Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sun, 18 Apr 2021 02:10:33 -0500 Subject: [PATCH 15/18] Debug message printed before loading task context --- src/kernel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kernel.c b/src/kernel.c index f84c88f..f1b5c9d 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -75,6 +75,7 @@ struct process_state_t *next_process(struct kernel_t *kernel, struct process_sta kernel->active_process = extract_min(kernel->priority_queue); if(kernel->active_process != NULL) { + printf("entering process %08x\n\tcr3=%08x state=%08x.\n", kernel->active_process, kernel->active_process->page_table, kernel->active_process->state); load_address_space(kernel->active_process->page_table); load_context(kernel->active_process->state); } From 40da57e233fa5f08f18145077a655512c78db610 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sun, 18 Apr 2021 02:10:56 -0500 Subject: [PATCH 16/18] APIC enabled after running kernel state constructors --- src/x86/quark_x86.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index cd03450..a75b381 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -60,14 +60,6 @@ int initialize(void *multiboot_info) page_stack.stack_pointer = (physaddr_t*)0xFFC00000; 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; - - static struct priority_queue_t priority_queue; construct_priority_queue(&priority_queue, &page_stack); static struct resource_table_t resource_table; @@ -80,12 +72,14 @@ int initialize(void *multiboot_info) { load_module(&kernel_state, &boot_info.modules[i]); } - next_process(&kernel_state, NULL); - + apic_enable(page_stack); + apic_registers->divide_config.value = APIC_DIVIDE_16; + apic_registers->lvt_timer.vector = ISR_PREEMPT; + apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC; + apic_registers->lvt_timer.mask = 0; + apic_registers->initial_count.value = 1024*1024*128; asm("sti"); - while(1) - { - asm("hlt"); - } - // next_process(&kernel_state, NULL); + next_process(&kernel_state, NULL); + while(1) asm("hlt"); + } From 086dfe546a24ac8c41ab1db05fb1db56f0b57a8c Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sun, 18 Apr 2021 08:00:56 -0500 Subject: [PATCH 17/18] GRUB config file loads modules at boot --- rootfs/boot/grub/grub.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rootfs/boot/grub/grub.cfg b/rootfs/boot/grub/grub.cfg index a731acc..49fa9ae 100644 --- a/rootfs/boot/grub/grub.cfg +++ b/rootfs/boot/grub/grub.cfg @@ -1,3 +1,5 @@ menuentry "Quark OS" { multiboot2 /apps/quark-kernel + module2 /apps/quark-testmod + module2 /apps/quark-testmod } \ No newline at end of file From 5efc389935a5b7c352fa945bc28c8ba1d386558e Mon Sep 17 00:00:00 2001 From: ngiddings Date: Mon, 19 Apr 2021 03:40:33 -0500 Subject: [PATCH 18/18] Finished basic task switching mechansim PCB is local to a process's address space. Context switches are written in assembly. Moved x86 headers to include/x86 --- include/context.h | 4 +- include/kernel.h | 2 +- include/system.h | 7 ++++ {src => include}/x86/apic.h | 0 {src => include}/x86/interrupts.h | 0 include/x86/isr.h | 27 +++++++++++++ {src => include}/x86/msr.h | 0 {src => include}/x86/multiboot2.h | 0 include/x86/processstate.h | 21 ++++++++++ src/Makefile.am | 2 + src/kernel.c | 6 +-- src/x86/apic.c | 5 ++- src/x86/context.c | 54 ++++++------------------- src/x86/contextswitch.S | 67 +++++++++++++++++++++++++++++++ src/x86/entry.S | 24 ++++++----- src/x86/interrupts.c | 50 +++++++++++++++-------- src/x86/isr.c | 66 ++++++++++++------------------ src/x86/isr.h | 28 ------------- src/x86/msr.c | 2 +- src/x86/multiboot2.c | 2 +- src/x86/preempt.S | 17 ++++++++ src/x86/quark_x86.c | 24 +++++------ 22 files changed, 246 insertions(+), 162 deletions(-) create mode 100644 include/system.h rename {src => include}/x86/apic.h (100%) rename {src => include}/x86/interrupts.h (100%) create mode 100644 include/x86/isr.h rename {src => include}/x86/msr.h (100%) rename {src => include}/x86/multiboot2.h (100%) create mode 100644 include/x86/processstate.h create mode 100644 src/x86/contextswitch.S delete mode 100644 src/x86/isr.h create mode 100644 src/x86/preempt.S diff --git a/include/context.h b/include/context.h index c65932e..8f321d9 100644 --- a/include/context.h +++ b/include/context.h @@ -5,4 +5,6 @@ void *initialize_context(void *task_entry, struct page_stack_t *page_stack); -void load_context(struct process_state_t *context) __attribute__((naked)); +void save_context(struct process_state_t *context, void *ptr); + +void load_context(struct process_state_t *context); diff --git a/include/kernel.h b/include/kernel.h index be6095d..635c5f8 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -26,6 +26,6 @@ size_t do_syscall(struct kernel_t *kernel, enum syscall_id_t id, size_t arg1, si 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)); +struct process_state_t *next_process(struct kernel_t *kernel, struct process_state_t *prev_state); void panic(const char *message) __attribute__ ((noreturn)); diff --git a/include/system.h b/include/system.h new file mode 100644 index 0000000..383533c --- /dev/null +++ b/include/system.h @@ -0,0 +1,7 @@ +#pragma once + +extern int stack_top; +extern int _kernel_pstart; +extern int _kernel_pend; +extern int _kernel_start; +extern int _kernel_end; diff --git a/src/x86/apic.h b/include/x86/apic.h similarity index 100% rename from src/x86/apic.h rename to include/x86/apic.h diff --git a/src/x86/interrupts.h b/include/x86/interrupts.h similarity index 100% rename from src/x86/interrupts.h rename to include/x86/interrupts.h diff --git a/include/x86/isr.h b/include/x86/isr.h new file mode 100644 index 0000000..a2377da --- /dev/null +++ b/include/x86/isr.h @@ -0,0 +1,27 @@ +#pragma once + +struct interrupt_frame_t; + +__attribute__ ((interrupt)) +void isr_generic(struct interrupt_frame_t *frame); + +__attribute__ ((interrupt)) +void isr_division_by_zero(struct interrupt_frame_t *frame); + +__attribute__ ((interrupt)) +void isr_gp_fault(struct interrupt_frame_t *frame, unsigned int error); + +__attribute__ ((interrupt)) +void isr_page_fault(struct interrupt_frame_t *frame, unsigned int error); + +__attribute__ ((interrupt)) +void isr_double_fault(struct interrupt_frame_t *frame, unsigned int error); + +__attribute__ ((interrupt)) +void isr_timer(struct interrupt_frame_t *frame); + +__attribute__ ((naked)) +void isr_preempt(struct interrupt_frame_t *frame); + +__attribute__ ((interrupt)) +void isr_syscall(struct interrupt_frame_t *frame); \ No newline at end of file diff --git a/src/x86/msr.h b/include/x86/msr.h similarity index 100% rename from src/x86/msr.h rename to include/x86/msr.h diff --git a/src/x86/multiboot2.h b/include/x86/multiboot2.h similarity index 100% rename from src/x86/multiboot2.h rename to include/x86/multiboot2.h diff --git a/include/x86/processstate.h b/include/x86/processstate.h new file mode 100644 index 0000000..a991ef1 --- /dev/null +++ b/include/x86/processstate.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#define PCB_LOCATION 0x800 + +struct process_state_t +{ + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t ss; + uint32_t esp; + uint32_t cs; + uint32_t eip; + uint32_t flags; +}; diff --git a/src/Makefile.am b/src/Makefile.am index e55eca4..8f5c591 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,8 @@ quark_kernel_SOURCES += x86/mmgr.c \ x86/isr.c \ x86/msr.c \ x86/context.c \ + x86/contextswitch.S \ + x86/preempt.S \ x86/quark_x86.c \ x86/entry.S quark_kernel_LDFLAGS += -T x86/linker.ld diff --git a/src/kernel.c b/src/kernel.c index f1b5c9d..4ca80aa 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -66,7 +66,7 @@ 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) -{ +{ if(prev_state != NULL) { kernel->active_process->state = prev_state; @@ -75,9 +75,9 @@ struct process_state_t *next_process(struct kernel_t *kernel, struct process_sta kernel->active_process = extract_min(kernel->priority_queue); if(kernel->active_process != NULL) { - printf("entering process %08x\n\tcr3=%08x state=%08x.\n", kernel->active_process, kernel->active_process->page_table, kernel->active_process->state); load_address_space(kernel->active_process->page_table); - load_context(kernel->active_process->state); + printf("entering process %08x cr3=%08x state=%08x.\n", kernel->active_process, kernel->active_process->page_table, kernel->active_process->state); + return kernel->active_process->state; } panic("no processes available to enter!"); } diff --git a/src/x86/apic.c b/src/x86/apic.c index 0f990f8..8eb82da 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,7 +1,7 @@ #include "mmgr.h" #include "allocator.h" -#include "apic.h" -#include "msr.h" +#include "x86/apic.h" +#include "x86/msr.h" #include "stdio.h" #include @@ -38,6 +38,7 @@ void apic_enable(struct page_stact_t *page_stack) 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 | 0x1FF; + apic_registers->destination_format.value = 0xFFFFFFFF; } void apic_eoi() diff --git a/src/x86/context.c b/src/x86/context.c index 69e1481..36d6ed0 100644 --- a/src/x86/context.c +++ b/src/x86/context.c @@ -2,55 +2,25 @@ #include "pageallocator.h" #include "mmgr.h" #include "string.h" - -struct process_state_t -{ - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp_temp; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - uint32_t eip; - uint32_t cs; - uint32_t flags; - uint32_t esp; - uint32_t ss; -}; +#include "x86/processstate.h" void *initialize_context(void *task_entry, struct page_stack_t *page_stack) { - map_page(page_stack, (void*)0xFF7FF000, reserve_page(page_stack), PAGE_RW); - map_page(page_stack, (void*)0xFF7FD000, reserve_page(page_stack), PAGE_RW | PAGE_USERMODE); + map_page(page_stack, (void*)NULL, reserve_page(page_stack), PAGE_RW); + map_page(page_stack, (void*)0xFF7FF000, reserve_page(page_stack), PAGE_RW | PAGE_USERMODE); unmap_page((void*)0xFF7FE000); - unmap_page((void*)0xFF7FC000); uint32_t flags; - struct process_state_t *stack = (struct process_state_t*)((void*)0xFF800000 - 20 - 8*4); asm("pushf; " "mov (%%esp), %0; " "popf; " : "=r"(flags)); - memset(stack, 0, sizeof(*stack)); - stack->eip = (uint32_t)task_entry; - stack->cs = 27; - stack->flags = flags | 0x200; - stack->esp = 0xFF7FE000; - stack->ss = 35; - stack->esp_temp = &stack->eax; - return (void*)stack; + struct process_state_t *state = (struct process_state_t*)PCB_LOCATION; + memset(NULL, 0, page_size); + state->cs = 0x1B; + state->eip = (uint32_t)task_entry; + state->flags = (flags & ~0xFD) | 0x200; + state->ss = 0x23; + state->esp = 0xFF800000; + state->ebp = 0xFF800000; + return (void*)state; } - -void load_context(struct process_state_t *context) -{ - asm("mov $0x10, %%ax; " - "mov %%ax, %%ds; " - "mov %%ax, %%es; " - "mov %%ax, %%fs; " - "mov %%ax, %%gs; " - ::: "ax"); - asm("mov 4(%esp), %esp; " - "popal; " - "iret; "); -} \ No newline at end of file diff --git a/src/x86/contextswitch.S b/src/x86/contextswitch.S new file mode 100644 index 0000000..79c48ba --- /dev/null +++ b/src/x86/contextswitch.S @@ -0,0 +1,67 @@ +.section .text + +/* + * save_context(struct process_state_t *context, struct interrupt_frame_t *frame) + */ + .global save_context + .type save_context, @function +save_context: + push %edi + push %esi + push %eax + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov 16(%esp), %eax + mov %ebx, 0x04(%eax) + mov %ecx, 0x08(%eax) + mov %edx, 0x0C(%eax) + mov %edi, 0x10(%eax) + mov %esi, 0x14(%eax) + mov %ebp, 0x18(%eax) + mov %eax, %edi + pop %eax + mov %eax, 0x00(%edi) + mov 16(%esp), %esi + mov 0x10(%esi), %eax + mov %eax, 0x1C(%edi) + mov 0x0C(%esi), %eax + mov %eax, 0x20(%edi) + mov 0x08(%esi), %eax + mov %eax, 0x2C(%edi) + mov 0x04(%esi), %eax + mov %eax, 0x24(%edi) + mov 0x00(%esi), %eax + mov %eax, 0x28(%edi) + pop %esi + pop %edi + ret + +/* + * load_context(struct process_state_t *context) + */ +.global load_context +.type load_context, @function +load_context: + mov 4(%esp), %eax + push 0x1C(%eax) + push 0x20(%eax) + push 0x2C(%eax) + push 0x24(%eax) + push 0x28(%eax) + push 0x00(%eax) + mov 0x04(%eax), %ebx + mov 0x08(%eax), %ecx + mov 0x0C(%eax), %edx + mov 0x10(%eax), %edi + mov 0x14(%eax), %esi + mov 0x18(%eax), %ebp + mov 0x1C(%eax), %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + pop %eax + iret \ No newline at end of file diff --git a/src/x86/entry.S b/src/x86/entry.S index 24aad6a..4ef8462 100755 --- a/src/x86/entry.S +++ b/src/x86/entry.S @@ -97,18 +97,20 @@ _multibootHeaderEnd: .section .bss .align 16 -stackBottom: +stack_bottom: .skip 8192 -stackTop: +.global stack_top +stack_top: .align 4096 -_tempPgDir: +.global default_page_dir +default_page_dir: .skip 4096 -_tempIdentityMap: +default_page_table: .skip 4096 -_tempPgTable: +identity_map: .skip 4096 - + .section .text .global _start .type _start, @function @@ -121,21 +123,21 @@ _start: jne .err # Initialize stack in physical address space - mov $stackTop, %esp + mov $stack_top, %esp sub $BASE_DIFF, %esp # Push physical address of identity map - mov $_tempIdentityMap, %eax + mov $identity_map, %eax sub $BASE_DIFF, %eax push %eax # Push physical address of page table - mov $_tempPgTable, %eax + mov $default_page_table, %eax sub $BASE_DIFF, %eax push %eax # Push physical address of page directory - mov $_tempPgDir, %eax + mov $default_page_dir, %eax sub $BASE_DIFF, %eax push %eax @@ -165,7 +167,7 @@ _start: mov %eax, %cr3 # Initialize stack in virtual memory - mov $stackTop, %esp + mov $stack_top, %esp # Change EBX to point to the virtual address of the multiboot info # If the new pointer is out-of-bounds, error diff --git a/src/x86/interrupts.c b/src/x86/interrupts.c index 4b02a3c..ff0f9f9 100644 --- a/src/x86/interrupts.c +++ b/src/x86/interrupts.c @@ -1,11 +1,14 @@ -#include "interrupts.h" -#include "isr.h" +#include "x86/interrupts.h" +#include "x86/isr.h" #include "string.h" +#include "system.h" #include #define idt_size 256 #define gdt_size 6 +extern int default_page_dir; + enum segment_type_t { SEGMENT_KERNEL_CODE, @@ -86,7 +89,7 @@ struct descriptor_table_info_t void load_gdt(struct gdt_entry_t *gdt) { struct descriptor_table_info_t gdt_info; - gdt_info.size = sizeof(struct gdt_entry_t) * 6 - 1; + gdt_info.size = sizeof(struct gdt_entry_t) * 7 - 1; gdt_info.location = (void *)gdt; asm("lgdt (%0);" "jmp $8, $.ldcs;" @@ -120,11 +123,14 @@ void load_tr(uint16_t gdt_offset) : "r"(gdt_offset)); } -void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage) +void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage, uint32_t selector) { - descriptor->offset_1 = (uint32_t) isr & 0xFFFF; - descriptor->offset_2 = (uint32_t) isr >> 16; - descriptor->selector = 8; + if(type != INTERRPUT_TASK32) + { + descriptor->offset_1 = (uint32_t) isr & 0xFFFF; + descriptor->offset_2 = (uint32_t) isr >> 16; + } + descriptor->selector = selector; descriptor->zero = 0; descriptor->type = type; descriptor->storage = 0; @@ -207,15 +213,26 @@ void initialize_gdt() { static struct gdt_entry_t gdt[gdt_size]; static struct tss_entry_t tss; + static struct tss_entry_t double_fault_tss; 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_entry_t) - 1, SEGMENT_TSS); + create_segment_descriptor(&gdt[6], (size_t)&double_fault_tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS); memset(&tss, 0, sizeof(tss)); - tss.esp0 = 0xFF800000; + memset(&double_fault_tss, 0, sizeof(tss)); + tss.esp0 = &stack_top; tss.ss0 = 0x10; + double_fault_tss.esp0 = &stack_top; + double_fault_tss.ss0 = 0x10; + double_fault_tss.esp = &stack_top; + double_fault_tss.cs = 0x08; + double_fault_tss.ds = 0x10; + double_fault_tss.ss = 0x10; + double_fault_tss.cr3 = &default_page_dir; + double_fault_tss.eip = (void*)isr_double_fault; load_gdt(gdt); load_tr(5 * sizeof(struct gdt_entry_t)); } @@ -226,15 +243,14 @@ void initialize_idt() 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[i], (void*)isr_generic, INTERRPUT_INT32, 0, 8); } - 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_TRAP32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_TRAP32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_TRAP32, 0); - create_interrupt_descriptor(&idt[ISR_PREEMPT], (void*)isr_preempt, 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); + create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0, 8); + create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_TRAP32, 0, 8); + create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_TRAP32, 0, 8); + create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_TASK32, 0, 8 * 6); + create_interrupt_descriptor(&idt[ISR_PREEMPT], (void*)isr_preempt, INTERRPUT_INT32, 3, 8); + create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0, 8); + create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0, 8); load_idt(idt); } diff --git a/src/x86/isr.c b/src/x86/isr.c index 2e95102..5bff31a 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -1,32 +1,43 @@ #include "kernel.h" -#include "isr.h" +#include "x86/isr.h" #include "stdio.h" -#include "apic.h" +#include "x86/apic.h" +#include "x86/processstate.h" +#include "context.h" -void isr_generic(void* frame) +struct interrupt_frame_t +{ + size_t eip; + size_t cs; + size_t eflags; + size_t esp; + size_t ss; +}; + +void isr_generic(struct interrupt_frame_t *frame) { printf("Generic interrupt.\n"); } -void isr_division_by_zero(void* frame) +void isr_division_by_zero(struct interrupt_frame_t *frame) { printf("Exception: Division by zero\n"); } -void isr_gp_fault(void* frame, unsigned int error) +void isr_gp_fault(struct interrupt_frame_t *frame, unsigned int error) { asm("cli"); asm("mov $0x10, %%ax; " "mov %%ax, %%ds; " "mov %%ax, %%es; " "mov %%ax, %%fs; " - "mov %%ax, %%gs; " - ::: "ax"); + "mov %%ax, %%gs; " :: + : "ax"); printf("Exception: GP fault, code %08x\n", error); asm("hlt"); } -void isr_page_fault(void* frame, unsigned int error) +void isr_page_fault(struct interrupt_frame_t *frame, unsigned int error) { size_t addr; asm("mov %%cr2, %0" @@ -35,53 +46,26 @@ void isr_page_fault(void* frame, unsigned int error) "mov %%ax, %%ds; " "mov %%ax, %%es; " "mov %%ax, %%fs; " - "mov %%ax, %%gs; " - ::: "ax"); + "mov %%ax, %%gs; " :: + : "ax"); printf("Exception: Page fault, code %08x, linear address %08x\n", error, addr); asm("hlt"); } -void isr_double_fault(void* frame, unsigned int error) +void isr_double_fault(struct interrupt_frame_t *frame, unsigned int error) { asm("cli"); - + printf("Exception: Double fault (!!), code %08x\n", error); asm("hlt"); } -void isr_timer(void* frame) +void isr_timer(struct interrupt_frame_t *frame) { printf("Timer tick.\n"); apic_eoi(); } -void isr_preempt(void* frame) +void isr_syscall(struct interrupt_frame_t *frame) { - asm("pushal; " - "mov %esp, %ebp; "); - asm("mov $0x10, %%ax; " - "mov %%ax, %%ds; " - "mov %%ax, %%es; " - "mov %%ax, %%fs; " - "mov %%ax, %%gs; " - ::: "ax"); - struct process_state_t *process_state; - asm("mov %%ebp, %0" - : "=r"(process_state)); - printf("Preempted process %08x.\n", kernel_state.active_process); - apic_eoi(); - next_process(&kernel_state, process_state); -} - -void isr_ap_start(void* frame) -{ - asm(".code16"); - //... - asm(".code32"); - // do something useful -} - -void isr_syscall(void* frame) -{ - } \ No newline at end of file diff --git a/src/x86/isr.h b/src/x86/isr.h deleted file mode 100644 index b4d8d9b..0000000 --- a/src/x86/isr.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -__attribute__ ((interrupt)) -void isr_generic(void* frame); - -__attribute__ ((interrupt)) -void isr_division_by_zero(void* frame); - -__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); - -__attribute__ ((interrupt)) -void isr_timer(void* frame); - -__attribute__ ((naked)) -void isr_preempt(void* frame); - -__attribute__ ((naked)) -void isr_ap_start(void* frame); - -__attribute__ ((interrupt)) -void isr_syscall(void* frame); \ No newline at end of file diff --git a/src/x86/msr.c b/src/x86/msr.c index 4182a2d..c11aa91 100644 --- a/src/x86/msr.c +++ b/src/x86/msr.c @@ -1,4 +1,4 @@ -#include "msr.h" +#include "x86/msr.h" void read_msr(enum msr_id_t msr_addr, uint64_t *value) { diff --git a/src/x86/multiboot2.c b/src/x86/multiboot2.c index d1f8a2f..a41fad5 100644 --- a/src/x86/multiboot2.c +++ b/src/x86/multiboot2.c @@ -1,4 +1,4 @@ -#include "multiboot2.h" +#include "x86/multiboot2.h" #include "stdio.h" #include "string.h" diff --git a/src/x86/preempt.S b/src/x86/preempt.S new file mode 100644 index 0000000..47cc4c2 --- /dev/null +++ b/src/x86/preempt.S @@ -0,0 +1,17 @@ +.section .text + +.global isr_preempt +.type isr_preempt, @function +isr_preempt: + cli + push %esp + push $0x800 + call save_context + sub $8, %esp + push $0x800 + push $kernel_state + call next_process + sub $8, %esp + push %eax + call load_context + \ No newline at end of file diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index a75b381..b03ef31 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -3,22 +3,18 @@ #include "allocator.h" #include "mmgr.h" #include "priorityqueue.h" -#include "multiboot2.h" +#include "x86/multiboot2.h" #include "memorymap.h" -#include "apic.h" -#include "interrupts.h" +#include "x86/apic.h" +#include "x86/interrupts.h" #include "stdio.h" #include "string.h" #include "module.h" +#include "system.h" #include "config.h" #include #include -extern int _kernel_pstart; -extern int _kernel_pend; -extern int _kernel_start; -extern int _kernel_end; - struct kernel_t kernel_state; int initialize(void *multiboot_info) @@ -51,11 +47,11 @@ int initialize(void *multiboot_info) } initialize_screen(); printf("***%s***\n", PACKAGE_STRING); - printf("Type\t\tLocation\t\tSize\n"); + /*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++) { printf("%i\t\t\t%08x\t\t%u\n", boot_info.map.array[i].type, boot_info.map.array[i].location, boot_info.map.array[i].size); - } + }*/ page_stack.base_pointer = (physaddr_t*)0xFFC00000; page_stack.stack_pointer = (physaddr_t*)0xFFC00000; page_stack.limit_pointer = (physaddr_t*)0xFFC00000; @@ -73,13 +69,13 @@ int initialize(void *multiboot_info) load_module(&kernel_state, &boot_info.modules[i]); } apic_enable(page_stack); - apic_registers->divide_config.value = APIC_DIVIDE_16; - apic_registers->lvt_timer.vector = ISR_PREEMPT; + /*apic_registers->divide_config.value = APIC_DIVIDE_1; apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC; + apic_registers->lvt_timer.vector = ISR_PREEMPT; apic_registers->lvt_timer.mask = 0; - apic_registers->initial_count.value = 1024*1024*128; + apic_registers->initial_count.value = 1024*1024;*/ asm("sti"); - next_process(&kernel_state, NULL); + load_context(next_process(&kernel_state, NULL)); while(1) asm("hlt"); }