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/include/context.h b/include/context.h index 792966c..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__((noreturn)); +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/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 47c3d2e..dcf041c 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,9 @@ 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 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/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/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 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 97% rename from src/x86/interrupts.h rename to include/x86/interrupts.h index 13c01a8..3b78343 100644 --- a/src/x86/interrupts.h +++ b/include/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 }; 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/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 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 a4755d5..4ca80aa 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->resource_table, kernel->page_stack); if(index < 0) { panic("no space left in resource table for module"); @@ -66,14 +66,20 @@ 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; queue_insert(kernel->priority_queue, kernel->active_process); } kernel->active_process = extract_min(kernel->priority_queue); - load_context(kernel->active_process->state); + if(kernel->active_process != NULL) + { + load_address_space(kernel->active_process->page_table); + 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!"); } void panic(const char *message) 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; 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 7867800..dc5b8b3 100644 --- a/src/resource.c +++ b/src/resource.c @@ -1,13 +1,51 @@ #include "resource.h" +#include "mmgr.h" +#include "allocator.h" +#include "types/status.h" -int find_resource_slot(struct resource_table_t *table) +int construct_resource_table(struct resource_table_t *table, struct page_stack_t *page_stack) { - for(int i = 0; i < table->capacity; i++) + 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) + { + 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; } diff --git a/src/x86/apic.c b/src/x86/apic.c index 9698e55..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 @@ -37,7 +37,8 @@ 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; + apic_registers->destination_format.value = 0xFFFFFFFF; } void apic_eoi() diff --git a/src/x86/context.c b/src/x86/context.c index c7262d0..36d6ed0 100644 --- a/src/x86/context.c +++ b/src/x86/context.c @@ -1,32 +1,26 @@ #include "context.h" #include "pageallocator.h" #include "mmgr.h" +#include "string.h" +#include "x86/processstate.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); + 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; - 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; + 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 %0, %%esp; " - "popal; " - "iret; " - :: "r"(context)); -} \ 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 37fe8b6..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, @@ -30,13 +33,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 +78,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,12 +86,10 @@ 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; - 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;" @@ -87,11 +114,23 @@ void load_idt(struct interrupt_descriptor_t *idt) : "r"(&idt_info)); } -void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage) +void load_tr(uint16_t gdt_offset) { - descriptor->offset_1 = (uint32_t) isr & 0xFFFF; - descriptor->offset_2 = (uint32_t) isr >> 16; - descriptor->selector = 8; + 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, uint32_t selector) +{ + 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; @@ -118,7 +157,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 +169,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 +181,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 +193,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 +205,36 @@ 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; + 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_t), SEGMENT_TSS); + 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)); + 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)); } void initialize_idt() @@ -188,14 +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_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); + 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 81dbc4e..5bff31a 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -1,67 +1,71 @@ #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"); 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" : "=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"); } -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"); - 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"); - //... - 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 c8fff69..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" @@ -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, 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 7f8d281..b03ef31 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -2,22 +2,19 @@ #include "pageallocator.h" #include "allocator.h" #include "mmgr.h" -#include "multiboot2.h" +#include "priorityqueue.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) @@ -26,7 +23,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,46 +33,49 @@ 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); } 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; 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; + 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]); } - + apic_enable(page_stack); + /*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;*/ asm("sti"); - while(1) - { - asm("hlt"); - } - // next_process(&kernel_state, NULL); + load_context(next_process(&kernel_state, NULL)); + while(1) asm("hlt"); + }