From 50fcaa26738a4701aaab79d4f5b5637914f52bfe Mon Sep 17 00:00:00 2001 From: ngiddings Date: Thu, 15 Apr 2021 07:22:01 -0500 Subject: [PATCH 01/17] Added timer ISR --- src/x86/isr.c | 8 ++++++++ src/x86/isr.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/x86/isr.c b/src/x86/isr.c index 8d36841..339a1f8 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -1,5 +1,6 @@ #include "isr.h" #include "stdio.h" +#include "apic.h" __attribute__ ((interrupt)) void isr_division_by_zero(void* frame) @@ -25,6 +26,13 @@ void isr_double_fault(void* frame, unsigned int error) asm("hlt"); } +__attribute__ ((interrupt)) +void isr_timer(void* frame) +{ + printf("Timer tick.\n"); + apic_eoi(); +} + __attribute__ ((naked)) void isr_ap_start(void* frame) { diff --git a/src/x86/isr.h b/src/x86/isr.h index 1725d53..272e224 100644 --- a/src/x86/isr.h +++ b/src/x86/isr.h @@ -12,6 +12,9 @@ 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_ap_start(void* frame); From 0c5d18ddc0457991dc647a0477efb65a133a1a31 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Thu, 15 Apr 2021 07:22:26 -0500 Subject: [PATCH 02/17] Added enum for timer interrupt vector --- src/x86/interrupts.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x86/interrupts.h b/src/x86/interrupts.h index d8ff3b9..96db47c 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 }; From 3e73c7c0ac4eadff9006cf76d00aaf921cb6c365 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Thu, 15 Apr 2021 07:22:58 -0500 Subject: [PATCH 03/17] Fixed APIC register mapping --- src/x86/apic.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/x86/apic.c b/src/x86/apic.c index 9d6d113..c725790 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,8 +1,18 @@ +#include "mmgr.h" #include "apic.h" +#include "msr.h" +#include -void apic_enable() +extern int _kernel_end; + +void apic_enable(struct page_stact_t *page_stack) { - + struct msr_apic_base_t msr; + read_msr(MSR_APIC_BASE, (uint64_t*)&msr); + map_page(page_stack, &_kernel_end, msr.apic_base << 12, 0); + printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); + apic_registers = (struct apic_registers_t*)&_kernel_end; + apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100; } void apic_eoi() @@ -32,4 +42,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 +} From 8e6589b472e1fed1745e8bcca3b29b074849c188 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Thu, 15 Apr 2021 07:23:19 -0500 Subject: [PATCH 04/17] Added some test code to setup a timer --- src/x86/quark_x86.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 0b6ec8c..69c3618 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -9,6 +9,7 @@ #include "string.h" #include "module.h" #include "isr.h" +#include "config.h" #include #include @@ -41,6 +42,7 @@ int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) int initialize(void *multiboot_info) { + printf("***%s***\n", PACKAGE_STRING); static struct interrupt_descriptor_t idt[256]; static struct page_stack_t page_stack; static struct kernel_t kernel; @@ -74,29 +76,33 @@ int initialize(void *multiboot_info) { load_module(&kernel, &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_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); 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); + apic_enable(page_stack); + printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); + printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); + + 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*512; + apic_registers->lvt_timer.mask = 0; + printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); + printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); + asm("sti"); + while(1) asm("hlt"); // TODO: enter first process } From 6138766c49443c11b45a8d61fc3a741564e1145d Mon Sep 17 00:00:00 2001 From: ngiddings Date: Fri, 16 Apr 2021 01:45:40 -0500 Subject: [PATCH 05/17] Added sequence to remap PIC Wrote GDT code in C Added routines to initialize GDT and IDT --- src/x86/apic.c | 22 ++++++ src/x86/entry.S | 34 +-------- src/x86/interrupts.c | 178 ++++++++++++++++++++++++++++++++++++++++++- src/x86/interrupts.h | 16 +--- src/x86/isr.c | 14 +++- src/x86/isr.h | 3 + src/x86/quark_x86.c | 30 ++------ 7 files changed, 223 insertions(+), 74 deletions(-) diff --git a/src/x86/apic.c b/src/x86/apic.c index c725790..399ab41 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,12 +1,34 @@ #include "mmgr.h" #include "apic.h" #include "msr.h" +#include "stdio.h" #include extern int _kernel_end; 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); map_page(page_stack, &_kernel_end, msr.apic_base << 12, 0); diff --git a/src/x86/entry.S b/src/x86/entry.S index 6ec1c8b..bb4a2ed 100755 --- a/src/x86/entry.S +++ b/src/x86/entry.S @@ -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 @@ -170,7 +153,7 @@ _start: push %eax # Load physical address of startPaging() - mov $startPaging, %eax + mov $start_paging, %eax sub $BASE_DIFF, %eax # Initialize paging @@ -180,8 +163,6 @@ _start: 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,19 +171,6 @@ _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 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 96db47c..13c01a8 100644 --- a/src/x86/interrupts.h +++ b/src/x86/interrupts.h @@ -38,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 339a1f8..80fd862 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -2,6 +2,12 @@ #include "stdio.h" #include "apic.h" +__attribute__ ((interrupt)) +void isr_generic(void* frame) +{ + printf("Generic interrupt.\n"); +} + __attribute__ ((interrupt)) void isr_division_by_zero(void* frame) { @@ -11,18 +17,22 @@ void isr_division_by_zero(void* frame) __attribute__ ((interrupt)) void isr_gp_fault(void* frame, unsigned int error) { - + asm("cli"); + printf("Exception: GP fault, code %08x\n", error); + asm("hlt"); } __attribute__ ((interrupt)) void isr_page_fault(void* frame, unsigned int error) { - + printf("Exception: Page fault\n"); } __attribute__ ((interrupt)) void isr_double_fault(void* frame, unsigned int error) { + asm("cli"); + printf("Exception: Double fault (!!), code %08x\n", error); asm("hlt"); } diff --git a/src/x86/isr.h b/src/x86/isr.h index 272e224..c5a3914 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); diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 69c3618..474fa5e 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -17,7 +17,7 @@ extern int _kernel_end; struct apic_registers_t volatile *apic_registers; -int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) +int start_paging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) { for (int i = 0; i < 1024; i++) { @@ -42,8 +42,9 @@ int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) int initialize(void *multiboot_info) { + initialize_gdt(); + initialize_idt(); printf("***%s***\n", PACKAGE_STRING); - static struct interrupt_descriptor_t idt[256]; static struct page_stack_t page_stack; static struct kernel_t kernel; struct memory_region_t map_array[16]; @@ -76,33 +77,18 @@ int initialize(void *multiboot_info) { load_module(&kernel, &boot_info.modules[i]); } - 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_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); - lidt(idt); - asm volatile( - "mov $0xFF, %%al;" - "outb %%al, $0xA1;" - "outb %%al, $0x21;" - ::: "al" - ); apic_enable(page_stack); - printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); - printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); - 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*512; + apic_registers->initial_count.value = 1024*1024*1024; apic_registers->lvt_timer.mask = 0; printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); asm("sti"); - while(1) asm("hlt"); + while(1) + { + asm("hlt"); + } // TODO: enter first process } From 8896c4313f6fcb3cced59c9114ff06efa9cc6bf6 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:45:24 -0500 Subject: [PATCH 06/17] Fixed glitch in trim_map() Entries were not modified properly; only removals worked correctly. --- src/memorymap.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) 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; } From 6c047c63432618f02f94b706432949555d0b0246 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:49:38 -0500 Subject: [PATCH 07/17] Remvoed unused dymamic memory allocator --- src/allocator.cpp | 102 ---------------------------------------------- src/allocator.hpp | 42 ------------------- 2 files changed, 144 deletions(-) delete mode 100644 src/allocator.cpp delete mode 100644 src/allocator.hpp 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 From fdcdb9acab60460000875d561d130ee37c9f8fca Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:52:16 -0500 Subject: [PATCH 08/17] Updated virtual memory manager Added page flags Added function current_address_space() Fixed create_address_space() Renamed some fields in page_table_entry_t to fit naming scheme --- include/mmgr.h | 20 +++++++++++++++++++- src/x86/mmgr.c | 40 ++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 23 deletions(-) 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/src/x86/mmgr.c b/src/x86/mmgr.c index a12be9f..c4edb6a 100644 --- a/src/x86/mmgr.c +++ b/src/x86/mmgr.c @@ -11,28 +11,17 @@ 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; @@ -47,12 +36,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 +58,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 +78,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 +108,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)" : From 2d6fa0d163a566271c0487cc9f645c04c2fe7468 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:55:05 -0500 Subject: [PATCH 09/17] Added functions to create and load process contexts --- include/context.h | 8 ++++++++ src/x86/context.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 include/context.h create mode 100644 src/x86/context.c 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/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 From 9630d0a39636f267b121f55f5e8ad8e6956697e8 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:56:44 -0500 Subject: [PATCH 10/17] Added load_program() function Builds program image from ELF file in memory Fixed multiple definition error caused by constant in elf.h: moved contant to elf.c --- include/elf.h | 13 +++++++------ src/elf.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/elf.c 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/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 From cb6d2681efd8cc73cc5424f1c4b6822a869b2d39 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:57:37 -0500 Subject: [PATCH 11/17] Started code to manage kernel resource table --- include/resource.h | 27 +++++++++++++++++++++++++++ src/resource.c | 13 +++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 include/resource.h create mode 100644 src/resource.c 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/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; +} From db280f3fad5dd803bff68456a4d356e6db824c82 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:57:50 -0500 Subject: [PATCH 12/17] Added new source files to Makefile.am --- src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index e696654..ca01154 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 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 From 4bbe63819a5877fcd27c9af1a3fae48c7471fc71 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:58:10 -0500 Subject: [PATCH 13/17] Added page_table firld to process_t --- include/process.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From ce6371f0c31d54ac0e7ea9d55d8223770f68a192 Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 00:59:15 -0500 Subject: [PATCH 14/17] Added ISR for preemption of processes --- src/x86/isr.c | 26 +++++++++++++++++--------- src/x86/isr.h | 3 +++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/x86/isr.c b/src/x86/isr.c index 80fd862..81dbc4e 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -1,20 +1,18 @@ +#include "kernel.h" #include "isr.h" #include "stdio.h" #include "apic.h" -__attribute__ ((interrupt)) 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) { asm("cli"); @@ -22,28 +20,39 @@ void isr_gp_fault(void* frame, unsigned int error) asm("hlt"); } -__attribute__ ((interrupt)) void isr_page_fault(void* frame, unsigned int error) { - printf("Exception: Page fault\n"); + size_t addr; + asm("mov %%cr2, %0" + : "=r"(addr)); + printf("Exception: Page fault, code %08x, linear address %08x\n", error, addr); + asm("hlt"); } -__attribute__ ((interrupt)) void isr_double_fault(void* frame, unsigned int error) { asm("cli"); + printf("Exception: Double fault (!!), code %08x\n", error); asm("hlt"); } -__attribute__ ((interrupt)) void isr_timer(void* frame) { printf("Timer tick.\n"); apic_eoi(); } -__attribute__ ((naked)) +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"); @@ -52,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 c5a3914..b4d8d9b 100644 --- a/src/x86/isr.h +++ b/src/x86/isr.h @@ -18,6 +18,9 @@ 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); From b582c39ff84df873d23807cc41bcc9ac39c0376d Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 01:00:28 -0500 Subject: [PATCH 15/17] Started work on process management --- include/kernel.h | 17 +++++++-- include/priorityqueue.h | 4 +-- src/kernel.c | 77 +++++++++++++++++++++++++++++++++++++++-- src/priorityqueue.c | 4 +-- src/x86/apic.c | 4 ++- src/x86/quark_x86.c | 20 +++++------ 6 files changed, 106 insertions(+), 20 deletions(-) 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/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/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/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/x86/apic.c b/src/x86/apic.c index 399ab41..32d6b84 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -6,6 +6,8 @@ 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 @@ -31,7 +33,7 @@ void apic_enable(struct page_stact_t *page_stack) ); struct msr_apic_base_t msr; read_msr(MSR_APIC_BASE, (uint64_t*)&msr); - map_page(page_stack, &_kernel_end, msr.apic_base << 12, 0); + map_page(page_stack, &_kernel_end, msr.apic_base << 12, PAGE_RW); printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); apic_registers = (struct apic_registers_t*)&_kernel_end; apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100; diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 474fa5e..31fb801 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -4,18 +4,16 @@ #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_end; -struct apic_registers_t volatile *apic_registers; +struct kernel_t kernel_state; int start_paging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) { @@ -46,7 +44,6 @@ int initialize(void *multiboot_info) initialize_idt(); printf("***%s***\n", PACKAGE_STRING); 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]; @@ -73,22 +70,23 @@ int initialize(void *multiboot_info) page_stack.stack_pointer = (physaddr_t*)0xFFC00000; page_stack.limit_pointer = (physaddr_t*)0xFF900000; initialize_page_stack(&page_stack, &boot_info.map, 4096); - for(int i = 0; i < boot_info.module_count; i++) - { - load_module(&kernel, &boot_info.modules[i]); - } 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; - printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); - printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); + + kernel_state.page_stack = &page_stack; + for(int i = 0; i < boot_info.module_count; i++) + { + load_module(&kernel_state, &boot_info.modules[i]); + } + asm("sti"); while(1) { asm("hlt"); } - // TODO: enter first process + // next_process(&kernel_state, NULL); } From b141582f40c91cdd59af0e852ac12ed578c52d3a Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 01:18:14 -0500 Subject: [PATCH 16/17] Added very simple kernel memory allocator --- include/allocator.h | 9 +++++++++ src/Makefile.am | 2 +- src/allocator.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 include/allocator.h create mode 100644 src/allocator.c 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/src/Makefile.am b/src/Makefile.am index ca01154..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 elf.c resource.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 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; +} From 961139df9ed8720087fab3b90993d523dafaf0ea Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 03:45:45 -0500 Subject: [PATCH 17/17] Improved kernel memory usage Moved base linear address to 0xFF800000 Kernel only reserves the page frames it actually needs Memory for multiboot2 headers is freed Video memory and APIC registers are dynamically mapped into linear addresses --- include/pageallocator.h | 2 +- include/stdio.h | 2 ++ src/pageallocator.c | 17 +++++++++++++++- src/x86/apic.c | 5 +++-- src/x86/entry.S | 28 ++++++++++++--------------- src/x86/linker.ld | 9 ++++----- src/x86/mmgr.c | 28 +++++++++++++++++++++++++++ src/x86/multiboot2.c | 4 ---- src/x86/putc.c | 10 +++++++++- src/x86/quark_x86.c | 43 +++++++++++++++-------------------------- 10 files changed, 91 insertions(+), 57 deletions(-) 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/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/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/x86/apic.c b/src/x86/apic.c index 32d6b84..9698e55 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,4 +1,5 @@ #include "mmgr.h" +#include "allocator.h" #include "apic.h" #include "msr.h" #include "stdio.h" @@ -33,9 +34,9 @@ void apic_enable(struct page_stact_t *page_stack) ); struct msr_apic_base_t msr; read_msr(MSR_APIC_BASE, (uint64_t*)&msr); - map_page(page_stack, &_kernel_end, msr.apic_base << 12, PAGE_RW); + 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 = (struct apic_registers_t*)&_kernel_end; apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100; } diff --git a/src/x86/entry.S b/src/x86/entry.S index bb4a2ed..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 @@ -108,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 @@ -152,13 +139,22 @@ _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 $start_paging, %eax sub $BASE_DIFF, %eax # Initialize paging call *%eax - + # Jump into mapped kernel binary lea 1f, %eax jmp *%eax @@ -173,7 +169,7 @@ _start: # 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/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 c4edb6a..572abc2 100644 --- a/src/x86/mmgr.c +++ b/src/x86/mmgr.c @@ -28,6 +28,34 @@ 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); 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 31fb801..7f8d281 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -1,5 +1,7 @@ #include "kernel.h" #include "pageallocator.h" +#include "allocator.h" +#include "mmgr.h" #include "multiboot2.h" #include "memorymap.h" #include "apic.h" @@ -11,38 +13,18 @@ #include #include +extern int _kernel_pstart; +extern int _kernel_pend; +extern int _kernel_start; extern int _kernel_end; struct kernel_t kernel_state; -int start_paging(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; -} - int initialize(void *multiboot_info) { initialize_gdt(); initialize_idt(); - printf("***%s***\n", PACKAGE_STRING); + initialize_allocator(&_kernel_end, (void*)0xFFC00000); static struct page_stack_t page_stack; struct memory_region_t map_array[16]; char bootloader_name[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,8 +57,8 @@ 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;