summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gdb_history386
-rw-r--r--src/backup437
-rw-r--r--src/bootloader/bios_disk.asm149
-rw-r--r--src/bootloader/bios_functions/bios_disk.asm40
-rw-r--r--src/bootloader/bios_functions/print.asm58
-rw-r--r--src/bootloader/bootloader.asm95
-rw-r--r--src/bootloader/cpu_check.asm28
-rw-r--r--src/bootloader/enter_kernel.asm72
-rw-r--r--src/bootloader/gdt.asm6
-rw-r--r--src/bootloader/print.asm21
-rw-r--r--src/bootloader/video.asm4
-rw-r--r--src/debug/gdbinit.gdb9
-rwxr-xr-xsrc/debug/gdbinit.py28
-rw-r--r--src/debug/i8086.xml113
-rw-r--r--src/include/acpi.h37
-rw-r--r--src/include/heap.h5
-rw-r--r--src/include/int.h84
-rw-r--r--src/include/io.h38
-rw-r--r--src/include/isv.h25
-rw-r--r--src/include/kernel.h16
-rw-r--r--src/include/libc.h4
-rw-r--r--src/include/madt.h20
-rw-r--r--src/include/math.h6
-rw-r--r--src/include/paging.h95
-rw-r--r--src/include/panic.h60
-rw-r--r--src/include/random.h5
-rw-r--r--src/include/serial.h13
-rw-r--r--src/include/smp.h4
-rw-r--r--src/include/testmalloc.h6
-rw-r--r--src/include/timer.h8
-rwxr-xr-xsrc/indigo_osbin19512 -> 41152 bytes
-rw-r--r--src/kernel/acpi.c179
-rw-r--r--src/kernel/drivers/serial.c39
-rw-r--r--src/kernel/heap.c211
-rw-r--r--src/kernel/int.c253
-rw-r--r--src/kernel/io.c24
-rw-r--r--src/kernel/isv.c12
-rw-r--r--src/kernel/isv_asm.asm65
-rw-r--r--src/kernel/kernel.c46
-rw-r--r--src/kernel/klog.c100
-rw-r--r--src/kernel/libc.c19
-rw-r--r--src/kernel/madt.c179
-rw-r--r--src/kernel/page.c573
-rw-r--r--src/kernel/panic.c80
-rw-r--r--src/kernel/printf.c6
-rw-r--r--src/kernel/random.c36
-rw-r--r--src/kernel/smp.c80
-rw-r--r--src/kernel/smp_trampoline.asm140
-rw-r--r--src/kernel/testmalloc.c35
-rw-r--r--src/kernel/timer.c296
-rw-r--r--src/kernel/video.c (renamed from src/kernel/drivers/video.c)3
-rw-r--r--src/link.ld48
-rw-r--r--src/makefile104
53 files changed, 3053 insertions, 1347 deletions
diff --git a/src/.gdb_history b/src/.gdb_history
index 41118ac..edbca99 100644
--- a/src/.gdb_history
+++ b/src/.gdb_history
@@ -1,256 +1,256 @@
-next
-print buddy_size
-print pmap->next
-print pmap
-print *pmap
-print *pmap
-print pmap
-quit
-quit
+c
+info threads
quit
-break page.c:198
c
-watch pmap
+info threads
+step
c
-print pmap
-next
-print buddy_size
-next
+print cores
+print cores_active
+info threads
c
-print *pmap
-quitquit
+info threads
quit
-break page.c
c
-quit
-break init_pmap
+info threads
c
-next
-watch pmap_i
-c
-print pmap_i
-next
+info threads
quit
-break page.c:220
+b smp_boot
c
+qit
quit
-break init_pmap
+b smp.c:59
c
next
-watch pmap_i
-c
-print pmap_i
-c
-print pmap_i
-next
-print zones[zone_i]
+info threads
next
-break page.c:137
-c
+info threads
next
-info b
-c
-print pmap_i
-c
-print pmap_i
+info threads
+info threads
+info threads
+quit
+b smp.c:65
c
-print pmap_i
next
-print *pmap
-print pmap
+info threads
+info thread 2
quit
-break page.c:220
+b timer.c:57
c
-print pmap
-print *pmap
quit
-break debug_pmap
-c
+b timer.c:57
c
quit
-break page.c:179
+b smp.c:57
c
+print *(uint32_t *)&icr
+print/x *(uint32_t *)&icr
+info threads
next
-print buddy_bit
-print budorder
-c
-quit
-quit
-break page.c:147
-c
+info threads
next
-print threshold_bitsize
-print (uint64_t)threshold_bitsize
-print pmap_i
-print *pmap
-print threshold_bitsize
-print buddy_bitsize
+info threads
next
-print buddy_bit
-print buddy_bit
-print buddy_bitlen
-print buddy_bitlen[0][7]
-print buddy_bitlen[0][7]
+info threads
next
-quit
-break panic
-c
+info threads
+next
+info threads
next
-x ebp
-print $ebp
-info reg ebp
-x 0x1ffff8
-stack 50
+info threads
+print/x *(uint32_t *)&icr
+pirnt (void *)0x8000
+prit (void *)0x8000
+print (void *)0x8000
+print *(void *)0x8000
+print __load_start_smp_bootloader
+print &__load_start_smp_bootloader
+print (void *)&__load_start_smp_bootloader
+print (void *)&__load_stop_smp_bootloader
quit
-break debug_pmap
-c
-info reg rbp
-info reg rbp
-x 0x1fffe8
-print (void*)&debug_pmap
-next
-stack
-stack 50
-info reg rbp
-x 0x1fffe8
-x/20 0x1fffe8
+print &__load_start_smp_bootloader
+print &__load_stop_smp_bootloader
+print &__load_stop_smp_bootloader
+print smp_bootstrap
+print smp_bootloader
+print &__load_stop_smp_bootloader
+print __load_stop_smp_bootloader
+print &__load_stop_smp_bootloader
+print smp_bootstrap_corecount
+b smp_trampoline
+hb smp_trampoline
+c
+d
+d
+hb smp_trampoline
+c
+info reg rip
quit
+hb smp_trampoline
+c
quit
-break panic
c
-next
-info stack
-stack
-next
-info rsp
-x 0x1fff28
-x *0x1fff28
-stack 50
quit
-break panic
+hb smp_trampoline
+c
+info threads
+hexdump 0
+c
+c
+c
+c
c
c
-stack
-stack 50
c
-stack 50
-info reg rbp
-quit
-break panic
-c
-next
-print stack
-stack 50
-stack --help
-stack 0x20
-stack 100 0x20
-info reg rbp
-info reg rbp + 1
-info reg rbp
-x 0x1fff58+8
-x 0x1fff58-8
-x 0x1fff58+1
-quit
-break main
c
-next
-stepi
-next
-stepi
-x 0x1fffe8 - 8
-x 0x1fffe8 + 8
-x 0x1fffe8
-x 0x1fffc8-8
-x 0x1fffe8-8
-next
-step
-print rsp
-stack
-x $rbp-8
-next
-x $rbp-8
-x $rbp+8
-stack 50
-stack 100
-stack 90
-stack 90 90
-stack 90
-x $ebp
-x $ebp-8x $eb
-x $ebp-8
-x $ebp+8
-quit
-break panic.c:27
c
-next
-print *Frame
-print frame
-print *frame
-print frame->function_base
-print/x frame->function_base
-x 0x103ef2
-x frame->function_base
-x frame->lastframe->function_base
-quit
-break panic.c:29
c
-print *frame
c
-quit
-break page.c:30
+c
+c
+c
+c
+cc
+c
+c
+c
+c
+c
+c
+c
+d
c
quit
-break panic.c:30
+b smp_trampoline
+c
+hb smp_trampoline
+d 2
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
c
c
-pirnt *frame
-print *frame
c
-print *frame
c
-print *frame
c
-print *frame
c
-print *frame
-x 0x1ffff8
c
quit
c
-x 831e
-x 0x831e
-x 0x103f58
-x/i 0x831e
-x/i 0x831e-8
-x/i 0x831e-16
-x/10i 0x831e
-x/10i 0x831e-16
-x/10i 0x831e-1
-x/10i 0x831e-
-x/10i 0x831e
-x/10i 0x831e-8
-x/10i 0x831e+8
-x/10i 0x831e
+info threads
quit
-break 0x831e
c
+info threads
quit
-b *0x831e
+info threads
+next
+next
+print 0x8000 / 0x1000
+next
+quit
+quit
+next
+info threads
+next
+info threads
+next
+info threads
+quit
+next
+info threads
+next
+info threads
+next
+info threads
+next
+info threads
+next
+info threads
+next
+info threads
+quit
+hb 0
c
quit
+next
+next
+next
+print icr
+next
+next
+info threads
+quit
+next
+info threads
+next
+info threads
+next
+info threads
+next
+info threads
quit
+b smp.c:60
c
-print *frame
-print *frame
-x *frame
-x/1 *frame
- *frame
+next
+info threads
+next
+info threads
quit
-break main.c
+b memcpy
c
+print dest
+x 0xffff800000008000
+print 0xffff800000008000
+print/x 0xffff800000008000
+print n
+b 54
+c
+next
+info reg
+info reg rax
+info reg rbx
+inf reg rdi
+x/i 0xffff800000000000
+x/i 0xffff800000008000
+ smp_trampoline
+hexdump 0xffff800000008000
quit
-break main
+b memcpy
c
-stack
+print dest
+hexdump 0xffff800000008000
+b 64
c
+hexdump 0xffff800000008000
+print __load_start_smp_bootloader
+hexdump 0xffff800000000800
+quit
+info reg rsp
quit
diff --git a/src/backup b/src/backup
deleted file mode 100644
index 9191304..0000000
--- a/src/backup
+++ /dev/null
@@ -1,437 +0,0 @@
-#include <printf.h>
-#include <paging.h>
-#include <stdint.h>
-#include <libc.h>
-#include <limits.h>
-#include <kernel.h>
-
-void debug_print_memory() {
- struct memory_table *memtable = (struct memory_table *)&_meminfo_loc;
- printf(" __________________________________________________________________________\n");
- printf("| type\tstart\t\t\tend\t\t\tsize\t\t |\n");
- printf("|--------------------------------------------------------------------------|\n");
- for(unsigned int i = 0; memtable[i].length > 0; i++) {
- printf("| %u %u\t0x%p\t0x%p\t0x%p |\n", memtable[i].type, memtable[i].ACPI, memtable[i].base, (memtable[i].base + memtable[i].length), memtable[i].length);
- }
- printf("----------------------------------------------------------------------------\n");
-}
-
-void debug_pmap() {
- struct phys_map* pmap;
- int pmap_i = 0, order;
- uint64_t buddy_size, blong_i, bbit_i, buddy_chunksize, omit_cnt;
- printf("Maximum buddy order: %u (up to %#x sized chunks)\n", MAX_BUDDY_ORDER, (0x1000 << MAX_BUDDY_ORDER - 1));
- for(pmap = (struct phys_map*)&_stage2_pagetable; pmap != 0; pmap = pmap->next) {
- printf("Table %u:\n"
- "\tPhysical Start:\t%#p\n"
- "\tTable location:\t%#p\n", pmap_i, pmap->zone_paddr, pmap);
- for(order = 0; order <= MAX_BUDDY_ORDER - 1; order++) {
- buddy_chunksize = (0x1000 << order); //TODO just put it in the for loop
- buddy_size = (((order == MAX_BUDDY_ORDER - 1)
- ? (uint64_t *)pmap->next : pmap->buddy[order + 1]) - pmap->buddy[order]);
- printf("\tbuddy[%u]:\n"
- "\t\tAddress:\t%#x\n"
- "\t\tSize:\t\t%u\n"
- "\t\tBuddies:\t\t\n", order, pmap->buddy[order], buddy_size);
-
- omit_cnt = 0;
-
- for(blong_i = 0; blong_i < buddy_size; blong_i++) {
- for(bbit_i = 0; bbit_i < 64; bbit_i++) {
- if(*(pmap->buddy[order] + blong_i) & ((uint64_t)1 << bbit_i)) {
- if((omit_cnt < 20) || (blong_i == buddy_size - 1)) {
- printf("address %#x\tbit %u: %x\t is free\n",
- pmap->buddy[order] + blong_i, bbit_i, pmap->zone_paddr + ((blong_i * 64) + bbit_i) * buddy_chunksize);
- }
- omit_cnt++;
- if(omit_cnt == 20) {
- printf("\t\t\t[more entries ommited]\n");
- }
- }
- }
- }
-print_next_buddy: ;
- }
- pmap_i++;
- }
-}
-
-/*
- * part 1:
- * init tables (complete)
- *
- * part 2: setting the actual entires
- * if entry contains table, set 0, set threshold
- * else:
- * if entry:
- */
-
-// init_memory revision
-// rules:
- /**
-void init_pmap() {
- struct memory_table *memtable = (struct memory_table *)&_meminfo_loc;
- struct phys_map *pmap = (struct phys_map*)&_stage2_pagetable;
- struct phys_map *last_pmap;
- unsigned int i, x;
- uint64_t budentry_len, pmap_chunksize, total_pmap_len = 0;
- void *y;
- void *paged_mem = &_stage2_pagetable + 0x200000;
- map_page(&_stage2_pagetable, &_stage2_pagetable, PAGE_SIZE_2M);
- for(i = 0; memtable[i].length > 0; i++) {
- if((memtable[i].type == MEM_AVAILABLE) && (memtable[i].ACPI & 1)) {
- total_pmap_len += 88; //it'd be nice to find a cleaner way
-
- //make sure we don't overwrite what we have so far of the kernel
- if((memtable[i].base <= (void*)&_stage2_pagetable) && (memtable[i].base + memtable[i].length >= (void *)&_stage2_pagetable)) {
- pmap->chunk_start = &_stage2_pagetable;
- pmap->chunk_size = memtable[i].length - (pmap->chunk_start - memtable[i].base);
- }
- else {
- pmap->chunk_start = memtable[i].base;
- pmap->chunk_size = memtable[i].length;
- }
-
- for(x = 0; x < 8; x++) {
- pmap->bsize[x] = ceil((pmap->chunk_size / (0x1000 * (1 << x))) / (double)64);
- total_pmap_len += pmap->bsize[x] * 8;
- }
-
- pmap->next = (void*)&_stage2_pagetable + total_pmap_len;
-
- while((void*)pmap->next + sizeof(struct phys_map) >= paged_mem) {
- //do check here if nessesary
- map_page(paged_mem, paged_mem, PAGE_SIZE_2M);
- paged_mem += 0x200000;
- }
-
- last_pmap = pmap;
- pmap = pmap->next;
- }
- }
- last_pmap->next = 0; //I wonder if there's a better way to do this
- pmap = (struct phys_map*)&_stage2_pagetable;
-
-}
-**/
-
-void init_pmap() {
- struct memory_table *zones = (struct memory_table *)&_meminfo_loc;
- struct phys_map *pmap = (struct phys_map*)&_stage2_pagetable;
- struct phys_map *last_pmap = (struct phys_map*)&_stage2_pagetable;
-
- unsigned int zone_i, pmap_i = 0;
- int budorder;
-
- //we keep this info out of the struct because we won't need it after setting up
- uint64_t zone_len[MAX_ZONE_CNT], buddy_bitlen[MAX_ZONE_CNT][MAX_BUDDY_ORDER];
- uint64_t *buddy_end;
-
- uint64_t pmap_size, pmap_bbitsize, pmap_blongsize, buddy_size, pmap_bit;
- uint64_t threshold_longsize = 0, threshold_bit, threshold_end, threshold_bitsize;
- uint64_t deleteme_last_p_bits;
-
-
- void *paged_mem = (void *)&_stage2_pagetable + 0x200000;
- map_page(&_stage2_pagetable, &_stage2_pagetable, PAGE_SIZE_2M);
-
- for(zone_i = 0; zones[zone_i].length > 0; zone_i++) {
-
- if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1)) {
-
- //hopefully this should never happen... but x86 is routy.
- //I should dig into the docs to check before removing this.
- //We also could forget about MAX_ZONE_CNT if we did.
-
- if(zone_i >= MAX_ZONE_CNT) {
- printf("Only %u zones can be used! Modify MAX_ZONE_CNT in paging.h to use all memory.\n", MAX_ZONE_CNT);
- break;
- }
-
-
- if((zones[zone_i].base <= (void*)&_stage2_pagetable) &&
- (zones[zone_i].base + zones[zone_i].length >= (void *)&_stage2_pagetable)) {
- pmap->zone_paddr = &_stage2_pagetable;
- zone_len[pmap_i] = zones[zone_i].length - (pmap->zone_paddr - zones[zone_i].base);
- }
- else {
- pmap->zone_paddr = zones[zone_i].base;
- zone_len[pmap_i] = zones[zone_i].length;
- }
-
- pmap->buddy[0] = (void *)pmap + sizeof(*pmap);
-
- for(budorder = 1; budorder < MAX_BUDDY_ORDER; budorder++) {
- buddy_bitlen[pmap_i][budorder - 1] = GET_BUDDY_BITLEN(zone_len[pmap_i], budorder - 1);
- pmap->buddy[budorder] = (uint64_t *)pmap->buddy[budorder - 1] +
- LSIZE_FROM_BITLEN(buddy_bitlen[pmap_i][budorder - 1]);
- }
-
- buddy_bitlen[pmap_i][MAX_BUDDY_ORDER - 1] = GET_BUDDY_BITLEN(zone_len[pmap_i], MAX_BUDDY_ORDER - 1);
- pmap->next = (void *)pmap->buddy[MAX_BUDDY_ORDER - 1] +
- (LSIZE_FROM_BITLEN(buddy_bitlen[pmap_i][MAX_BUDDY_ORDER - 1]) * 8);
-
- pmap = pmap->next;
- pmap_i++;
- last_pmap = pmap;
-
- //allocates by an extra sizeof(struct phys_map),
- //but were about to discard anyway
- while((void *)pmap + sizeof(*pmap) >= paged_mem) {
- map_page(paged_mem, paged_mem, PAGE_SIZE_2M);
- paged_mem += 0x200000;
- }
-
- }
- }
- pmap_size = (void*)(pmap) - (void*)&_stage2_pagetable;
- if(pmap_size >= zone_len[0]) panic(); //TODO debugging
-
- pmap = (struct phys_map*)&_stage2_pagetable;
-
- // Honestly, this section makes me feel like Yandere Dev. It's ugly.
- // I've been rewriting this function forever, so I'm deciding to slam it out start to finish.
- // I know there's a lot of repeated if statements. I know it hurts.
- // But fear not.
- // I'll come back and rewrite this part when I've gotten a break from memory management.
- for(pmap = (struct phys_map*)&_stage2_pagetable; pmap != 0; pmap++) {
- for(budorder = MAX_BUDDY_ORDER - 1; budorder >= 0; budorder--) {
- pmap_bbitsize = ceil((float)pmap_size / ((uint64_t)0x1000 << budorder));
- pmap_blongsize = pmap_bbitsize / 64;
-
- if(budorder == MAX_BUDDY_ORDER - 1) {
- buddy_end = (uint64_t *)pmap->next - 1;
- threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2;
- threshold_bitsize = UINT64_MAX;
- }
- else {
- buddy_end = pmap->buddy[budorder + 1] - 1;
- threshold_longsize = threshold_bitsize / 64;
- threshold_end = threshold_longsize + 1;
- }
- pmap_bit = pmap_bbitsize & 63;
- buddy_size = buddy_end - pmap->buddy[budorder];
-
-
- if(pmap_bbitsize >= BITLEN_FROM_LSIZE(buddy_size)) {
- //is this nessesary?
- bzero(pmap->buddy[budorder], buddy_size * 8);
- }
- else {
- if(budorder == MAX_BUDDY_ORDER - 1) {
- if(pmap_blongsize) bzero(pmap->buddy[budorder], (pmap_blongsize - 1) * 8);
- if(pmap_bit) {
- *(pmap->buddy[budorder] + pmap_blongsize) = ~(((uint64_t)1 << pmap_bit) - 1);
- }
- else {
- *(pmap->buddy[budorder] + pmap_blongsize) = UINT64_MAX;
- }
- if(pmap_blongsize + 1 == buddy_size) {
- //TODO why did I have this conditional? Do I need it later? Check on desktop before removing
- if(buddy_bitlen[0][budorder]) {
- *(pmap->buddy[budorder] + pmap_blongsize) &=
- ((uint64_t)1 << (buddy_bitlen[0][budorder] & 63)) - 1;
- }
- }
- else {
- memset(pmap->buddy[budorder] + pmap_blongsize + 1, UINT8_MAX,
- (void *)buddy_end - (void *)pmap->buddy[budorder] - 8);
- *buddy_end = ((uint64_t)1 << (buddy_bitlen[0][budorder] & 63)) - 1;
- }
- }
- else {
- if(threshold_longsize) bzero(pmap->buddy[budorder], (threshold_longsize - 1) * 8);
-
- if(threshold_bitsize > pmap_bbitsize)
- *(pmap->buddy[budorder] + threshold_longsize) = ((uint64_t)1 << ((threshold_bitsize - 1) & 63));
-
- if(buddy_size - threshold_longsize)
- bzero(pmap->buddy[budorder] + threshold_longsize + 1, buddy_size - threshold_longsize);
- *buddy_end = ((uint64_t)1 << ((buddy_bitlen[0][budorder] & 63) - 1));
- }
- threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2;
- }
- }
- }
-// for(pmap = pmap->next; pmap != 0; pmap++) {
-// }
-}
-
-
-// for(budlong_ptr = pmap->buddy[budorder]; budlong_ptr < (uint64_t *)pmap->next - 1; budlong_ptr++) {
-
-/**
-//uses buddy system allocation
-void init_memory() {
- struct memory_table *memtable = (struct memory_table *)&_meminfo_loc;
- struct phys_map *map = (struct phys_map*)&_stage2_pagetable;
- struct phys_map *lasttable;
- unsigned int i, buddy_chunksize;
- uint64_t buddy_bitsize, prev_buddy_bsize, ppt_size;
- uint64_t *buddy_ptr, *budentry_end, *threshold;
- uint64_t buddy_size64;
-
- map_page((void*)&_stage2_pagetable, (void*)&_stage2_pagetable, PAGE_SIZE_2M);
- void *next_page = (void *)0x400000;
- // at this point, we are declaring our header and kernel itself as free (so don't forget to fix that!)
-
- //TODO all these for loops are unsanitary.
- //We hae a lot of branches in the for loops,
- //And we re-do work to allocate the page-table.
- //I'll clean this up when I'm certain my buddy system works.
- for(i = 0; memtable[i].length > 0; i++) {
- if((memtable[i].type == MEM_AVAILABLE) && (memtable[i].ACPI & 1)) {
- map->chunk_start = (void*)memtable[i].base;
- map->chunk_size = memtable[i].length;
- buddy_ptr = (void*)&map->buddies;
-
- for(buddy_chunksize = 0x1000; buddy_chunksize < 0x100000; buddy_chunksize *= 2) {
- buddy_bitsize = memtable[i].length / buddy_chunksize;
- buddy_size64 = ceil(buddy_bitsize / (double)64);
-
- if((void*)&buddy_ptr[buddy_size64] + 24 >= next_page) {
- map_page(next_page, next_page, PAGE_SIZE_2M);
- next_page += 0x200000;
- }
-
- printf("buddy\t%x\theader bitsize\t%u\theader longsize\t%u\tbuddy start\t%p",\
- buddy_chunksize, buddy_bitsize, buddy_size64, buddy_ptr);
- if(((buddy_bitsize * 2) != prev_buddy_bsize) && (buddy_chunksize != 0x1000)) {
- buddy_ptr[-1] |= ((uint64_t)1 << ((prev_buddy_bsize & 63) - 1));
- printf("\tlast:\t%lx", buddy_ptr[-1]);
- }
- printf("\n");
-
- if(buddy_chunksize < 0x80000) {
- bzero(buddy_ptr, buddy_size64 * 8);
- prev_buddy_bsize = buddy_bitsize;
- }
-
- else if(buddy_size64 % buddy_bitsize) {
- memset(buddy_ptr, 0xff, (buddy_size64 - 1) * 8);
- buddy_ptr[buddy_size64] |= 1 << buddy_bitsize;
- }
-
- else memset(buddy_ptr, 0xff, buddy_size64);
-
- buddy_ptr += buddy_size64;
- }
-
- //this feels kind of gross
- lasttable = map;
- map->next = (struct phys_map*)buddy_ptr;
- map = (struct phys_map*)buddy_ptr;
- }
- }
- lasttable->next = (void*)0;
- map = (struct phys_map*)&_stage2_pagetable;
- //now we will allocate the table out of itself so we don't mess things up.
- //We can't just call palloc(), we need to allocate out of the first available pages (where the pages are)
- //we should clean this whole gross function
- /**
- ppt_size = (uint64_t)((void *)buddy_ptr - (void *)&_stage2_pagetable);
- threshold = (void*)UINT64_MAX;
- int buddy_bit;
- for(buddy_chunksize = 0x80000; buddy_chunksize >= 0x1000; buddy_chunksize /= 2) {
- //this means that our table must fit into the first page table. Fixme later, low priotrity
- buddy_size64 = ceil((map->chunk_size / buddy_chunksize) / (double)64);
- budentry_end = buddy_ptr;
- for(buddy_ptr -= buddy_size64; buddy_ptr <= budentry_end; buddy_ptr++) {
- if(buddy_ptr > threshold) {
- buddy_ptr = budentry_end;
- continue;
- }
- if(
- }
- }
-}
- **/
-
-//TODO this function was deleted due to it being wrong.
-//I'll create it once I have the physical paging prerequisite set up.
-void create_pagetable_stage2(uint64_t free_mem) {
-}
-
-
-/**
- * BIG TODO:
- * Paging turned out to be simpler then I thought. I've temporarily fixed the code, but needs to be rewritten/simplified.
- * Let's get rid of those nasty GOTOs if we can.
- * Also, once we get physical memory allocator up and running, impliment that in this function.
-**/
-
-bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) {
- //printf("map page called\n");
- uintptr_t va_ptr = (uintptr_t)virtual_addr;
- uintptr_t pa_ptr = (uintptr_t)physical_addr;
- if((va_ptr % (1 << size)) || (pa_ptr % (1 << size))) {
- return 0;
- }
- page_table *table = (page_table *)PAGEMAP_LOCATION;
- int pte_i = (va_ptr >> 12) & 0x1ff;
- int pde_i = (va_ptr >> 21) & 0x1ff;
- int pdpe_i = (va_ptr >> 30) & 0x1ff;
- int pml4e_i = (va_ptr >> 39) & 0x1ff;
-
- if(table->pml4e[pml4e_i].present) {
- if(table->pml4e[pml4e_i].base_ptr != (uintptr_t)&table->pdpe[pdpe_i] >> 12) goto error;
- if(table->pdpe[pdpe_i].present) {
- if(size == PAGE_SIZE_1G) {
- if(table->pdpe[pdpe_i].base_ptr == ((uintptr_t)pa_ptr >> 30 & 0x1ff))
- return true;
- goto error;
- }
- if(table->pdpe[pdpe_i].base_ptr != (uintptr_t)&table->pde[pde_i] >> 12) goto error;
-
- if(table->pde[pde_i].present) {
- if(size == PAGE_SIZE_2M) {
- if(table->pde[pde_i].base_ptr == ((uintptr_t)pa_ptr >> 21 & 0x1ff))
- return true;
- goto error;
- }
- if(table->pde[pde_i].base_ptr != (uintptr_t)&table->pte[pte_i] >> 12) goto error;
- if(table->pte[pte_i].present) {
- if(table->pte[pte_i].base_ptr != ((pa_ptr >> 12) & 0x1ff)) goto error;
- return true;
- }
- else goto mod_page_pte;
- }
- else goto mod_page_pde;
- }
- else goto mod_page_pdpe;
- }
- else {
- table->pml4e[pml4e_i].base_ptr = (uintptr_t)&table->pdpe[pdpe_i] >> 12;
- table->pdpe[pml4e_i].read_write = 1;
- table->pml4e[pml4e_i].present = 1;
-mod_page_pdpe:
- table->pdpe[pdpe_i].read_write = 1;
- //TODO you just found out things are a lot more simple then you thought!
- if(size == PAGE_SIZE_1G) {
- table->pdpe[pdpe_i].size = 1;
- table->pdpe[pdpe_i].base_ptr = pa_ptr >> 12;
- table->pdpe[pdpe_i].present = 1;
- return true;
- }
- table->pdpe[pdpe_i].base_ptr = (uintptr_t)&table->pde[pde_i] >> 12;
- table->pdpe[pdpe_i].present = 1;
-mod_page_pde:
- table->pde[pde_i].read_write = 1;
- if(size == PAGE_SIZE_2M) {
- table->pde[pde_i].size = 1;
- table->pde[pde_i].base_ptr = pa_ptr >> 12;
- table->pde[pde_i].present = 1;
- return true;
- }
- table->pde[pde_i].base_ptr = (uintptr_t)&table->pte[pte_i] >> 12;
- table->pde[pde_i].present = 1;
-mod_page_pte:
- table->pte[pte_i].base_ptr = pa_ptr >> 12;
- table->pte[pte_i].read_write = 1;
- table->pte[pte_i].present = 1;
- return true;
- }
-error:
- printf("Page allocation error!\n");
- return false;
-}
diff --git a/src/bootloader/bios_disk.asm b/src/bootloader/bios_disk.asm
new file mode 100644
index 0000000..5992920
--- /dev/null
+++ b/src/bootloader/bios_disk.asm
@@ -0,0 +1,149 @@
+bios_disk:
+.init:
+mov [boot_device], dl
+mov ah, 0x8
+int 0x13
+;TODO defaults
+
+jc .init_use_defaults
+
+mov [max_head], dh
+mov [max_sector], cl
+and WORD [max_sector], 0x3f
+
+mov [max_cylinder], cl
+shl WORD [max_cylinder], 8
+or [max_cylinder], ch
+and WORD [max_cylinder], 0x3ff
+
+ret
+
+.init_use_defaults:
+mov BYTE [max_sector], 63
+mov WORD [max_head], 15
+mov BYTE [max_cylinder], 1023
+
+ret
+
+; Return:
+; CH = low eight bits of maximum cylinder number
+; CL = maximum sector number (bits 5-0), high two bits of maximum cylinder number (bits 7-6)
+; DH = maximum head number
+
+.load_sectors_v2:
+;AH = 02h
+;AL = number of sectors to read (must be nonzero)
+;CH = low eight bits of cylinder number
+;CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7)
+;DH = head number
+;DL = drive number (bit 7 set for hard disk)
+;ES:BX -> data buffer
+
+; I don't understand i8086. The base pointer needs to be above the stack pointer,
+; yet the stack grows down,
+; and we can't address using sp, or by subtraction.
+; it's like it's forcing us to use the whole push/pop thing.
+
+sub sp, 16
+mov bp, sp
+
+; sector: rbp + 0 (uint8_t)
+; head: rbp + 1 (uint8_t)
+; cylinder: rbp + 2 (uint16_t)
+; sector_cnt: rbp + 4 (uint16_t)
+; destination: rbp + 6 (uint32_t)
+
+; set up variables ______________________________________________
+
+;destination to stack
+mov [bp + 6], edi
+
+; find init chs ________________________________________________
+
+; divide sector_start / max_sectors
+; TODO test for overflow
+mov ax, si
+shr esi, 16
+mov dx, si
+
+;find sector
+div DWORD [max_sector]
+inc dx
+mov [bp], edx ; remainder is sector variable
+
+;find head and cylinder
+mov dx, 0
+div DWORD [max_head]
+mov [bp + 1], dx ; head
+mov [bp + 2], ax ; cylinder
+
+.sector_for_loop:
+mov [bp + 4], cx
+
+; do bios call ___________________________________________________
+mov ah, 2
+mov al, 1
+; sets up ch and cl
+mov cx, [bp + 2]
+xchg ch, cl
+shl cl, 6
+or cl, [bp]
+
+mov dh, [bp + 1]
+mov dl, [boot_device]
+mov bx, 0x500 ; where we store the sector temporarily
+
+int 0x13
+jc .read_failed
+
+; mempcy __________________________________________________________
+
+; we move it to the place at edi, which I don't think changes
+mov esi, 0x500
+mov ecx, 512
+a32 rep movsb
+
+; recalc chs ______________________________________________________
+
+; need to test for more overflows I think
+inc WORD [bp]
+mov al, [bp]; increase the sector we're on
+cmp al, [max_sector]
+jbe .continue_loop
+mov WORD [bp], 1
+
+inc WORD [bp + 1]
+mov al, [bp + 1]
+cmp al, [max_head]
+jbe .continue_loop
+mov WORD [bp + 1], 0
+inc DWORD [bp + 2]
+
+; loopin back ____________________________________________________
+.continue_loop:
+mov cx, [bp + 4]
+
+
+loop .sector_for_loop
+add bp, 16
+mov sp, bp
+
+
+ret
+
+
+
+
+.read_failed:
+mov bx, .loadsectors_error
+call bios_print
+cli
+hlt
+
+.loadsectors_error: db "Error loading required sector!", 0
+
+boot_device: db 0
+max_sector: db 0
+max_cylinder: dw 0
+max_head: db 0
+
diff --git a/src/bootloader/bios_functions/bios_disk.asm b/src/bootloader/bios_functions/bios_disk.asm
deleted file mode 100644
index 195057a..0000000
--- a/src/bootloader/bios_functions/bios_disk.asm
+++ /dev/null
@@ -1,40 +0,0 @@
-bios_disk:
-.load_sectors:
-pusha
-mov es, dx
-
-; TODO when our kernel gets to big to fit in one track, we need to just switch over to LHS with extended bios functions.
-
-mov ah, 0x02 ; read disc sectors
-mov ch, 0x00 ; track 0
-mov dh, 0x00 ; head 0
-mov dl, [stage0.boot_device]
-
-int 0x13
-
-jc .failed
-
-mov ah, 0
-popa
-ret
-
-.failed:
-debug:
-mov bx, .loadsectors_error
-mov cx, 0
-call bios_print
-
-push 0
-mov al, ah
-mov ah, 0 ; you need to clean up the bios print function!
-push ax
-mov cx, 1
-mov bx, sp
-call bios_print
-
-
-mov ah, 1
-popa
-ret
-
-.loadsectors_error: db "Error loading sectors: ", 0
diff --git a/src/bootloader/bios_functions/print.asm b/src/bootloader/bios_functions/print.asm
deleted file mode 100644
index 303fa8f..0000000
--- a/src/bootloader/bios_functions/print.asm
+++ /dev/null
@@ -1,58 +0,0 @@
-;TODO fix null problem, allow passing value insted of pointer
-bios_print:
-pusha
-mov ah, 0x0e
-
-.print_loop:
-mov al, [bx]
-cmp al, 0
-je .fini
-
-test cx, cx ; if cx is zero, ascii, otherwise hex string
-jne .print_hex
-int 0x10
-.print_hex_ret:
-inc bx
-jmp .print_loop
-
-.fini:
-mov al, 0xd
-int 0x10
-mov al, 0xa
-int 0x10
-popa
-ret
-
-
-.print_hex:
-mov al, '0'
-int 0x10
-
-mov al, 'x'
-int 0x10
-
-mov al, [bx]
-shr al, 4
-call .bios_print_nibble
-
-mov al, [bx]
-and al, 0x0f
-call .bios_print_nibble
-
-mov al, ' '
-int 0x10
-
-jmp .print_hex_ret
-
-
-.bios_print_nibble:
-cmp al, 9
-ja .print_hex_letter
-add al, 0x30
-int 0x10
-ret
-
-.print_hex_letter:
-add al, 0x57
-int 0x10
-ret
diff --git a/src/bootloader/bootloader.asm b/src/bootloader/bootloader.asm
index 3ac10f3..f912e49 100644
--- a/src/bootloader/bootloader.asm
+++ b/src/bootloader/bootloader.asm
@@ -1,11 +1,11 @@
[bits 16]
-[extern _kernel_size]
+[extern _kernel_sector_size]
[extern _bootloader_stage1_size]
-[extern _kernel_loc]
+[extern _kernel_s1_loc]
jmp stage0
-times 3-($-$$) db 0x90 ; a temporary dirty fix to emulate a floppy disk insted of a hard risk
-times 59 db 0 ; (TODO support hard disks)
+times 3-($-$$) db 0x90
+times 59 db 0
stage0:
@@ -14,43 +14,48 @@ jmp 0:.entry
mov ax, 0
mov ds, ax
-mov bp, ax
-
-mov ds, ax
mov es, ax
-mov ax, 0x8fc0
+;stack segments
+mov ax, 0x7000
mov ss, ax
-mov ax, 0xfffe
+mov ax, 0xfff0
mov sp, ax
+mov bp, 0
mov al, 0x92
or al, 2
out 0x92, al
-mov [.boot_device], dl
+
+call bios_disk.init
+
mov bx, .loadstage2_msg
-mov cx, 0
call bios_print
-; TODO put in an error message and a maximum fail count
.load_stage1:
-mov al, _bootloader_stage1_size
-mov cl, 0x2 ; read sector 2
-mov dx, 0x0 ; dest segment 0
-mov bx, 0x7e00 ; dest offst 0
-call bios_disk.load_sectors
+;TODO LOAD STAGE ONE HERE
+
+; we start on 0x100000
+; esi: sector start
+; cx: sector count
+; edi: memory desination
+
+mov esi, 1 ; 2nt sector
+mov ecx, _bootloader_stage1_size
+mov edi, 0x7e00 ; desination
+call bios_disk.load_sectors_v2
+
jmp mbr_end.entry
-.boot_device: db 0
.loadstage2_msg: db "Loading (stage 2) bootloader...", 0
-%include "bootloader/bios_functions/bios_disk.asm"
-%include "bootloader/bios_functions/print.asm"
+%include "bootloader/bios_disk.asm"
+%include "bootloader/print.asm"
times 510 - ($-$$) db 0
dw 0xaa55
@@ -66,15 +71,12 @@ boot_msg:
mbr_end:
.entry:
+cli
; entering unreal mode
mov bx, boot_msg.stage2_loaded
-mov cx, 0
call bios_print
-cli
-push ds
-
lgdt [protected_gdt.descriptor]
mov eax, cr0
@@ -83,52 +85,29 @@ mov cr0, eax
jmp $+2
-mov bx, 0x10 ; descriptor 2, the data descriptor
-mov ds, bx ; put it into the segment register
-mov es, bx ;
+mov bx, 0x10
+mov ds, bx
+mov es, bx
and al, 0xfe
mov cr0, eax
-pop ds
+mov bx, 0
+mov ds, bx
+mov es, bx
sti
-;we are now in unreal mode
-
-mov cl, 5
-mov edi, _kernel_loc
-.loop:
-mov al, 0x1 ; sector count
-mov dx, 0x0 ; dest addr segment
-mov bx, 0x500 ; dest addr offset
-call bios_disk.load_sectors
-
-
-inc cl
-
-push cx
-
-mov esi, 0x500
-mov ecx, 512
-a32 rep movsb
-nop
-
-pop cx
-
-cmp cl, _kernel_size+2
-je .loop_end
-
-jmp .loop
-
-.loop_end:
+mov esi, _bootloader_stage1_size
+mov edi, 0x100000
+mov ecx, _kernel_sector_size
+call bios_disk.load_sectors_v2
mov bx, boot_msg.kernel_loaded
-mov cx, 0
call bios_print
call detect_arch
-call vbe_init
+;call vbe_init
done:
call enter_longmode
diff --git a/src/bootloader/cpu_check.asm b/src/bootloader/cpu_check.asm
index 0fa6ddf..ec5ee7b 100644
--- a/src/bootloader/cpu_check.asm
+++ b/src/bootloader/cpu_check.asm
@@ -1,4 +1,4 @@
-[extern _meminfo_loc]
+[extern _meminfo]
detect_arch:
; detect CPUID
@@ -19,6 +19,7 @@ cpuid
and edx, 0x0020000000
jz .print_long_error
+
; APIC
mov eax, 0x00000001
cpuid
@@ -31,14 +32,13 @@ jz .print_sse_error
mov bx, .no_error
-mov cx, 0
call bios_print
; get memory mappings
mov ax, 0
mov es, ax
-mov ax, _meminfo_loc
+mov ax, _meminfo
mov di, ax
mov eax, 0xe820
@@ -64,50 +64,50 @@ je .mem_detected
jmp .mem_detect_loop
.mem_detected:
+add di,24
+mov ecx, 24
+mov al, 0
+rep stosb
+
ret
.print_cpuid_error:
mov bx, .cpuid_error
-mov cx, 0
call bios_print
jmp $
.print_long_error:
mov bx, .arch_error
-mov cx, 0
call bios_print
jmp $
.print_apic_error:
mov bx, .apic_error
-mov cx, 0
call bios_print
jmp $
.print_mem_error:
mov bx, .mem_error
-mov cx, 0
call bios_print
jmp $
.print_sse_error:
mov bx, .sse_error
-mov cx, 0
call bios_print
jmp $
.cpuid_error:
- db "No CPUID capabilitity", 0x0
+ db "Somehow, your CPU doesn't even support the ability to detect its abilities. I'm gonna go out on a limb and say your cpu is too old to run this OS.", 0x0
.arch_error:
- db "This operating system was compiled to run in 64 bit mode!", 0x0
+ db "This operating system requires a x64 processor.", 0x0
.apic_error:
- db "No apic support", 0x0
+ db "No APIC support.", 0x0
.mem_error:
- db "Could not get information on memory!", 0x0
+ db "Couldn't obtain memory map.", 0x0
.sse_error:
- db "This OS requires SSE", 0x0
+ db "This OS requires the SSE instruction set.", 0x0
.no_error:
- db "CPU info gathered!", 0x0
+ db "CPU meets requirements to boot!", 0x0
diff --git a/src/bootloader/enter_kernel.asm b/src/bootloader/enter_kernel.asm
index d3933cf..ef2cd71 100644
--- a/src/bootloader/enter_kernel.asm
+++ b/src/bootloader/enter_kernel.asm
@@ -1,14 +1,14 @@
[extern main]
[extern _kernel_stack_loc]
-[extern _stage1_pagetable]
+[extern _kernel_page_size]
enter_longmode:
cli
-; TODO check if a20 is already set
mov al, 0x92
or al, 2
out 0x92, al
+;enter 32 bit mode
lgdt [protected_gdt.descriptor]
mov eax, cr0
or eax, 0x1
@@ -30,44 +30,56 @@ mov es, ax
mov fs, ax
mov gs, ax
-mov edi, _stage1_pagetable ; 0x3000
-mov cr3, edi
-mov eax, 0
-mov ecx, 0xc00 ; 0x1000
-rep stosd
-mov edi, cr3
+mov edi, 0x10000
+mov cr3, edi
-mov DWORD [edi], _stage1_pagetable + 0x1003 ; pml4e[0] = pdpe
-add edi, 0x1000
-mov DWORD [edi], _stage1_pagetable + 0x2003 ; pdpe[0] = pde
-add edi, 0x1000
-mov DWORD [edi], 0x83 ; pde[0] = pte
+mov eax, 0
+mov ecx, 0x1800 ; bzero 6 pages
+rep stosd
-mov eax, cr4
-or eax, 0x620
-mov cr4, eax
+mov DWORD [0x10000], 0x11003 ; pml4e[0] = pdpe
+mov DWORD [0x11000], 0x12003 ; pdpe[0] = pde
+mov DWORD [0x12000], 0x83 ; pde[0] = pte
+
+mov DWORD [0x10ff8], 0x13003
+mov DWORD [0x13ff0], 0x14003
+mov DWORD [0x14000], 0x15003
+
+mov eax, 0x100003
+mov ebx, 0
+mov ecx, _kernel_page_size
+.kernel_load_loop:
+mov DWORD [0x15000 + ebx], eax
+add ebx, 8
+add eax, 0x1000
+loop .kernel_load_loop
-;end of setting up pages
-mov ecx, 0xc0000080
-rdmsr
-or eax, 1 << 8
-wrmsr
-mov eax, cr0
-or eax, 1 << 31 | 1 << 0 ; this is where we set paging and protected mode (respectively)!
-mov cr0, eax
+mov eax, cr4
+; PAE, OSFXSR, OSXMMEXCPT
+or eax, 1 << 5 | 1 << 9 | 1 << 10
+mov cr4, eax
+;end of setting up pages
+;testing to see if NX bit is available.
+;If it's not and we enable it, it will cause pagefaults on read
+mov eax, 0x80000001
+cpuid
+and edx, 1 << 20
+shr edx, 9
+
mov ecx, 0xc0000080
rdmsr
-or eax, 1 << 8
+or eax, 1 << 8 | 1 << 11
+or eax, edx
wrmsr
mov eax, cr0
-and ax, 0xfffb
-or eax, 0x80000002
+or eax, 1 << 31 | 1 << 0;
+and ax, ~(1 << 2)
mov cr0, eax
@@ -76,8 +88,10 @@ lgdt [long_gdt.descriptor]
jmp LONG_CODE_SEGMENT:enter_kernel
enter_kernel:
bits 64
-mov rbp, _kernel_stack_loc
+mov rbp, 0
mov rsp, _kernel_stack_loc
-call main ; where we actually call the kernel
+mov rax, QWORD main
+;push QWORD 0
+jmp rax
jmp $
ret
diff --git a/src/bootloader/gdt.asm b/src/bootloader/gdt.asm
index 0ba0a44..0e6d89b 100644
--- a/src/bootloader/gdt.asm
+++ b/src/bootloader/gdt.asm
@@ -45,8 +45,8 @@ db 0
dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!)
dw 0 ; base address 15:00
db 0 ; base address 23:16
-db 10011010b ;1st flags and type. The first four bits (1010) are type, and the last are flags. See https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf
-db 10101111b ;1111 is segment limit continued. 0: available, 0: 64 bit (change?), 1: 32 bit segment, 1: granularity (shifts 3 hex didgets to get all of memory)
+db 10011010b
+db 00100000b
db 0
.gdt_data:
@@ -54,7 +54,7 @@ dw 0
dw 0
db 0
db 10010010b
-db 00000000b
+db 00100000b
db 0
.gdt_end: ; later calculates offset in defs below
diff --git a/src/bootloader/print.asm b/src/bootloader/print.asm
new file mode 100644
index 0000000..29769f5
--- /dev/null
+++ b/src/bootloader/print.asm
@@ -0,0 +1,21 @@
+;TODO fix null problem, allow passing value insted of pointer
+bios_print:
+pusha
+mov ah, 0x0e
+
+.print_loop:
+mov al, [bx]
+cmp al, 0
+je .fini
+
+int 0x10
+inc bx
+jmp .print_loop
+
+.fini:
+mov al, 0xd
+int 0x10
+mov al, 0xa
+int 0x10
+popa
+ret
diff --git a/src/bootloader/video.asm b/src/bootloader/video.asm
index 5b292c2..e47c1dc 100644
--- a/src/bootloader/video.asm
+++ b/src/bootloader/video.asm
@@ -151,25 +151,21 @@ ret
.vbe_unsupported:
mov bx, .unsupported_msg
-mov cx, 0
call bios_print
jmp $
.vbe_generic_error:
mov bx, .lazyerror_msg
-mov cx, 0
call bios_print
jmp $
.edid_error:
mov bx, .ediderror_msg
-mov cx, 0
call bios_print
jmp $
.res_unsupported:
mov bx, .res_unsupported_msg
-mov cx, 0
call bios_print
jmp $
diff --git a/src/debug/gdbinit.gdb b/src/debug/gdbinit.gdb
index 6c0cc28..c890f8d 100644
--- a/src/debug/gdbinit.gdb
+++ b/src/debug/gdbinit.gdb
@@ -1,4 +1,11 @@
target remote localhost:1234
symbol-file debug/debug_syms.o
-break *0x7c00
+hb smp_boot
+
+
+
+define cs2bs
+ print (1 << (5 + $arg0))
+end
continue
+
diff --git a/src/debug/gdbinit.py b/src/debug/gdbinit.py
new file mode 100755
index 0000000..75ab5ca
--- /dev/null
+++ b/src/debug/gdbinit.py
@@ -0,0 +1,28 @@
+class NextInstructionAddress(gdb.Command):
+ """
+Run until Next Instruction address.
+
+Usage: nia
+
+Put a temporary breakpoint at the address of the next instruction, and continue.
+
+Useful to step over int interrupts.
+
+See also: http://stackoverflow.com/questions/24491516/how-to-step-over-interrupt-calls-when-debugging-a-bootloader-bios-with-gdb-and-q
+"""
+ def __init__(self):
+ super().__init__(
+ 'nia',
+ gdb.COMMAND_BREAKPOINTS,
+ gdb.COMPLETE_NONE,
+ False
+ )
+ def invoke(self, arg, from_tty):
+ frame = gdb.selected_frame()
+ arch = frame.architecture()
+ pc = gdb.selected_frame().pc()
+ length = arch.disassemble(pc)[0]['length']
+ gdb.Breakpoint('*' + str(pc + length), temporary = True)
+ gdb.execute('continue')
+
+NextInstructionAddress()
diff --git a/src/debug/i8086.xml b/src/debug/i8086.xml
new file mode 100644
index 0000000..0c91287
--- /dev/null
+++ b/src/debug/i8086.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2017 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+ <architecture>i8086</architecture>
+ <feature name="org.gnu.gdb.i386.core">
+ <flags id="i386_eflags" size="4">
+ <field name="CF" start="0" end="0"/>
+ <field name="" start="1" end="1"/>
+ <field name="PF" start="2" end="2"/>
+ <field name="AF" start="4" end="4"/>
+ <field name="ZF" start="6" end="6"/>
+ <field name="SF" start="7" end="7"/>
+ <field name="TF" start="8" end="8"/>
+ <field name="IF" start="9" end="9"/>
+ <field name="DF" start="10" end="10"/>
+ <field name="OF" start="11" end="11"/>
+ <field name="NT" start="14" end="14"/>
+ <field name="RF" start="16" end="16"/>
+ <field name="VM" start="17" end="17"/>
+ <field name="AC" start="18" end="18"/>
+ <field name="VIF" start="19" end="19"/>
+ <field name="VIP" start="20" end="20"/>
+ <field name="ID" start="21" end="21"/>
+ </flags>
+
+ <reg name="eax" bitsize="32" type="int32"/>
+ <reg name="ecx" bitsize="32" type="int32"/>
+ <reg name="edx" bitsize="32" type="int32"/>
+ <reg name="ebx" bitsize="32" type="int32"/>
+ <reg name="esp" bitsize="32" type="data_ptr"/>
+ <reg name="ebp" bitsize="32" type="data_ptr"/>
+ <reg name="esi" bitsize="32" type="int32"/>
+ <reg name="edi" bitsize="32" type="int32"/>
+
+ <reg name="eip" bitsize="32" type="code_ptr"/>
+ <reg name="eflags" bitsize="32" type="i386_eflags"/>
+ <reg name="cs" bitsize="32" type="int32"/>
+ <reg name="ss" bitsize="32" type="int32"/>
+ <reg name="ds" bitsize="32" type="int32"/>
+ <reg name="es" bitsize="32" type="int32"/>
+ <reg name="fs" bitsize="32" type="int32"/>
+ <reg name="gs" bitsize="32" type="int32"/>
+
+ <reg name="st0" bitsize="80" type="i387_ext"/>
+ <reg name="st1" bitsize="80" type="i387_ext"/>
+ <reg name="st2" bitsize="80" type="i387_ext"/>
+ <reg name="st3" bitsize="80" type="i387_ext"/>
+ <reg name="st4" bitsize="80" type="i387_ext"/>
+ <reg name="st5" bitsize="80" type="i387_ext"/>
+ <reg name="st6" bitsize="80" type="i387_ext"/>
+ <reg name="st7" bitsize="80" type="i387_ext"/>
+
+ <reg name="fctrl" bitsize="32" type="int" group="float"/>
+ <reg name="fstat" bitsize="32" type="int" group="float"/>
+ <reg name="ftag" bitsize="32" type="int" group="float"/>
+ <reg name="fiseg" bitsize="32" type="int" group="float"/>
+ <reg name="fioff" bitsize="32" type="int" group="float"/>
+ <reg name="foseg" bitsize="32" type="int" group="float"/>
+ <reg name="fooff" bitsize="32" type="int" group="float"/>
+ <reg name="fop" bitsize="32" type="int" group="float"/>
+ </feature>
+ <feature name="org.gnu.gdb.i386.32bit.sse">
+ <vector id="v4f" type="ieee_single" count="4"/>
+ <vector id="v2d" type="ieee_double" count="2"/>
+ <vector id="v16i8" type="int8" count="16"/>
+ <vector id="v8i16" type="int16" count="8"/>
+ <vector id="v4i32" type="int32" count="4"/>
+ <vector id="v2i64" type="int64" count="2"/>
+ <union id="vec128">
+ <field name="v4_float" type="v4f"/>
+ <field name="v2_double" type="v2d"/>
+ <field name="v16_int8" type="v16i8"/>
+ <field name="v8_int16" type="v8i16"/>
+ <field name="v4_int32" type="v4i32"/>
+ <field name="v2_int64" type="v2i64"/>
+ <field name="uint128" type="uint128"/>
+ </union>
+ <flags id="i386_mxcsr" size="4">
+ <field name="IE" start="0" end="0"/>
+ <field name="DE" start="1" end="1"/>
+ <field name="ZE" start="2" end="2"/>
+ <field name="OE" start="3" end="3"/>
+ <field name="UE" start="4" end="4"/>
+ <field name="PE" start="5" end="5"/>
+ <field name="DAZ" start="6" end="6"/>
+ <field name="IM" start="7" end="7"/>
+ <field name="DM" start="8" end="8"/>
+ <field name="ZM" start="9" end="9"/>
+ <field name="OM" start="10" end="10"/>
+ <field name="UM" start="11" end="11"/>
+ <field name="PM" start="12" end="12"/>
+ <field name="FZ" start="15" end="15"/>
+ </flags>
+
+ <reg name="xmm0" bitsize="128" type="vec128" regnum="32"/>
+ <reg name="xmm1" bitsize="128" type="vec128"/>
+ <reg name="xmm2" bitsize="128" type="vec128"/>
+ <reg name="xmm3" bitsize="128" type="vec128"/>
+ <reg name="xmm4" bitsize="128" type="vec128"/>
+ <reg name="xmm5" bitsize="128" type="vec128"/>
+ <reg name="xmm6" bitsize="128" type="vec128"/>
+ <reg name="xmm7" bitsize="128" type="vec128"/>
+
+ <reg name="mxcsr" bitsize="32" type="i386_mxcsr" group="vector"/>
+ </feature>
+</target>
+
diff --git a/src/include/acpi.h b/src/include/acpi.h
index c15e044..f06bc9b 100644
--- a/src/include/acpi.h
+++ b/src/include/acpi.h
@@ -1,30 +1,20 @@
+#ifndef acpi_included
+#define acpi_included
#include <stdint.h>
-#include <libc.h>
+#include <stdbool.h>
+#include <int.h>
-struct rsdp_v1 {
- char sig[8];
- uint8_t checksum;
- char OEMID[6];
- uint8_t version;
- uint32_t rsdt_addr;
-} __attribute__((packed));
+//sdt types
+#define SDT_MADT 0
+#define SDT_HPET 1
-struct rsdp_v2 {
- struct rsdp_v1 v1;
- uint32_t len;
- uint64_t xsdt_addr;
- uint8_t extended_checksum;
- uint8_t reserved[3];
-} __attribute__((packed));
+void find_root_sdp();
+void *find_sdt(int type);
+void debug_acpi();
-typedef union rsdp_t {
- struct rsdp_v1 v1;
- struct rsdp_v2 v2;
-} rsdp_t;
-
-struct acpi_header {
+typedef struct sdt {
char sig[4];
uint32_t length;
uint8_t revision;
@@ -34,6 +24,7 @@ struct acpi_header {
uint32_t OEMRevision;
uint32_t creator_id;
uint32_t creator_revision;
-} __attribute__((packed));
+} __attribute__((packed)) sdt_head;
+
-rsdp_t *find_RSDP();
+#endif
diff --git a/src/include/heap.h b/src/include/heap.h
new file mode 100644
index 0000000..b1d7d6a
--- /dev/null
+++ b/src/include/heap.h
@@ -0,0 +1,5 @@
+void *malloc(size_t size);
+void *realloc(void *old_chunk, size_t size);
+void malloc_init();
+void debug_heap();
+void free(void *size);
diff --git a/src/include/int.h b/src/include/int.h
new file mode 100644
index 0000000..8cc6a88
--- /dev/null
+++ b/src/include/int.h
@@ -0,0 +1,84 @@
+#ifndef int_header
+#define int_header
+
+#include <stdint.h>
+#include <stddef.h>
+
+
+
+void usleep(unsigned int us);
+void init_interrupts();
+
+typedef uint32_t *lapic_t;
+
+//this is only for madt; do we really need it here?
+struct ioapic_t {
+ void *address;
+ unsigned int gsi_base;
+ unsigned int gsi_count;
+};
+
+//future: if we start to do things like this more then once,
+struct ioapic_fixedlen {
+ size_t count;
+ struct ioapic_t *ioapic;
+};
+
+//TODO change name
+struct apic_vt {
+ uint8_t vector;
+ unsigned int delivery_mode:3;
+ unsigned int dest_mode:1;
+ unsigned int delivery_status:1;
+ unsigned int polarity:1; //0 = high, 1 = low.
+ unsigned int remote_irr:1;
+ unsigned int trigger_mode:1;
+ unsigned int mask:1;
+ unsigned long int reserved:40;
+ unsigned int destination:7;
+} __attribute__((packed));
+
+
+//simplified idt_descriptor makes things easier
+struct idt_entry {
+ void *addr;
+ unsigned int ist:3;
+ unsigned int type:4;
+ unsigned int priv:2;
+};
+
+#define IOAPIC_REDIRECT_FIXED(vector, destination) \
+ ((struct apic_vt) { \
+ .vector = vector, \
+ .delivery_mode = 0, \
+ .dest_mode = 0, \
+ .polarity = 0, \
+ .remote_irr = 0, \
+ .trigger_mode = 0, \
+ .mask = 0, \
+ .destination = destination \
+})
+
+#define KERNEL_IDT_GATE(isr) \
+ ((struct idt_entry) { \
+ .addr = isr, \
+ .ist = 0, \
+ .type = INT_GATE_64, \
+ .priv = 0 \
+})
+
+#define TASK_GATE_64 0x5
+#define INT_GATE_64 0xe
+#define TRAP_GATE_64 0xf
+
+#define SPURRIOUS_VECTOR 255
+
+
+void create_fixed_interrupt(unsigned int irq, struct apic_vt *redirect);
+void clear_int();
+unsigned int alloc_idt(struct idt_entry *entry);
+void free_idt(unsigned int entry);
+void modify_idt(struct idt_entry *entry, unsigned int vector);
+
+
+#endif
diff --git a/src/include/io.h b/src/include/io.h
new file mode 100644
index 0000000..fb19bdc
--- /dev/null
+++ b/src/include/io.h
@@ -0,0 +1,38 @@
+#ifndef io_header
+#define io_header
+
+#include <stdint.h>
+#include <printf.h>
+
+static inline void outb(uint16_t port, uint8_t value) {
+ asm volatile("outb %1, %0" :: "a"(value), "Nd"(port));
+}
+
+static inline uint8_t inb(uint16_t port) {
+ uint8_t ret;
+ asm volatile("inb %0, %1" : "=a"(ret) : "Nd"(port));
+ return(ret);
+}
+
+static inline void io_wait() {
+ asm volatile("outb 0x80, %%al"::"a"(0));
+}
+
+static inline uint64_t read_tsc() {
+ uint64_t time;
+ asm volatile("xor rax, rax\n"
+ "rdtsc\n"
+ "shl rdx, 32\n"
+ "or rax, rdx\n"
+ "mov %0, rax\n"
+ :"=r"(time):);
+ return time;
+
+}
+
+void outb_wait(uint16_t port, uint8_t value);
+void read_msr(uint32_t addr, uint64_t *value);
+void write_msr(uint32_t addr, uint64_t value);
+void hlt();
+uint64_t get_rip();
+#endif
diff --git a/src/include/isv.h b/src/include/isv.h
new file mode 100644
index 0000000..d9dfa1b
--- /dev/null
+++ b/src/include/isv.h
@@ -0,0 +1,25 @@
+#ifndef isv_defined
+#define isv_defined
+
+//TODO move to int.h
+
+struct int_frame {
+ void *rip;
+ uint64_t segment_selector;
+ uint64_t rflags;
+ void *rsp;
+ uint64_t stack_segment;
+} __attribute__((packed));
+
+struct exception_frame {
+ uint64_t err;
+ struct int_frame frame;
+} __attribute__((packed));
+
+__attribute__((interrupt)) void spurrious_int(void *unused);
+__attribute__((interrupt)) void kernel_block(void *unused);
+__attribute__((interrupt)) void fatal_hwexception(struct int_frame *frame);
+__attribute__((interrupt)) void fatal_hwexception_errcode(struct exception_frame *frame);
+__attribute__((interrupt)) void lapic_timer_racefixer(void *unused);
+
+#endif
diff --git a/src/include/kernel.h b/src/include/kernel.h
index 2a87f5e..4d8ea22 100644
--- a/src/include/kernel.h
+++ b/src/include/kernel.h
@@ -1,5 +1,13 @@
-#define EASTEREGG_BLOATWARE //TODO move to some kind of global config file
-void panic();
+#ifndef KERNEL
+#define KERNEL
-#define KERNEL_PANIC_INVOKED 0
-//more to come
+
+#define PA_OFFSET 0xffff800000000000
+#define TXT_OFFSET 0xffffffff80000000
+
+#define PHYS_TO_VIRT(addr) ((void *)(addr) + PA_OFFSET)
+
+#define DEV_EMAIL "brett_weiland@bpcspace.com"
+
+
+#endif
diff --git a/src/include/libc.h b/src/include/libc.h
index c7ccda7..d0789cf 100644
--- a/src/include/libc.h
+++ b/src/include/libc.h
@@ -1,13 +1,17 @@
#ifndef _STRING_H_
#define _STRING_H_
#include <stddef.h>
+#include <stdint.h>
void *strcpy(char *dest, char *src);
void *memcpy(void *dest, void *src, size_t n); //TODO
void *bzero(const void *dest, size_t size);
void *memset(void *s, char c, size_t n);
+size_t strlen(const char *s);
int strcmp(const char *str1, const char *str2);
int strncmp(const char *str1, const char *str2, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
int ceil(double n1);
+int round(double n1);
+
#endif
diff --git a/src/include/madt.h b/src/include/madt.h
new file mode 100644
index 0000000..84bfa5d
--- /dev/null
+++ b/src/include/madt.h
@@ -0,0 +1,20 @@
+#ifndef madt_header
+#define madt_header
+#include <int.h>
+
+struct cores_info {
+ unsigned int corecount;
+ uint8_t apic_id[256];
+ uint8_t bsp;
+};
+
+void init_madt();
+void get_ioapic(struct ioapic_fixedlen *ret);
+void get_coreinfo(struct cores_info *cores);
+void debug_madt();
+unsigned int irq_to_gsi(unsigned int irq);
+lapic_t get_lapic();
+void boot_multicore();
+
+
+#endif
diff --git a/src/include/math.h b/src/include/math.h
new file mode 100644
index 0000000..10b0521
--- /dev/null
+++ b/src/include/math.h
@@ -0,0 +1,6 @@
+#ifndef MATH_INCLUDED
+#define MATH_INCLUDED
+
+#define DIV_ROUND_UP(number, factor) (((number) + ((factor) - 1)) / factor)
+
+#endif
diff --git a/src/include/paging.h b/src/include/paging.h
index 3d31ef2..16afae2 100644
--- a/src/include/paging.h
+++ b/src/include/paging.h
@@ -1,96 +1,23 @@
-#include <stdbool.h>
-//paging errors
-#define PAGEMAP_LOCATION 0x4000
#ifndef _PAGE_H_
#define _PAGE_H_
-#include <stdint.h>
-
-#define PAGE_VIRT_UNALIGNED 0x01
-#define PAGE_PHYS_UNALIGNED 0x02
-#define PAGE_PHYS_INVALID 0x03
-#define PAGE_VIRT_INVALID 0x04
-
-//*
-typedef struct __attribute__((packed)) {
- unsigned int present : 1; // present, must be one when accessed.
- unsigned int read_write : 1; // if set to one, read and write is set
- unsigned int user : 1; // another bit we'll never use, for seperating CPL 0-2 and 3+
- unsigned int writethrough_cache : 1; // honestly maybe I should look into caching
- unsigned int cachable : 1; // hardware chaching. 0 is enabled, whats the worst that could happen?
- unsigned int accessed : 1; // we'll never use any of these!
- unsigned int zg0 : 1; // needs to be (and will be) zero'd
- unsigned int size : 1;
- unsigned int zg1 : 1; // needs to be (and will be) zero'd
- unsigned int software_marks : 3; // available for our own use, I doubt we'll use it in such a simple thing
-
- uintptr_t base_ptr : 40;
- unsigned int sign:11;
-} page_entry;
-
-
-typedef struct __attribute__((packed)) {
- page_entry pml4e[512];
- page_entry pdpe[512];
- page_entry pde[512];
- page_entry pte[512];
-} page_table;
-
-#define MEM_AVAILABLE 1
-#define MEM_RESERVED 2
-#define MEM_APCI_RECLAIMABLE 3
-#define MEM_APCI_NVS 4
-#define MEM_BAD 5
-
-#define PAGE_SIZE_4K 12
-#define PAGE_SIZE_2M 21
-#define PAGE_SIZE_1G 30
-#define MAX_BUDDY_ORDER 8
-
-#define MAX_ZONE_CNT 16 //should cover all cases
-
-struct memory_table {
- void *base;
- uint64_t length;
- uint32_t type;
- uint32_t ACPI;
-} __attribute__((packed));
-
-/**
- * the bsizes are there so we don't have to calculate it every time.
- *
- * Keep in mind that at if the allocator reaches the last buddy,
- * it _will_ have to calculate the bitwidth, even if it's a multiple of 64.
- * This scenario hopefully won't happen much during time sensitive areas,
- * and (I think) linux calculates the buddy size every single time anyway.
-**/
-struct phys_map {
- struct phys_map *next;
- void *zone_paddr;
- uint64_t extra_bits;
- uint64_t *buddy[MAX_BUDDY_ORDER];
-};
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
-//clean up doing extra work some other time
-#define LSIZE_FROM_BITLEN(bitlen) (((bitlen) + 63) / 64)
-#define BITLEN_FROM_LSIZE(lsize) ((lsize) * 64)
-#define GET_BUDDY_BITLEN(zone_len, order) ((zone_len) / (0x1000 << (order)))
-#define GET_ORDER_CHUNKSIZE(order) (0x1000 << ((order)))
+void unmap_lowmem();
+size_t map_complete_physical();
+void debug_print_memory();
-extern void* _meminfo_loc;
-extern void* _stage2_pagetable;
-bool map_page(void *virtual_addr, void *physical_addr, uint8_t PAGE_SIZE);
-void debug_print_memory();
-void create_pagetable_stage2(uint64_t free_mem);
-void init_memory(); //TODO removeme
-void init_pmap();
-void *palloc();
-void *pfree();
+struct phys_map *init_pmap(size_t pagetable_size);
+void *palloc(size_t size);
+void pfree(void *addr, size_t size);
void debug_pmap();
+void get_mem_capabilities();
+void ram_stresser();
#endif
-
diff --git a/src/include/panic.h b/src/include/panic.h
index 1386348..6a987f4 100644
--- a/src/include/panic.h
+++ b/src/include/panic.h
@@ -1,27 +1,59 @@
#ifndef PANIC_INCLUDED
#define PANIC_INCLUDED
-#define EASTEREGG_BLOATWARE
-
#include <stdint.h>
-void panic(int reason, int type);
+#define EASTEREGG_BLOATWARE
+
+//TODO this needs to be moved once we find somehwere better
struct stack_frame {
- struct stack_frame *next;
- uint64_t function_base;
+ struct stack_frame *next; //rbp
+ void *function_base; //rip
+} __attribute__((packed));
+
+struct registers {
+ uint64_t rax, rbx, rcx, rdx, rsi, rdi;
} __attribute__((packed));
-//kernel panic reasons, likely to grow at an extremely fast rate
-#define KERNEL_PANIC_PMAPSIZE 0
-#define KERNEL_PANIC_RSDP_UNFOUND 1
-#define KERNEL_PANIC_KERNEL_RETURNED 2
+void panic(int reason, void *frame_p, struct registers *regs);
+
+
+#define PANIC(reason) panic(reason, 0, 0)
+
+//hardware exceptions/faults
+//kernel panic reasons 0-31 reserved for these
+//later on, we can make an ugly function to find our vector.
+//I did a lot of work assuming it was pushed onto the stack,
+//so if I choose not to impliment that these defs will be deleted.
+/**
+#define KERNEL_PANIC_HWE_DE 0
+#define KERNEL_PANIC_HWE_BR 5
+#define KERNEL_PANIC_HWE_UD 6
+#define KERNEL_PANIC_HWE_NM 7
+#define KERNEL_PANIC_HWE_DF 8
+#define KERNEL_PANIC_HWE_TS 10
+#define KERNEL_PANIC_HWE_NP 11
+#define KERNEL_PANIC_HWE_SS 12
+#define KERNEL_PANIC_HWE_GP 13
+#define KERNEL_PANIC_HWE_PF 14
+#define KERNEL_PANIC_HWE_MF 16
+#define KERNEL_PANIC_HWE_AC 17
+#define KERNEL_PANIC_HWE_MC 18
+#define KERNEL_PANIC_HWE_XM 19
+#define KERNEL_PANIC_HWE_VE 20
+#define KERNEL_PANIC_HWE_SE 30
+**/
+#define KERNEL_PANIC_HW_EXCEPTION 0
+#define KERNEL_PANIC_HW_EXCEPTION_ERR 1 //exception with error code
+//kernel generated exceptions
+#define KERNEL_PANIC_RSDP_UNFOUND 32
+#define KERNEL_PANIC_KERNEL_RETURNED 33
+#define KERNEL_PANIC_INVALID_PFREE 34
+#define KERNEL_PANIC_INVALID_RSDT 35
+#define KERNEL_PANIC_INVALID_IOAPIC_VEC 36
+#define KERNEL_PANIC_HPET_REQUIRED 37
-//kernel panic types, may or may not expand once I get further in development
-#define KERNEL_PANIC_INVOKED 0
-#define KERNEL_PANIC_ERROR 1 //i'll change this once I see what happends
-//TODO move this to some kind of global more accesable header
-#define DEV_EMAIL "brett_weiland@bpcspace.com"
#endif
diff --git a/src/include/random.h b/src/include/random.h
new file mode 100644
index 0000000..6f35278
--- /dev/null
+++ b/src/include/random.h
@@ -0,0 +1,5 @@
+#ifndef random_header
+#define random_header
+void randinit();
+unsigned int randint();
+#endif
diff --git a/src/include/serial.h b/src/include/serial.h
index 824e245..ef5eecf 100644
--- a/src/include/serial.h
+++ b/src/include/serial.h
@@ -3,14 +3,25 @@
#define _SERIAL_H_
#include <stdint.h>
+#include <stdbool.h>
+
#define COM1 0x3f8
#define COM2 0x2f8
#define COM3 0x3e8
#define COM4 0x2e8
-int init_serial(uint16_t port);
+
+bool init_serial(uint16_t port);
void serial_out(uint16_t port, char *string);
void _putchar_serial(uint16_t port, char character);
+void move_cursor(unsigned int x, unsigned int y);
+
+
+//TODO fix shitty header
+void _putchar_screen(char character);
+
+void clear_screen();
+
#endif
diff --git a/src/include/smp.h b/src/include/smp.h
new file mode 100644
index 0000000..c4a675a
--- /dev/null
+++ b/src/include/smp.h
@@ -0,0 +1,4 @@
+#ifndef SMP_INCLUDED
+#define SMP_INCLUDED
+void smp_boot();
+#endif
diff --git a/src/include/testmalloc.h b/src/include/testmalloc.h
new file mode 100644
index 0000000..25ab7f3
--- /dev/null
+++ b/src/include/testmalloc.h
@@ -0,0 +1,6 @@
+#ifndef testmalloc_header
+#define testmalloc_header
+
+void test_malloc(unsigned int cnt);
+
+#endif
diff --git a/src/include/timer.h b/src/include/timer.h
new file mode 100644
index 0000000..0277e87
--- /dev/null
+++ b/src/include/timer.h
@@ -0,0 +1,8 @@
+#ifndef timer
+#define timer
+
+void init_timer();
+void usleep(unsigned int us);
+uint64_t timestamp();
+
+#endif
diff --git a/src/indigo_os b/src/indigo_os
index 3df46fd..0a9c1af 100755
--- a/src/indigo_os
+++ b/src/indigo_os
Binary files differ
diff --git a/src/kernel/acpi.c b/src/kernel/acpi.c
index 0c22fe4..e5a6e4d 100644
--- a/src/kernel/acpi.c
+++ b/src/kernel/acpi.c
@@ -1,58 +1,169 @@
#include <acpi.h>
#include <stdint.h>
#include <printf.h>
+#include <kernel.h>
+#include <stdbool.h>
+#include <kernel.h>
+#include <io.h>
+#include <int.h>
+#include <libc.h>
+#include <panic.h>
-static int RSDP_verify(void *rsdp_pointer) {
- printf("Verifying potential RSDP at address 0x%p... ", rsdp_pointer);
- union rsdp_t *rsdp = rsdp_pointer;
+
+//finding rsdp
+typedef struct rsdp {
+ char sig[8];
+ uint8_t checksum;
+ char OEMID[6];
+ uint8_t revision;
+ uint32_t rsdt;
+
+ //these only exist on REV > 1
+ uint32_t len;
+ uint64_t xsdt;
+ uint8_t extended_checksum;
+ uint8_t reserved[3];
+
+} __attribute__((packed)) root_sdp;
+
+
+//root descriptor SDTs
+struct rsdt {
+ sdt_head header;
+ uint32_t sdt_pointers[];
+} __attribute__((packed));
+
+struct xsdt {
+ sdt_head header;
+ uint64_t sdt_pointers[];
+} __attribute__((packed));
+
+root_sdp *rsdp;
+
+
+
+void debug_acpi() {
+ sdt_head *sdt;
+ int sdt_i, sdt_cnt;
+
+ if(rsdp->revision) {
+ struct xsdt *root = PHYS_TO_VIRT(rsdp->xsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 8;
+ printf("sdts found in apic headers: %i\n", sdt_cnt);
+ for(sdt_i = 0; sdt_i < sdt_cnt; sdt_i++) {
+ sdt = PHYS_TO_VIRT(root->sdt_pointers[sdt_i]);
+ printf("ACPI debug:%.4s\n", sdt->sig);
+ }
+ }
+ else {
+ struct rsdt *root = PHYS_TO_VIRT((uint64_t)rsdp->rsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 4;
+ printf("sdts found in apic headers: %i\n", sdt_cnt);
+ for(sdt_i = 0; sdt_i < sdt_cnt; sdt_i++) {
+ sdt = PHYS_TO_VIRT((uint64_t)root->sdt_pointers[sdt_i]);
+ printf("ACPI debug:%.4s\n", sdt->sig);
+ }
+ }
+}
+
+//TODO clean up confusing variable name rsdt
+void *find_sdt(int type) {
+ char sig[4];
+ sdt_head *sdt;
+ int sdt_i, sdt_cnt;
+
+ //If we never need to expand this, then you can clean it up.
+ switch(type) {
+ case SDT_MADT:
+ strcpy(sig, "APIC");
+ break;
+ case SDT_HPET:
+ strcpy(sig, "HPET");
+ break;
+ }
+
+ if(rsdp->revision) {
+ struct xsdt *root = PHYS_TO_VIRT(rsdp->xsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 8;
+ for(sdt_i = 0; sdt_i < sdt_cnt - 1; sdt_i++) {
+ sdt = PHYS_TO_VIRT((uint64_t)root->sdt_pointers[sdt_i]);
+ if(!(strncmp(sdt->sig, sig, 4))) {
+ return sdt;
+ }
+ }
+ }
+ else {
+ struct rsdt *root = PHYS_TO_VIRT((uint64_t)rsdp->rsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 4;
+ for(sdt_i = 0; sdt_i < sdt_cnt - 1; sdt_i++) {
+ sdt = PHYS_TO_VIRT((uint64_t)root->sdt_pointers[sdt_i]);
+ if(!(strncmp(sdt->sig, sig, 4))) {
+ return sdt;
+ }
+ }
+ }
+ return 0;
+}
+
+bool verify_sdt(sdt_head *sdt) {
uint8_t checksum = 0;
- char *rsdp_csm_ptr = rsdp_pointer;
+ for(int i = 0; i < sdt->length; i++) checksum += ((uint8_t *)sdt)[i];
+ return checksum == 0;
+}
+
+static root_sdp *verify_sdp(root_sdp *uv_rsdp) {
+ char *rsdp_char_ptr = (char *)uv_rsdp;
int i;
- if(checksum) return 0;
- if(rsdp->v1.version) {
- printf("APCI revision > 2.\n");
- checksum = 0;
- printf("len : %i\n", rsdp->v2.len);
- for(i = 0; i < rsdp->v2.len; i++) {
- checksum += rsdp_csm_ptr[i];
+ uint8_t checksum = 0;
+ if(uv_rsdp->revision) {
+ for(i = 0; i < uv_rsdp->len; i++) {
+ checksum += rsdp_char_ptr[i];
}
}
else {
- printf("APCI revision 1.\n");
for(i = 0; i <= 20; i++) {
- checksum += rsdp_csm_ptr[i];
+ checksum += rsdp_char_ptr[i];
}
}
- if(checksum) {
- return 0;
- printf("Invalid, searching on.\n");
+ if(!checksum) {
+ printf("Found RSDP revision %i at address %x.\n", uv_rsdp->revision, uv_rsdp);
+ return uv_rsdp;
}
- printf("RSDP Verified!\n");
- return 1;
+ printf("Skipped over invalid RSDP at 0x%p.\n", uv_rsdp);
+ return 0;
}
-rsdp_t *find_RSDP() {
+
+void find_root_sdp() {
const char sig[9] = "RSD PTR ";
uintptr_t *p = (void *)0x040e;
uintptr_t *ebda_unshifted = (void *)p;
+ bool rsdt_verified;
- void *ebda = (void *)((uintptr_t)ebda_unshifted << (uintptr_t)4 & (uintptr_t)0xfffff);
+ void *ebda = PHYS_TO_VIRT((void *)((uintptr_t)ebda_unshifted << (uintptr_t)4 & (uintptr_t)0xfffff));
- for(void *i = ebda; i <= ebda + 64000; i += 16) {
- if(!(memcmp(sig, i, 8))) {
- if(RSDP_verify(i)) {
- return(i);
- }
- }
+
+
+ for(void *i = ebda; i <= ebda + 64000; i += 16)
+ if(!(memcmp(sig, i, 8)) && ((rsdp = verify_sdp(i)))) break;
+
+
+ for(void *i = PHYS_TO_VIRT(0xe0000); i <= PHYS_TO_VIRT(0xfffff); i += 16)
+ if(!(memcmp(sig, i, 8)) && ((rsdp = verify_sdp(i)))) break;
+
+ if(!(rsdp)) {
+ printf("Couldn't find the RSDP... not sure what to do now.\n");
+ PANIC(KERNEL_PANIC_RSDP_UNFOUND);
+ }
+
+ if(rsdp->revision) {
+ rsdt_verified = verify_sdt(PHYS_TO_VIRT(rsdp->xsdt));
+ }
+ else {
+ rsdt_verified = verify_sdt(PHYS_TO_VIRT((uint64_t)rsdp->rsdt));
}
- for(void *i = (void *)0xe0000; i <= (void *)0xfffff; i += 16) {
- if(!(memcmp(sig, i, 8))) {
- if(RSDP_verify(i)) {
- return(i);
- }
- }
+ if(!(rsdt_verified)) {
+ PANIC(KERNEL_PANIC_INVALID_RSDT);
}
}
-
-
diff --git a/src/kernel/drivers/serial.c b/src/kernel/drivers/serial.c
deleted file mode 100644
index 25f89ad..0000000
--- a/src/kernel/drivers/serial.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <stdint.h>
-#include <serial.h>
-static inline void outb(uint16_t port, uint8_t value) {
- asm volatile(
- "outb %0, %1" :: "a"(value), "Nd"(port)
- );
-}
-
-static inline uint8_t inb(uint16_t port) {
- uint8_t ret;
- asm volatile(
- "inb %1, %0" : "=a"(ret) : "Nd"(port)
- );
- return(ret);
-}
-
-int init_serial(uint16_t port) {
- outb(port + 1, 0x00);
- outb(port + 3, 0x80);
- outb(port + 0, 0x06);
- outb(port + 1, 0x00);
- outb(port + 3, 0x03);
- outb(port + 2, 0xc7);
- outb(port + 4, 0x0b);
- outb(port + 4, 0x1e);
-
- outb(port + 0, 0xae); // test char
-
- if(inb(port + 0) != 0xae)
- return 1;
-
- outb(port + 4, 0x0f); // dissable interupts
- return 0;
-}
-
-void _putchar_serial(uint16_t port, char msg) {
- while(!(inb(port + 5) & 0x20)); //wait for transmit to be done
- outb(port, msg);
-}
diff --git a/src/kernel/heap.c b/src/kernel/heap.c
new file mode 100644
index 0000000..db6392f
--- /dev/null
+++ b/src/kernel/heap.c
@@ -0,0 +1,211 @@
+#include <paging.h>
+#include <printf.h>
+#include <libc.h>
+#include <io.h>
+
+/** a disclaimer-
+ * I've never made an OS, so I don't know what kind of structures I'll have.
+ * Because of this, I'm not YET using a slab allocator.
+ * This allocator allocates sizes of 2^n, starting at 32, which can waste lots of space.
+ * In other places, you'll see me reallocating when it's not nessesary,
+ * as if my allocator doesn't over-allocate.
+ *
+ * Later in development, I will create a slab allocator, making it so that this isn't an issue.
+**/
+
+
+
+#define MIN_CHUNK_ORDER 5 //equal to 32 bytes for heap_chunk struct. Keeping away from 24 for easy division.
+#define MAX_CHUNK_I 6
+#define CHUNK_LIST_LEN MAX_CHUNK_I + 1
+#define LOG_SUB 63 - MIN_CHUNK_ORDER
+#define PAGE_SIZE 0x1000 //TODO [minor] maybe move this to some header somewhere
+
+#define CHUNK_SIZE_FROM_INDEX(i) ((1 << ((i) + MIN_CHUNK_ORDER)))
+#define CHUNK_INDEX_FROM_SIZE(s) ((63 - MIN_CHUNK_ORDER - __builtin_clzl((s))))
+
+
+typedef struct __attribute__((packed)) heap_chunk {
+ unsigned int free:1;
+ unsigned int size:4; //will use with flags later if needed
+ unsigned int lsize:4;
+ unsigned long reserved:55;
+ struct heap_chunk *fd;
+ struct heap_chunk *bk;
+} chunk;
+
+struct heap_chunk_roots {
+ void *fd;
+};
+
+
+//TODO this wastes some memory
+chunk arena[CHUNK_LIST_LEN];
+
+
+void debug_heap() {
+ chunk *on_chunk, *last_chunk;
+ size_t chunk_expected_size;
+ size_t chunk_actual_size;
+ for(unsigned int l = 0; l < CHUNK_LIST_LEN; l++) {
+ chunk_expected_size = CHUNK_SIZE_FROM_INDEX(l);
+ printf("\n%i sized chunks:\n", chunk_expected_size);
+ for(on_chunk = arena[l].fd; on_chunk != 0; on_chunk = on_chunk->fd) {
+ chunk_actual_size = CHUNK_SIZE_FROM_INDEX(on_chunk->size);
+ printf("\t%p", on_chunk);
+ if(chunk_expected_size != chunk_actual_size) {
+ printf("\nFound chunk of size %i in %i sized freebin!!!!\n", chunk_actual_size, chunk_expected_size);
+ hlt();
+ }
+ if(!on_chunk->free) {
+ printf("\nChunk found in freebin isn't free!\n");
+ hlt();
+ }
+ //may take a while
+ if((uintptr_t)on_chunk & (0x1000 - 1)) {
+ last_chunk = (void *)on_chunk - CHUNK_SIZE_FROM_INDEX(on_chunk->lsize);
+ if(last_chunk->size != on_chunk->lsize) {
+ printf("\nChunk before this one is a different size then lsize!");
+ hlt();
+ }
+ }
+ }
+ }
+ printf("\n\n");
+}
+
+
+
+void malloc_init() {
+ bzero(&arena, sizeof(arena));
+}
+
+void free(void *addr) {
+ chunk *on_chunk, *buddy_chunk, *next_chunk, *chunk_iter;
+ on_chunk = addr - 24;
+
+
+ for(;;) {
+ if(on_chunk->size == (MAX_CHUNK_I + 1)) {
+ pfree(on_chunk, 0x1000);
+ printf("freeing page %p\n", on_chunk);
+ return;
+ }
+ unsigned int chunk_size = CHUNK_SIZE_FROM_INDEX(on_chunk->size);
+ if((uintptr_t)on_chunk & ((chunk_size * 2) - 1)) {
+
+ buddy_chunk = (void *)on_chunk - CHUNK_SIZE_FROM_INDEX(on_chunk->lsize);
+ if((buddy_chunk->size != on_chunk->size) || !(buddy_chunk->free)) {
+ next_chunk = (void *)on_chunk + chunk_size;
+ break;
+ }
+ chunk_iter = buddy_chunk;
+
+ }
+ else {
+
+ buddy_chunk = (void *)on_chunk + chunk_size;
+ if((buddy_chunk->size != on_chunk->size) || !(buddy_chunk->free)) {
+ next_chunk = buddy_chunk;
+ break;
+ };
+ chunk_iter = on_chunk;
+
+ }
+
+ if(buddy_chunk->fd) (buddy_chunk->fd)->bk = buddy_chunk->bk;
+ (buddy_chunk->bk)->fd = buddy_chunk->fd;
+ on_chunk = chunk_iter;
+ on_chunk->size++;
+
+ }
+
+
+ next_chunk->lsize = on_chunk->size;
+ on_chunk->free = 1;
+
+ on_chunk->bk = (chunk *)&arena[on_chunk->size];
+ on_chunk->fd = arena[on_chunk->size].fd;
+ if(arena[on_chunk->size].fd) (arena[on_chunk->size].fd)->bk = on_chunk;
+ arena[on_chunk->size].fd = on_chunk;
+
+
+
+}
+
+
+static void split_chunk(chunk *full_chunk, unsigned int full_size, unsigned int req_size) {
+ chunk *on_chunk;
+
+ full_chunk->size = req_size;
+ full_chunk->free = 0;
+
+ //chunk isn't newly allocated page
+ //our free funciton won't check lsize if addr is divisible by 0x1000
+ if(full_chunk->bk) {
+ if(full_chunk->fd) (full_chunk->fd)->bk = (chunk *)&arena[full_size];
+ arena[full_size].fd = full_chunk->fd;
+ on_chunk = (void *)full_chunk + CHUNK_SIZE_FROM_INDEX(full_size);
+ if((uintptr_t)on_chunk & (0x1000 - 1)) on_chunk->lsize = full_size - 1;
+ }
+
+ on_chunk = (void *)full_chunk + CHUNK_SIZE_FROM_INDEX(req_size);
+
+ for(unsigned int sz = req_size; sz < full_size; sz++) {
+ on_chunk->lsize = (sz == req_size) ? req_size : sz - 1;
+ on_chunk->fd = arena[sz].fd;
+ on_chunk->bk = (chunk *)&arena[sz];
+ on_chunk->size = sz;
+ on_chunk->free = 1;
+
+ arena[sz].fd = on_chunk;
+ on_chunk = (void *)on_chunk + CHUNK_SIZE_FROM_INDEX(sz);
+ }
+}
+
+
+void *malloc(size_t size) {
+ size += sizeof(chunk);
+ chunk *on_chunk;
+ unsigned int chunk_sz_i; //desired chunk size index
+ unsigned int chunk_ck_i; //backup chunk size index in case we need to count up
+ //rounding size to nearest 2^n to find which size it fits into
+
+ if(size < 32) size = 32;
+
+ chunk_sz_i = CHUNK_INDEX_FROM_SIZE(size);
+ if(size & (size - 1)) chunk_sz_i++;
+
+ if(chunk_sz_i > MAX_CHUNK_I) return(void *)0;
+
+ //search for direct hits
+ if(arena[chunk_sz_i].fd) {
+ on_chunk = arena[chunk_sz_i].fd;
+ if(on_chunk->fd) (on_chunk->fd)->bk = (chunk *)&arena[chunk_sz_i];
+ arena[chunk_sz_i].fd = on_chunk->fd;
+ on_chunk->free = 0;
+ return (void *)on_chunk + sizeof(chunk);
+ }
+
+ //search for chunks above our size
+ for(chunk_ck_i = chunk_sz_i + 1; chunk_ck_i < CHUNK_LIST_LEN; chunk_ck_i++) {
+ if(arena[chunk_ck_i].fd) {
+ on_chunk = arena[chunk_ck_i].fd;
+ split_chunk(on_chunk, chunk_ck_i, chunk_sz_i);
+ return (void *)on_chunk + sizeof(chunk);
+ }
+ }
+
+ on_chunk = (void *)palloc(0x1000);
+ printf("allocating page %p\n", on_chunk);
+
+ split_chunk(on_chunk, 7, chunk_sz_i);
+ return (void *)on_chunk + sizeof(chunk);
+
+}
+void *realloc(void *old_chunk, size_t size) {
+ void *new_chunk = malloc(size);
+ memcpy(new_chunk, old_chunk, CHUNK_SIZE_FROM_INDEX(((chunk *)(old_chunk-24))->size));
+ free(old_chunk);
+ return new_chunk;
+}
diff --git a/src/kernel/int.c b/src/kernel/int.c
new file mode 100644
index 0000000..34f1c78
--- /dev/null
+++ b/src/kernel/int.c
@@ -0,0 +1,253 @@
+#include <int.h>
+#include <acpi.h>
+#include <io.h>
+#include <paging.h>
+#include <printf.h>
+#include <isv.h>
+#include <kernel.h>
+#include <libc.h>
+#include <madt.h>
+#include <timer.h>
+#include <panic.h>
+
+#define SEGMENT_GDT 0
+#define SEGMENT_LDT 1
+
+
+
+//io commands
+#define ICW1_ICW4 0x01
+#define ICW1_INIT 0x10
+
+#define ICW4_8086 0x01
+
+
+// PIC
+#define PICM_COMMAND 0x20
+#define PICM_DATA 0x21
+
+#define PICS_COMMAND 0xa0
+#define PICS_DATA 0xa1
+
+#define KERNEL_IDT_DESC_GATE(addr) \
+ ((struct idt_descriptor) { \
+ .offset_1 = (uint16_t)((uint64_t)addr & 0xffff), \
+ .offset_2 = (uint16_t)((uint64_t)addr >> 16), \
+ .offset_3 = (uint32_t)((uint64_t)addr >> 32), \
+ .segment = 0x8, \
+ .ist = 0, \
+ .type = INT_GATE_64, \
+ .priv = 0, \
+ .reserved = 0, \
+ .reserved_1 = 0, \
+ .reserved_2 = 0, \
+ .present = 1 \
+})
+
+#define GDT_ADDR (uint64_t)PHYS_TO_VIRT(0x7e22)
+
+#define IOAPICR_VER 1
+
+struct idt_descriptor {
+ uint16_t offset_1;
+ uint16_t segment;
+ unsigned int ist:3; //interupt stack table offset
+ unsigned int reserved:5;
+ unsigned int type:4;
+ unsigned int reserved_1:1;
+ unsigned int priv:2;
+ unsigned int present:1;
+ uint16_t offset_2;
+ uint32_t offset_3;
+ uint32_t reserved_2;
+} __attribute__((packed));
+
+
+struct segment_descriptor {
+ unsigned int priv:2;
+ unsigned int type:1;
+ unsigned int index:13;
+} __attribute__((packed));
+
+struct idt_reg {
+ uint16_t size;
+ uint64_t offset;
+} __attribute__((packed));
+
+struct gdt_reg {
+ uint16_t size;
+ uint64_t offset;
+} __attribute__((packed));
+
+struct idt_descriptor *idt;
+
+static struct idt_reg idtr;
+struct gdt_reg gdtr = {
+ .size = 0x17,
+ .offset = GDT_ADDR
+};
+
+
+lapic_t lapic; //would make this static but it's needed by timer.c
+static struct ioapic_fixedlen ioapic;
+static uint64_t isr_bitmap[4]; //first 32 is for exceptions;
+
+
+void disable_pic() {
+ //remapping PIC
+ outb_wait(PICM_COMMAND, ICW1_INIT | ICW1_ICW4); //initilizing
+ outb_wait(PICS_COMMAND, ICW1_INIT | ICW1_ICW4);
+
+ outb_wait(PICM_DATA, 32); //IRQ offsets
+ outb_wait(PICS_DATA, 40);
+
+ outb_wait(PICM_DATA, 4); //notify master of slave
+ outb_wait(PICS_DATA, 2); //nofity slave of mediocore social ethical standards
+
+ outb_wait(PICM_DATA, ICW4_8086);
+ outb_wait(PICS_DATA, ICW4_8086);
+
+
+ //masking.
+ outb_wait(PICS_DATA, 0xff);
+ outb_wait(PICM_DATA, 0xff);
+}
+
+void write_ioapic(void *ioapic_addr, uint32_t reg, uint32_t value) {
+ uint32_t *ioapic_r = ioapic_addr;
+ ioapic_r[0] = reg & 0xff;
+ ioapic_r[4] = value;
+}
+
+uint32_t read_ioapic(void *ioapic_addr, uint32_t reg) {
+ uint32_t *ioapic_r = ioapic_addr;
+ ioapic_r[0] = reg & 0xff;
+ return ioapic_r[4];
+}
+
+void create_fixed_interrupt(unsigned int irq, struct apic_vt *redirect) {
+ irq = irq_to_gsi(irq); //make sure there's no redirection entries.
+
+ struct ioapic_t *ioapic_smi = (void *)0;
+ for(unsigned int i = 0; i < ioapic.count; i++) {
+ if((irq >= ioapic.ioapic[i].gsi_base) &&
+ (irq < (ioapic.ioapic[i].gsi_base + ioapic.ioapic[i].gsi_count))) {
+ ioapic_smi = ioapic.ioapic[i].address;
+ break;
+ }
+ }
+ if(!ioapic_smi) PANIC(KERNEL_PANIC_INVALID_IOAPIC_VEC);
+
+
+ write_ioapic(ioapic_smi, (0x10 + (irq * 2)), *(uint32_t *)redirect);
+ write_ioapic(ioapic_smi, ((0x10 + (irq * 2)) + 1), *(uint64_t *)redirect >> 32);
+}
+
+unsigned int alloc_idt(struct idt_entry *entry) {
+ unsigned int b, i;
+ for(b = 0; b < (sizeof(isr_bitmap) / 8); b++) {
+ for(i = 0; i < 64; i++) {
+ if(!((isr_bitmap[b] >> i) & 1)) {
+ isr_bitmap[b] |= (uint64_t)1 << i;
+ idt[(b * 64) + i] = (struct idt_descriptor) {
+ .offset_1 = (uint16_t)((uint64_t)entry->addr & 0xffff),
+ .offset_2 = (uint16_t)((uint64_t)entry->addr >> 16),
+ .offset_3 = (uint32_t)((uint64_t)entry->addr >> 32),
+ .segment = 0x8,
+ .ist = entry->ist,
+ .type = entry->type,
+ .priv = entry->priv,
+ .reserved = 0,
+ .reserved_1 = 0,
+ .reserved_2 = 0,
+ .present = 1
+ };
+ return i;
+ }
+ }
+ }
+ return 0;
+}
+
+void modify_idt(struct idt_entry *entry, unsigned int vector) {
+ idt[vector] = (struct idt_descriptor) {
+ .offset_1 = (uint16_t)((uint64_t)entry->addr & 0xffff),
+ .offset_2 = (uint16_t)((uint64_t)entry->addr >> 16),
+ .offset_3 = (uint32_t)((uint64_t)entry->addr >> 32),
+ .segment = 0x8,
+ .ist = entry->ist,
+ .type = entry->type,
+ .priv = entry->priv,
+ .reserved = 0,
+ .reserved_1 = 0,
+ .reserved_2 = 0,
+ .present = 1
+ };
+}
+
+void free_idt(unsigned int entry) {
+ isr_bitmap[entry / 64] ^= ((uint64_t)1 << (entry & 63));
+ idt[entry].present = 0;
+}
+
+inline void clear_int() {
+ lapic[44] = 0;
+}
+
+
+void init_exceptions() {
+ //for idt index explainations, see include/panic.h
+ //TODO maybe utalize add_idt_entry?
+ unsigned int e;
+ idt[0] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+ idt[8] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ idt[16] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+ idt[17] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ idt[30] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ for(e = 5; e < 8; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+ for(e = 10; e < 15; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception_errcode);
+ for(e = 18; e < 21; e++) idt[e] = KERNEL_IDT_DESC_GATE(fatal_hwexception);
+}
+//void new_idt
+
+
+void init_interrupts() {
+ init_madt();
+ debug_madt();
+ lapic = get_lapic();
+
+ get_ioapic(&ioapic);
+ for(unsigned int i = 0; i < ioapic.count; i++) {
+ ioapic.ioapic[i].gsi_count = ((read_ioapic(ioapic.ioapic[i].address, IOAPICR_VER) >> 16) & 0xff);
+ printf("Found ioapic %i at addr %p, gsi %i to %i\n", i, ioapic.ioapic[i].address,
+ ioapic.ioapic[0].gsi_base, ioapic.ioapic[0].gsi_base + ioapic.ioapic[0].gsi_count);
+ }
+
+ disable_pic();
+
+ idt = palloc(0x1000);
+ idtr.size = 0x1000;
+ idtr.offset = (uint64_t)idt;
+
+ bzero(&isr_bitmap, sizeof(isr_bitmap));
+ isr_bitmap[0] = (((uint64_t)1 << 32) - 1);
+
+ //set idt and new gdt
+ asm("lgdt [%0]\n"
+ "lidt [%1]\n":: "m"(gdtr), "m"(idtr));
+
+
+ //Spurrious Interrupt (permanent, required for APIC)
+ idt[SPURRIOUS_VECTOR] = KERNEL_IDT_DESC_GATE(spurrious_int);
+
+ //Spurrious interrupt on IDT
+ lapic[60] = 0x1ff; //page 395
+
+ //initlize exceptions
+ init_exceptions();
+
+
+ //initilize the timers
+ init_timer();
+ asm("sti\n");
+}
diff --git a/src/kernel/io.c b/src/kernel/io.c
new file mode 100644
index 0000000..1974c35
--- /dev/null
+++ b/src/kernel/io.c
@@ -0,0 +1,24 @@
+#include <io.h>
+#include <stdint.h>
+//these functions are assumed not to be time-sensitive.
+void outb_wait(uint16_t port, uint8_t value) {
+ outb(port, value);
+ io_wait();
+}
+
+void read_msr(uint32_t addr, uint64_t *value) {
+ uint32_t low, high;
+ asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(addr));
+ *value = low | ((uint64_t)high << 32);
+}
+
+void write_msr(uint32_t addr, uint64_t value) {
+ uint32_t low = value & UINT32_MAX;
+ uint32_t high = value >> 32;
+ asm volatile("wrmsr"::"a"(low), "d"(high), "c"(addr));
+}
+
+void hlt() {
+ asm("cli\nhlt");
+}
+
diff --git a/src/kernel/isv.c b/src/kernel/isv.c
new file mode 100644
index 0000000..fbc60c0
--- /dev/null
+++ b/src/kernel/isv.c
@@ -0,0 +1,12 @@
+#include <printf.h>
+#include <stdint.h>
+#include <isv.h>
+#include <panic.h>
+
+
+__attribute__((interrupt)) void spurrious_int(void *unused) {
+ printf("Detected spurrious interrupt, doing nothing.\n");
+}
+
+
+
diff --git a/src/kernel/isv_asm.asm b/src/kernel/isv_asm.asm
new file mode 100644
index 0000000..b770aaa
--- /dev/null
+++ b/src/kernel/isv_asm.asm
@@ -0,0 +1,65 @@
+global timer_init_pit
+global kernel_block
+global fatal_hwexception
+global fatal_hwexception_errcode
+global lapic_timer_racefixer
+
+extern clear_int
+extern panic
+extern calibrate_lapic_waiting
+
+;I need to get my timing right and consistently boot smp,
+;_then_ I'll work on cleaning this up.
+
+timer_init_pit:
+cli
+mov ecx, DWORD [rbx + 0x390]
+mov DWORD [rbx + 0x380], 0
+in al, 0x61
+and al, 0xfe
+out 0x61, al
+mov DWORD [rbx + 0xb0], 0
+iretq
+
+
+kernel_block:
+call clear_int
+iretq
+
+
+fatal_hwexception:
+push qword rdi
+push qword rsi
+push qword rdx
+push qword rcx
+push qword rbx
+push qword rax
+mov rdi, 0
+mov rdx, rsp
+mov rsi, rdx
+add rsi, 48
+call panic
+
+; rdi: reason
+; rsi: frame
+; rdx: regs
+
+; 0xffff80000010af70
+fatal_hwexception_errcode:
+push qword rdi
+push qword rsi
+push qword rdx
+push qword rcx
+push qword rbx
+push qword rax
+mov rdi, 1
+mov rdx, rsp
+mov rsi, rdx
+add rsi, 48
+call panic
+
+lapic_timer_racefixer: ;in case the lapic makes it to zero, impliment me
+inc rbx
+call clear_int
+mov QWORD [rsp], calibrate_lapic_waiting
+iretq
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 50e0578..50b8359 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -1,31 +1,45 @@
#include <stdbool.h>
+#include <smp.h>
#include <serial.h>
#include <printf.h>
#include <paging.h>
#include <video.h>
#include <acpi.h>
#include <panic.h>
+#include <kernel.h>
+#include <stdbool.h>
+#include <int.h>
+#include <io.h>
+#include <cpuid.h>
+#include <heap.h>
+#include <random.h>
+#include <timer.h>
+#include <libc.h>
+
+//testing headers
+#include <testmalloc.h>
-void main() {
- if(!(init_serial(COM1))) {
- printf("\nKernal started on CPU 1!\n"); // will detect cpu later
- }
-
- rsdp_t *rsdp;
- rsdp = find_RSDP();
- if(!(rsdp)) {
- printf("Couldn't find the RSDP... not sure what to do now.\n");
- panic(KERNEL_PANIC_RSDP_UNFOUND, KERNEL_PANIC_INVOKED);
- }
- dump_video();
- debug_print_memory();
+void main() {
+#ifndef SCREEN_OUTPUT
+ if(init_serial(COM1)) printf("\nKernal started on CPU 1!\n");
+#endif
+ get_mem_capabilities();
+ init_pmap(map_complete_physical());
+ unmap_lowmem();
+
+
+ find_root_sdp();
+ debug_acpi();
+
+ init_interrupts();
- init_pmap();
- debug_pmap();
+
+ randinit();
- panic(KERNEL_PANIC_KERNEL_RETURNED, KERNEL_PANIC_INVOKED);
+ smp_boot();
+ PANIC(KERNEL_PANIC_KERNEL_RETURNED);
}
diff --git a/src/kernel/klog.c b/src/kernel/klog.c
new file mode 100644
index 0000000..52444b1
--- /dev/null
+++ b/src/kernel/klog.c
@@ -0,0 +1,100 @@
+#include <stdint.h>
+#include <serial.h>
+#include <io.h>
+#include <printf.h>
+#include <kernel.h>
+#include <stdbool.h>
+#include <libc.h>
+
+//README
+//this file has some temporary workarounds until I get further into development
+//this isn't going to be the serial driver I end up keeping
+
+#define VIDEO_BUFFER PHYS_TO_VIRT(0xb8000)
+#define MAX_LOOPBACK_ATTEMPTS 20
+
+//later we'll set it up for interrupting instead of polling
+bool init_serial(uint16_t port) {
+ outb_wait(port + 1, 0x00);
+ outb_wait(port + 2, 0x00);
+ outb_wait(port + 3, 0x80);
+ outb_wait(port + 0, 0x01); //here
+ outb_wait(port + 1, 0x00);
+ outb_wait(port + 3, 0x03);
+ outb_wait(port + 2, 0xc7);
+ outb_wait(port + 4, 0x0b);
+ outb_wait(port + 4, 0x1e);
+
+
+ //we shouldn't accept this as a loopback success.
+ //I'm making an exception because my dell desktop has a faulty serial port
+ //that requires some extra effort.
+
+ uint8_t loopback_byte;
+ for(int attempts = 0; attempts < MAX_LOOPBACK_ATTEMPTS; attempts++) {
+ outb_wait(port + 0, 0xae); // test char
+ loopback_byte = inb(port);
+ if(loopback_byte == 0xae) break;
+ }
+
+ if(loopback_byte != 0xae) {
+ //I'm sorry if these next few lines give you a stroke. They gave me one.
+
+ //My old Dell test desktop has disfunctional serial hardware that only works after a reboot.
+ //Seeing we don't have ACPI set up yet, we can't reboot without crashing.
+ //IM GOING TO REMOVE THIS ONCE I DEVELOP THE "REAL" SERIAL DRIVER!!!!
+ asm("mov rax, 0\n"
+ "div rax\n");
+ return false;
+ }
+
+ outb_wait(port + 4, 0x0f);
+ return true;
+}
+
+void _putchar_serial(uint16_t port, char msg) {
+ while(!(inb(port + 5) & 0x20)); //wait for transmit to be done
+ outb_wait(port, msg);
+}
+
+static unsigned int on_char = 0;
+static unsigned int on_line = 0;
+
+
+void clear_screen() {
+ char *screen_buffer = (void *)VIDEO_BUFFER;
+ for(unsigned int i = 0; i <= (80 * 25); i++) screen_buffer[i * 2] = ' ';
+ on_char = 0;
+ on_line = 0;
+}
+
+void next_line() {
+ if(on_line >= 25) {
+ on_line = 0;
+ clear_screen();
+ }
+ else {
+ on_line++;
+ }
+ on_char = 0;
+}
+
+void move_cursor(unsigned int x, unsigned int y) {
+ //yeah yeah yeah, it doens't test for overflows... I'm gonna delete this once i get serial working
+ //on my second desktop
+ on_char = x;
+ on_line = y;
+}
+
+//until we get serial working on hp
+void _putchar_screen(char msg) {
+ if(on_char >= 80) {
+ next_line();
+ } else if(msg == '\n') {
+ next_line();
+ return;
+ }
+ char *screen_buffer = (void *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2)));
+ *screen_buffer = msg;
+ on_char++;
+}
diff --git a/src/kernel/libc.c b/src/kernel/libc.c
index c786cd0..4278281 100644
--- a/src/kernel/libc.c
+++ b/src/kernel/libc.c
@@ -3,7 +3,7 @@
// TODO clean up variable names
int strncmp(const char *s1, const char *s2, unsigned int n) {
int i;
- for(i = 0; ((i <= n) && (s1[i] != '\0') && (s2[i] != '\0')); i++) {
+ for(i = 0; ((i < (n - 1)) && (s1[i] != '\0') && (s2[i] != '\0')); i++) {
if(s1[i] != s2[i]) {
return(s1[i] - s2[i]);
}
@@ -11,6 +11,13 @@ int strncmp(const char *s1, const char *s2, unsigned int n) {
return(s1[i] - s2[i]);
}
+//this one hasn't been tested
+size_t strlen(const char *s) {
+ size_t len = 0;
+ while(s[len + 1] != '\0') len++;
+ return(len);
+}
+
int strcmp(const char *s1, const char *s2) {
int i;
for(i = 0; ((s1[i] != '\0') && (s2[i] != '\0')); i++) {
@@ -25,7 +32,7 @@ int memcmp(const void *s1, const void *s2, size_t n) {
const unsigned char *p1 = s1;
const unsigned char *p2 = s2;
int i;
- for(i = 0; i < n; i++) {
+ for(i = 0; i < n - 1; i++) {
if(p1[i] != p2[i]) {
return(p1[i] - p2[i]);
}
@@ -41,7 +48,7 @@ void strcpy(char *dest, char *src) {
void *memcpy(void *dest, char *src, size_t n) {
char *p = dest;
- for(unsigned int i = 0; i <= n; i++) {
+ for(unsigned int i = 0; i < n; i++) {
p[i] = src[i];
}
return(dest);
@@ -56,12 +63,16 @@ void *bzero(void *dest, size_t size) {
}
//TODO move this function to a seperate math library
-unsigned int ceil(double n) {
+int ceil(double n) {
int low_n = (int)n;
if(n == (double)low_n) return(low_n);
return(low_n + 1);
}
+int round(double n) {
+ return(int)(n + 0.5);
+}
+
void *memset(void *s, char c, size_t n) {
char *p = s;
for(size_t i = 0; i < n; i++) {
diff --git a/src/kernel/madt.c b/src/kernel/madt.c
new file mode 100644
index 0000000..62e0535
--- /dev/null
+++ b/src/kernel/madt.c
@@ -0,0 +1,179 @@
+#include <stdint.h>
+#include <libc.h>
+#include <acpi.h>
+#include <int.h>
+#include <kernel.h>
+#include <stddef.h>
+#include <heap.h>
+#include <printf.h>
+#include <smp.h>
+#include <madt.h>
+#include <cpuid.h>
+
+//madt entry types. there's more, we don't need em yet
+#define LOCAL_APIC 0
+#define IO_APIC 1
+#define IO_INT_OVERRIDE 2
+#define IO_APIC_NMI_SOURCE 3
+#define IO_APIC_NMI 4
+#define MADT_LOCAL_APIC_ADDR_OVERRIDE 5
+
+struct madt_sdt {
+ sdt_head header;
+ uint32_t apic_base;
+ uint32_t flags;
+} __attribute__((packed));
+
+struct madt_entry {
+ uint8_t type;
+ uint8_t length;
+} __attribute__((packed));
+
+struct madt_local_apic {
+ uint8_t processor_id;
+ uint8_t apic_id;
+ uint32_t flags;
+} __attribute__((packed));
+
+struct madt_local_apic_override {
+ uint16_t reserved;
+ void *apic_base;
+} __attribute__((packed));
+
+struct madt_ioapic {
+ uint8_t apic_id;
+ uint8_t reserved;
+ uint32_t addr;
+ uint32_t gsi_base;
+} __attribute__((packed));
+
+struct madt_io_int_override {
+ uint8_t bus_src; //not sure what this is used for.
+ uint8_t irq;
+ uint32_t global_vector;
+ uint16_t flags;
+} __attribute__((packed));
+
+static struct madt_sdt *madt;
+
+
+void init_madt() {
+ madt = find_sdt(SDT_MADT);
+}
+
+void debug_madt() {
+ struct madt_entry *entry;
+ for(
+ entry = (void *)madt + sizeof(*madt);
+ (void *)entry < (void *)madt + madt->header.length;
+ entry = (void *)entry + entry->length) {
+ printf("MADT debug: ");
+ switch(entry->type) {
+ case LOCAL_APIC:
+ printf("local APIC\n");
+ break;
+ case IO_APIC:
+ printf("IOAPIC\n");
+ break;
+ case IO_INT_OVERRIDE:
+ printf("IOAPIC interupt override\n");
+ break;
+ case IO_APIC_NMI_SOURCE:
+ printf("IOAPIC NMI\n");
+ break;
+ case IO_APIC_NMI:
+ printf("Local APIC NMI\n");
+ break;
+ case MADT_LOCAL_APIC_ADDR_OVERRIDE:
+ printf("APIC addr override\n");
+ break;
+ default:
+ printf("other\n");
+ break;
+ }
+ }
+}
+
+unsigned int irq_to_gsi(unsigned int irq) {
+ struct madt_io_int_override *irq_override;
+ struct madt_entry *entry;
+
+ for(
+ entry = (void *)madt + sizeof(*madt);
+ (void *)entry < (void *)madt + madt->header.length;
+ entry = (void *)entry + entry->length) {
+
+ if(entry->type == IO_INT_OVERRIDE) {
+ irq_override = (void *)entry + 2;
+ if(irq_override->irq == irq) return irq_override->global_vector;
+ }
+ }
+ return (uint32_t)irq; //no entry found
+}
+
+void get_ioapic(struct ioapic_fixedlen *ret) {
+ struct madt_entry *entry;
+ struct madt_ioapic *mpio_entry;
+
+ ret->count = 0;
+
+ for(
+ entry = (void *)madt + sizeof(*madt);
+ (void *)entry < (void *)madt + madt->header.length;
+ entry = (void *)entry + entry->length) {
+ if(entry->type == IO_APIC) {
+ mpio_entry = (void *)entry + 2;
+ if(ret->count) {
+ ret->ioapic = realloc(ret->ioapic, ++ret->count * sizeof(struct ioapic_t));
+ }
+ else {
+ ret->ioapic = malloc(++ret->count * sizeof(struct ioapic_t));
+ }
+ ret->ioapic[ret->count - 1].address = PHYS_TO_VIRT((uintptr_t)mpio_entry->addr);
+ ret->ioapic[ret->count - 1].gsi_base = mpio_entry->gsi_base;
+ }
+ }
+}
+
+lapic_t get_lapic() {
+ struct madt_local_apic_override *ap_override;
+ struct madt_entry *entry;
+
+ for(
+ entry = (void *)madt + sizeof(*madt);
+ (void *)entry < (void *)madt + madt->header.length;
+ entry = (void *)entry + entry->length) {
+
+ if(entry->type == MADT_LOCAL_APIC_ADDR_OVERRIDE) {
+ ap_override = (void *)entry + 2;
+
+ return (lapic_t)PHYS_TO_VIRT(ap_override->apic_base);
+ }
+ }
+ return (lapic_t)PHYS_TO_VIRT((uint64_t)madt->apic_base);
+}
+
+void get_coreinfo(struct cores_info *cores) {
+ struct madt_local_apic *ap_info;
+ struct madt_entry *entry;
+ uint32_t unused_cpuid, ebx;
+
+ __get_cpuid(1, &unused_cpuid, &ebx, &unused_cpuid, &unused_cpuid);
+ cores->bsp = ebx << 24;
+
+ bzero(cores, sizeof(*cores));
+
+ for(
+ entry = (void *)madt + sizeof(*madt);
+ (void *)entry < (void *)madt + madt->header.length;
+ entry = (void *)entry + entry->length) {
+
+ if(entry->type == LOCAL_APIC) {
+ ap_info = (void *)entry + 2;
+ if(ap_info->flags & 1) {
+ cores->apic_id[cores->corecount] = ap_info->processor_id;
+ cores->corecount++;
+ }
+ }
+ }
+}
diff --git a/src/kernel/page.c b/src/kernel/page.c
index de4f557..9db8660 100644
--- a/src/kernel/page.c
+++ b/src/kernel/page.c
@@ -1,12 +1,106 @@
#include <printf.h>
-#include <paging.h>
#include <stdint.h>
#include <libc.h>
#include <limits.h>
+#include <panic.h>
+#include <math.h>
#include <kernel.h>
+#include <stdbool.h>
+#include <cpuid.h>
+
+//just using char because c is a lil bitch and won't let us use void
+extern char _kernel_shared_zone_begin;
+
+
+
+// PAGE MAPPING
+#define PAGEMAP_LOCATION 0x10000
+
+#define MAX_BUDDY_ORDER 8
+#define PALLOC_AUTO_BLEVEL MAX_BUDDY_ORDER
+
+typedef struct phys_map {
+ struct phys_map *next;
+ unsigned int max_buddy;
+ uint64_t bsize[MAX_BUDDY_ORDER];
+ uint64_t *buddy[MAX_BUDDY_ORDER];
+} pmap_t;
+
+static pmap_t *first_pmap;
+
+#define MEM_AVAILABLE 1
+#define MEM_RESERVED 2
+#define MEM_APCI_RECLAIMABLE 3
+#define MEM_APCI_NVS 4
+#define MEM_BAD 5
+
+// ZONES
+#define ZONE_MAP_PLOC 0x7000
+#define ZONE_MAP PHYS_TO_VIRT(ZONE_MAP_PLOC)
+
+
+
+//reorganized (moved) from header
+typedef struct __attribute__((packed)) {
+ unsigned int present : 1; // present, must be one when accessed.
+ unsigned int read_write : 1; // if set to one, read and write is set
+ unsigned int user : 1; // For seperating CPL 0-2 and 3+
+ unsigned int writethrough_cache : 1; // honestly maybe I should look into caching
+ unsigned int cachable : 1; // hardware chaching. 0 is enabled, whats the worst that could happen?
+ unsigned int accessed : 1; // we'll never use any of these!
+ unsigned int zg0 : 1; // needs to be (and will be) zero'd
+ unsigned int size : 1; // if set to 1, this entry points to physical memory
+ unsigned int zg1 : 1; // needs to be (and will be) zero'd
+ unsigned int software_marks : 3; // available for our own use, I doubt we'll use it in such a simple thing
+
+ uintptr_t base_ptr : 40;
+ unsigned int avail:11;
+ unsigned int no_exec:1;
+} page_table;
+
+
+struct memory_table {
+ void *base;
+ uint64_t length;
+ uint32_t type;
+ uint32_t ACPI;
+} __attribute__((packed));
+
+static bool NX_capable;
+static bool huge_page_capable;
+
+
+void get_mem_capabilities() {
+ uint32_t unused, edx;
+ __get_cpuid(0x80000001, &unused, &unused, &unused, &edx);
+ huge_page_capable = (edx >> 26) & 1;
+ NX_capable = (edx >> 20) & 1;
+}
+
+
+void unmap_lowmem() {
+ struct stack_frame *frame;
+
+ asm("addq rsp, %0\n"
+ "addq rbp, %0\n"
+ "mov %0, rbp"
+ :"=r"(frame)
+ :"r"(PA_OFFSET));
+
+ while(frame->next != 0) {
+ printf("%p\n", frame->function_base);
+ frame->next = PHYS_TO_VIRT((void *)frame->next);
+ frame = frame->next;
+ }
+
+ //[future]
+ //eventually, you should use the function that unmaps pages when you write it
+ page_table *entry = (page_table *)PAGEMAP_LOCATION;
+ entry[0].present = 0;
+}
void debug_print_memory() {
- struct memory_table *memtable = (struct memory_table *)&_meminfo_loc;
+ struct memory_table *memtable = (void *)ZONE_MAP;
printf(" __________________________________________________________________________\n");
printf("| type\tstart\t\t\tend\t\t\tsize\t\t |\n");
printf("|--------------------------------------------------------------------------|\n");
@@ -16,32 +110,39 @@ void debug_print_memory() {
printf("----------------------------------------------------------------------------\n");
}
+void ram_stresser() {
+ struct memory_table *memtable = (void *)ZONE_MAP - PA_OFFSET;
+ memtable[6].length = 0x10000;
+}
+
void debug_pmap() {
- struct phys_map* pmap;
+ pmap_t *pmap = first_pmap;
int pmap_i = 0, order;
- uint64_t buddy_size, blong_i, bbit_i, buddy_chunksize, omit_cnt;
- printf("Maximum buddy order: %u (up to %#x sized chunks)\n", MAX_BUDDY_ORDER, (0x1000 << MAX_BUDDY_ORDER - 1));
- for(pmap = (struct phys_map*)&_stage2_pagetable; pmap != 0; pmap = pmap->next) {
+ uint64_t blong_i, bbit_i, buddy_chunksize, omit_cnt;
+ printf("Maximum buddy order: %u (up to %#x sized chunks)\n", MAX_BUDDY_ORDER, ((0x1000 << MAX_BUDDY_ORDER) - 1));
+ for(; pmap != 0; pmap = pmap->next) {
printf("Table %u:\n"
- "\tPhysical Start:\t%#p\n"
- "\tTable location:\t%#p\n", pmap_i, pmap->zone_paddr, pmap);
+ "\tPhysical/pmap start:\t%#p\n"
+ "\tTable Size:\t%u\n", pmap_i, pmap,
+ (uint64_t)(pmap->buddy[MAX_BUDDY_ORDER - 1] + pmap->bsize[MAX_BUDDY_ORDER - 1]) - (uint64_t)pmap);
+
for(order = 0; order <= MAX_BUDDY_ORDER - 1; order++) {
buddy_chunksize = (0x1000 << order); //TODO just put it in the for loop
- buddy_size = (((order == MAX_BUDDY_ORDER - 1)
- ? (uint64_t *)pmap->next : pmap->buddy[order + 1]) - pmap->buddy[order]);
printf("\tbuddy[%u]:\n"
- "\t\tAddress:\t%#x\n"
+ "\t\tAddress:\t%#p\n"
"\t\tSize:\t\t%u\n"
- "\t\tBuddies:\t\t\n", order, pmap->buddy[order], buddy_size);
+ "\t\tBuddies:\t\t\n", order, pmap->buddy[order], pmap->bsize[order]);
omit_cnt = 0;
- for(blong_i = 0; blong_i < buddy_size; blong_i++) {
+ for(blong_i = 0; blong_i < pmap->bsize[order]; blong_i++) {
for(bbit_i = 0; bbit_i < 64; bbit_i++) {
- if(*(pmap->buddy[order] + blong_i) & ((uint64_t)1 << bbit_i)) {
- if((omit_cnt < 20) || (blong_i == buddy_size - 1)) {
- printf("address %#x\tbit %u: %p\t is free\n",
- pmap->buddy[order] + blong_i, bbit_i, (uint64_t)pmap->zone_paddr + (((blong_i * 64) + bbit_i) * buddy_chunksize));
+ if((pmap->buddy[order][blong_i]) & ((uint64_t)1 << bbit_i)) {
+ if((omit_cnt < 20) || (blong_i == pmap->bsize[order] - 1)) {
+ printf("address %#p\tbit %u: %p\t is free\n",
+ pmap->buddy[order] + blong_i,
+ bbit_i,
+ ((uint64_t)pmap - PA_OFFSET) + ((((blong_i * 64) + bbit_i) * buddy_chunksize)));
}
omit_cnt++;
if(omit_cnt == 20) {
@@ -55,237 +156,291 @@ void debug_pmap() {
}
}
-void init_pmap() {
- struct memory_table *zones = (struct memory_table *)&_meminfo_loc;
- struct phys_map *pmap = (struct phys_map*)&_stage2_pagetable;
+//TODO I know you don't want to, but you need to thoroughly check this.
+void pfree(void *addr, size_t size) {
+ int blevel = 0;
+ uint64_t *onbyte; //the byte out buddy resides on in the current level
+ uint64_t page_bitloc; // how many bits we are away from buddy[0]. Helps calculate bitshifts
+ int bbitlen; //length of free'd area in current level
+ int lshift; //lshift is how many bits we shift over, rightbit is what it sounds like dumbass
+ pmap_t *pmap = first_pmap;
+
+ /* note: there's no security check to see if the page is actually allocated,
+ * or if we are freeing the table itself.
+ * This should be okay, as only the kernel will be calling it.
+ * If it gets too messy we can always come back.
+ */
- unsigned int zone_i, pmap_i = 0;
- int budorder;
- //we keep this info out of the struct because we won't need it after setting up
- uint64_t zone_len[MAX_ZONE_CNT], buddy_bitlen[MAX_ZONE_CNT][MAX_BUDDY_ORDER], *buddy_end;
- uint64_t pmap_size, pmap_bbitsize, pmap_blongsize, buddy_size, buddy_bit, pmap_bit;
- uint64_t threshold_bitsize, threshold_longsize = 0;
+ if(((uintptr_t)addr & 4095) || (size & 4095)) {
+ PANIC(KERNEL_PANIC_INVALID_PFREE);
+ return; //TODO [minor] some more specificity, not a huge deal
+ }
+ size /= 0x1000;
+ for(; pmap != 0; pmap = pmap->next) {
+ page_bitloc = (addr - (void *)pmap) / 0x1000;
+ onbyte = pmap->buddy[0] + (page_bitloc / 64);
+ if((addr >= (void *)pmap) && onbyte < pmap->buddy[1]) break;
+ }
-
- void *paged_mem = (void *)&_stage2_pagetable + 0x200000;
- map_page(&_stage2_pagetable, &_stage2_pagetable, PAGE_SIZE_2M);
+ while(blevel < MAX_BUDDY_ORDER) {
+ lshift = (page_bitloc / (1 << blevel)) & 63;
+ onbyte = pmap->buddy[blevel] + ((page_bitloc / 64) / (1 << blevel));
+ bbitlen = size / (1 << blevel);
- for(zone_i = 0; zones[zone_i].length > 0; zone_i++) {
- if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1)) {
+ //TODO clean up this part ------------------------------------------------------------- (below)
+ if(bbitlen <= 1) {
+ if(lshift & 1) {
+ if((*onbyte >> (lshift - 1)) & 1) {
+ *onbyte &= ~(((uint64_t)1 << (lshift - 1)) | ((uint64_t)1 << lshift));
+ size += (1 << blevel);
+ page_bitloc -= (1 << blevel);
+ bbitlen = size / (1 << blevel);
+ }
+ }
+ else if((*onbyte >> (lshift + 1)) & 1) {
+ *onbyte &= ~(((uint64_t)1 << (lshift + 1)) | ((uint64_t)1 << lshift));
+ size += (1 << blevel);
+ bbitlen = size / (1 << blevel);
+ }
+ }
+ else if(((lshift + bbitlen) & 1) && ((*onbyte >> (lshift + bbitlen)) & 1)) {
+ *onbyte ^= ((uint64_t)1 << (lshift + bbitlen));
+ size += (1 << blevel);
+ bbitlen = size / (1 << blevel);
+ }
+ //TODO clean up this part ------------------------------------------------------------- (above)
- //hopefully this should never happen...
- //I should dig into the docs to check before removing this.
- //We also could forget about MAX_ZONE_CNT if we did.
-
- if(zone_i >= MAX_ZONE_CNT) {
- printf("Only %u zones can be used! Modify MAX_ZONE_CNT in paging.h to use all memory.\n", MAX_ZONE_CNT);
+ if((!((size - 1) & size)) && (bbitlen != 1)) {
+ blevel = 63 - __builtin_clzl(size);
+ }
+ else {
+ if(bbitlen <= 1) {
+ *onbyte |= ((uint64_t)1 << lshift);
break;
+ } else if(bbitlen & 1) { //check me
+ size -= (1 << blevel);
+ *onbyte |= ((uint64_t)1 << (bbitlen + lshift));
}
+ blevel++;
+ }
+ }
+}
- if((zones[zone_i].base <= (void*)&_stage2_pagetable) &&
- (zones[zone_i].base + zones[zone_i].length >= (void *)&_stage2_pagetable)) {
- pmap->zone_paddr = &_stage2_pagetable;
- zone_len[pmap_i] = zones[zone_i].length - (pmap->zone_paddr - zones[zone_i].base);
- }
- else {
- pmap->zone_paddr = zones[zone_i].base;
- zone_len[pmap_i] = zones[zone_i].length;
- }
+void *palloc(size_t size) {
+ bool self_alloc;
+ int min_blevel, blevel;
+ uint64_t bbit, unshifted_entry, threshold, bloc; //TODO move when you've confirmed casting stuff
+ uint64_t buddy_i, *ret, *bentry;
+ int itercount;
+ pmap_t *pmap = first_pmap;
- pmap->buddy[0] = (void *)pmap + sizeof(*pmap);
- for(budorder = 1; budorder < MAX_BUDDY_ORDER; budorder++) {
- buddy_bitlen[pmap_i][budorder - 1] = GET_BUDDY_BITLEN(zone_len[pmap_i], budorder - 1);
- pmap->buddy[budorder] = (uint64_t *)pmap->buddy[budorder - 1] +
- LSIZE_FROM_BITLEN(buddy_bitlen[pmap_i][budorder - 1]);
- }
+ if(size == 0) return 0;
+ if(size & 4095) {
+ size = DIV_ROUND_UP(size, 0x1000);
+ }
+ else {
+ size = size / 0x1000;
+ }
+
+ //checking if pmap has been initilized; if not we've been called to self allocate
+ //the first buddy should never be allocated; that's where our pmap lives
+ if(pmap->buddy[pmap->max_buddy][0] & 1) {
+ self_alloc = true;
+ min_blevel = pmap->max_buddy;
+ }
+ else {
+ //log(size, 2)
+ self_alloc = false;
+ min_blevel = 63 - __builtin_clzl(size);
+ if(size & (size - 1)) min_blevel++;
+ if(min_blevel > MAX_BUDDY_ORDER - 1) return 0;
+ }
- buddy_bitlen[pmap_i][MAX_BUDDY_ORDER - 1] = GET_BUDDY_BITLEN(zone_len[pmap_i], MAX_BUDDY_ORDER - 1);
- pmap->next = (void *)pmap->buddy[MAX_BUDDY_ORDER - 1] +
- (LSIZE_FROM_BITLEN(buddy_bitlen[pmap_i][MAX_BUDDY_ORDER - 1]) * 8);
+ for(blevel = min_blevel; blevel < MAX_BUDDY_ORDER; blevel++) {
+ for(pmap = first_pmap; pmap != 0; pmap = pmap->next) {
- pmap = pmap->next;
- pmap_i++;
+ for(buddy_i = 0; buddy_i < pmap->bsize[blevel]; buddy_i++) {
+ if(pmap->buddy[blevel][buddy_i] > (uint64_t)0) {
+ bentry = &pmap->buddy[blevel][buddy_i];
+ bbit = __builtin_ctzl(*bentry);
+ bloc = bbit;
- //allocates by an extra sizeof(struct phys_map),
- //but were about to discard anyway
- while((void *)pmap + sizeof(*pmap) >= paged_mem) {
- map_page(paged_mem, paged_mem, PAGE_SIZE_2M);
- paged_mem += 0x200000;
- }
+ *bentry ^= (uint64_t)1 << bbit;
+
+ ret = (((buddy_i * 64) + bbit) * (0x1000 << blevel)) + (void *)pmap;
+
+ threshold = 0b11;
+
+ itercount = 1;
+ for(blevel--; blevel >= 0; blevel--) {
+ bentry = pmap->buddy[blevel] + ((bentry - pmap->buddy[blevel + 1]) * 2);
+ itercount++;
+ if(bloc >= 32) bentry += 1;
+ bloc = (bloc * 2) & 63; // will be the amount we need to shift
+ bbit = ceil((float)size / (1 << blevel));
+
+ unshifted_entry = ((uint64_t)1 << bbit) & threshold;
+ if(unshifted_entry) {
+ threshold = ((uint64_t)1 << (bbit * 2)) - 1;
+ }
+ else {
+ threshold = (threshold << 2) | threshold;
+ }
+ *bentry |= (unshifted_entry << bloc);
+ }
+ if(!self_alloc) bzero(ret, size * 0x1000);
+ return ret;
+ }
+ }
}
}
- pmap_size = (void*)(pmap) - (void*)&_stage2_pagetable;
- if(pmap_size >= zone_len[0]) panic(); //TODO debugging
+ return 0;
+}
- pmap_i = 0;
- for(pmap = (struct phys_map*)&_stage2_pagetable; pmap->next != 0; pmap = pmap->next) {
- for(budorder = MAX_BUDDY_ORDER - 1; budorder >= 0; budorder--) {
- pmap_bbitsize = ceil((float)pmap_size / ((uint64_t)0x1000 << budorder));
- pmap_blongsize = pmap_bbitsize / 64;
- if(budorder == MAX_BUDDY_ORDER - 1) {
- buddy_size = (uint64_t *)pmap->next - pmap->buddy[budorder];
- buddy_end = (uint64_t *)pmap->next - 1;
+//returns size of pages needed
+size_t map_complete_physical() {
+ uint64_t total_mem;
+ unsigned int pdpe_cnt, pde_cnt, pde_max_i;
+ int zone_i, entry_i;
+ struct memory_table *zones = (void *)ZONE_MAP_PLOC;
+
- threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2;
- }
- else {
- buddy_size = pmap->buddy[budorder + 1] - pmap->buddy[budorder];
- buddy_end = pmap->buddy[budorder + 1] - 1;
+ page_table *pml4 = (page_table *)PAGEMAP_LOCATION;
+ page_table *pdpe = (page_table *)&_kernel_shared_zone_begin;
+ page_table *pde;
- threshold_longsize = threshold_bitsize / 64;
- }
- pmap_bit = pmap_bbitsize & 63;
- buddy_bit = buddy_bitlen[pmap_i][budorder] & 63;
+ for(zone_i = 0; zones[zone_i].length > 0; zone_i++);
+ total_mem = (uint64_t)zones[zone_i - 1].base + zones[zone_i - 1].length;
+
+ pdpe_cnt = (total_mem + (0x40000000 - 1)) / 0x40000000;
+
+ entry_i = (PA_OFFSET >> 39) & 0x1ff;
+ pml4[entry_i].base_ptr = (uintptr_t)&_kernel_shared_zone_begin >> 12;
+ pml4[entry_i].read_write = 1;
+ pml4[entry_i].user = 0;
+ pml4[entry_i].size = 0;
+ pml4[entry_i].no_exec = 1;
+ pml4[entry_i].present = 1;
- if((pmap_bbitsize >= BITLEN_FROM_LSIZE(buddy_size)) && (pmap == (void *)&_stage2_pagetable)) {
- bzero(pmap->buddy[budorder], buddy_size * 8);
+ if(huge_page_capable) {
+ for(int pdpe_i = 0; pdpe_i < pdpe_cnt; pdpe_i++) {
+ pdpe[pdpe_i].base_ptr = pdpe_i << 18;
+ pdpe[pdpe_i].read_write = 1;
+ pdpe[pdpe_i].user = 0;
+ pdpe[pdpe_i].size = 1;
+ pdpe[pdpe_i].no_exec = NX_capable;
+ pdpe[pdpe_i].present = 1;
+ }
+ return pdpe_cnt * 0x1000;
+ }
+ else {
+ pde_cnt = (total_mem + 0x100000) / 0x200000;
+ for(int pdpe_i = 0; pdpe_i < pdpe_cnt; pdpe_i++) {
+ pde = (page_table *)(&_kernel_shared_zone_begin + (pdpe_cnt * 0x1000) + (pdpe_i * 0x1000));
+
+ if((pdpe_i < pdpe_cnt - 1) || (!(pde_cnt & 511))) {
+ pde_max_i = 512;
}
else {
- if(budorder == MAX_BUDDY_ORDER - 1) {
- if(pmap == (void*)&_stage2_pagetable) {
- if(pmap_blongsize) bzero(pmap->buddy[budorder], (pmap_blongsize - 1) * 8);
- if(pmap_bit) {
- *(pmap->buddy[budorder] + pmap_blongsize) = ~(((uint64_t)1 << pmap_bit) - 1);
- }
- else {
- *(pmap->buddy[budorder] + pmap_blongsize) = UINT64_MAX;
- }
- if(pmap_blongsize + 1 == buddy_size) {
- *buddy_end &= ((uint64_t)1 << buddy_bit) - 1;
- }
- else {
- memset(pmap->buddy[budorder] + pmap_blongsize + 1, UINT8_MAX, (buddy_size - 1) * 8);
- if(buddy_bit) {
- *buddy_end = ((uint64_t)1 << buddy_bit) - 1;
- }
- else {
- *buddy_end = UINT64_MAX;
- }
- }
- threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2;
- }
- else {
- memset(pmap->buddy[budorder], UINT8_MAX, (buddy_size - 1) * 8);
- if(buddy_bit) {
- *buddy_end = ((uint64_t)1 << buddy_bit) - 1;
- }
- else {
- *buddy_end = UINT64_MAX;
- }
- }
- }
- else if(pmap == (void *)&_stage2_pagetable) {
- if(threshold_longsize) bzero(pmap->buddy[budorder], (threshold_longsize - 1) * 8);
+ pde_max_i = pde_cnt & 511;
+ }
+
+ pdpe[pdpe_i].base_ptr = (uintptr_t)pde >> 12;
+ pdpe[pdpe_i].read_write = 1;
+ pdpe[pdpe_i].user = 0;
+ pdpe[pdpe_i].size = 0;
+ pdpe[pdpe_i].no_exec = NX_capable;
+ pdpe[pdpe_i].present = 1;
- if(threshold_bitsize > pmap_bbitsize)
- *(pmap->buddy[budorder] + threshold_longsize) = ((uint64_t)1 << ((threshold_bitsize - 1) & 63));
-
- if(buddy_size - threshold_longsize)
- bzero(pmap->buddy[budorder] + threshold_longsize + 1, buddy_size - threshold_longsize);
- if(buddy_bit & 1) {
- *buddy_end = ((uint64_t)1 << (buddy_bit - 1));
- }
- threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2;
- }
- else {
- bzero(pmap->buddy[budorder], buddy_size);
- if(buddy_bit & 1) {
- *buddy_end = ((uint64_t)1 << ((buddy_bit) - 1));
- }
- }
+ for(int pde_i = 0; pde_i < pde_max_i; pde_i++) {
+ pde[pde_i].base_ptr = ((pdpe_i << 9) + pde_i) << 9;
+ pde[pde_i].read_write = 1;
+ pde[pde_i].user = 0;
+ pde[pde_i].size = 1;
+ pde[pde_i].no_exec = NX_capable;
+ pde[pde_i].present = 1;
}
}
- pmap_i++;
+ return (pdpe_cnt * 2) * 0x1000;
}
}
+pmap_t *init_pmap(size_t pagetable_size) {
+ pmap_t *pmap, *last_pmap;
+ struct memory_table *zones = (void *)ZONE_MAP;
+ int budorder, zone_i;
+ uint64_t pmap_size, pmap_bbitsize, zone_size;
+ bool first_pmap_i = true;
-/**
- * BIG TODO:
- * Paging turned out to be simpler then I thought. I've temporarily fixed the code, but needs to be rewritten/simplified.
- * Let's get rid of those nasty GOTOs if we can.
- * Also, once we get physical memory allocator up and running, impliment that in this function.
-**/
+
-bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) {
- //printf("map page called\n");
- uintptr_t va_ptr = (uintptr_t)virtual_addr;
- uintptr_t pa_ptr = (uintptr_t)physical_addr;
- if((va_ptr % (1 << size)) || (pa_ptr % (1 << size))) {
- return 0;
- }
- page_table *table = (page_table *)PAGEMAP_LOCATION;
- int pte_i = (va_ptr >> 12) & 0x1ff;
- int pde_i = (va_ptr >> 21) & 0x1ff;
- int pdpe_i = (va_ptr >> 30) & 0x1ff;
- int pml4e_i = (va_ptr >> 39) & 0x1ff;
-
- if(table->pml4e[pml4e_i].present) {
- if(table->pml4e[pml4e_i].base_ptr != (uintptr_t)&table->pdpe[pdpe_i] >> 12) goto error;
- if(table->pdpe[pdpe_i].present) {
- if(size == PAGE_SIZE_1G) {
- if(table->pdpe[pdpe_i].base_ptr == ((uintptr_t)pa_ptr >> 30 & 0x1ff))
- return true;
- goto error;
+ for(zone_i = 0; zones[zone_i].length > 0; zone_i++) {
+ if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1) &&
+ zones[zone_i].length >= (0x2000)) {
+ printf("found allocatable map at %p\n", zones[zone_i].base);
+ last_pmap = pmap;
+ if(zones[zone_i].base == (void *)0x100000) {
+ zone_size = zones[zone_i].length - (((uint64_t)&_kernel_shared_zone_begin - 0x100000) + pagetable_size);
+ pmap = PHYS_TO_VIRT((void *)&_kernel_shared_zone_begin + pagetable_size);
+ }
+ else {
+ zone_size = zones[zone_i].length;
+ pmap = PHYS_TO_VIRT(zones[zone_i].base);
}
- if(table->pdpe[pdpe_i].base_ptr != (uintptr_t)&table->pde[pde_i] >> 12) goto error;
- if(table->pde[pde_i].present) {
- if(size == PAGE_SIZE_2M) {
- if(table->pde[pde_i].base_ptr == ((uintptr_t)pa_ptr >> 21 & 0x1ff))
- return true;
- goto error;
+ if(first_pmap_i) {
+ pmap->next = NULL;
+ first_pmap_i = false;
+ }
+ else {
+ pmap->next = last_pmap;
+ }
+
+ for(budorder = 0; budorder < MAX_BUDDY_ORDER; budorder++) {
+ pmap_bbitsize = zone_size / (0x1000 << budorder);
+ pmap->bsize[budorder] = DIV_ROUND_UP(pmap_bbitsize , 64);
+ if(budorder) {
+ pmap->buddy[budorder] = pmap->buddy[budorder - 1] + pmap->bsize[budorder - 1];
+ }
+ else {
+ pmap->buddy[0] = (void *)pmap + sizeof(*pmap);
+ }
+ if(budorder < MAX_BUDDY_ORDER - 1) {
+ bzero(pmap->buddy[budorder], pmap->bsize[budorder] * 8);
+ if(pmap_bbitsize & 1) {
+ pmap->buddy[budorder][pmap->bsize[budorder] - 1] =
+ ((uint64_t)1 << ((pmap_bbitsize - 1) & 63));
+ }
+ if(pmap_bbitsize == 1) {
+ pmap->max_buddy = budorder;
+ for(budorder++; budorder < MAX_BUDDY_ORDER; budorder++) {
+ pmap->buddy[budorder] = 0;
+ pmap->bsize[budorder] = 0;
+ }
+ break;
+ }
}
- if(table->pde[pde_i].base_ptr != (uintptr_t)&table->pte[pte_i] >> 12) goto error;
- if(table->pte[pte_i].present) {
- if(table->pte[pte_i].base_ptr != ((pa_ptr >> 12) & 0x1ff)) goto error;
- return true;
+ else {
+ pmap->max_buddy = MAX_BUDDY_ORDER - 1;
+ memset(pmap->buddy[budorder], UINT8_MAX, pmap->bsize[budorder] * 8);
+ if((pmap_bbitsize / 64) != (pmap->bsize[budorder])) {
+ pmap->buddy[budorder][pmap->bsize[budorder] - 1] =
+ (((uint64_t)1 << (pmap_bbitsize & 63)) - 1);
+ }
}
- else goto mod_page_pte;
}
- else goto mod_page_pde;
- }
- else goto mod_page_pdpe;
- }
- else {
- table->pml4e[pml4e_i].base_ptr = (uintptr_t)&table->pdpe[pdpe_i] >> 12;
- table->pdpe[pml4e_i].read_write = 1;
- table->pml4e[pml4e_i].present = 1;
-mod_page_pdpe:
- table->pdpe[pdpe_i].read_write = 1;
- //TODO you just found out things are a lot more simple then you thought!
- if(size == PAGE_SIZE_1G) {
- table->pdpe[pdpe_i].size = 1;
- table->pdpe[pdpe_i].base_ptr = pa_ptr >> 12;
- table->pdpe[pdpe_i].present = 1;
- return true;
- }
- table->pdpe[pdpe_i].base_ptr = (uintptr_t)&table->pde[pde_i] >> 12;
- table->pdpe[pdpe_i].present = 1;
-mod_page_pde:
- table->pde[pde_i].read_write = 1;
- if(size == PAGE_SIZE_2M) {
- table->pde[pde_i].size = 1;
- table->pde[pde_i].base_ptr = pa_ptr >> 12;
- table->pde[pde_i].present = 1;
- return true;
+
+ pmap_size = (uint64_t)(pmap->buddy[pmap->max_buddy] + pmap->bsize[pmap->max_buddy]) - (uint64_t)pmap;
+ first_pmap = pmap; //we spoof palloc into allocating from the specific required pmap.
+ palloc(pmap_size);
}
- table->pde[pde_i].base_ptr = (uintptr_t)&table->pte[pte_i] >> 12;
- table->pde[pde_i].present = 1;
-mod_page_pte:
- table->pte[pte_i].base_ptr = pa_ptr >> 12;
- table->pte[pte_i].read_write = 1;
- table->pte[pte_i].present = 1;
- return true;
}
-error:
- printf("Page allocation error!\n");
- return false;
+ return pmap;
}
diff --git a/src/kernel/panic.c b/src/kernel/panic.c
index 851684a..82a761f 100644
--- a/src/kernel/panic.c
+++ b/src/kernel/panic.c
@@ -1,13 +1,15 @@
#include <panic.h>
#include <stdint.h>
#include <printf.h>
+#include <kernel.h>
+#include <serial.h>
+#include <isv.h>
-void panic(int reason, int type) { // will fill with debugging info latter
+void panic(int reason, void *eframe_p, struct registers *regs) { // will fill with debugging info latter
+
- struct stack_frame *frame;
-
#ifdef EASTEREGG_BLOATWARE
- printf("Kernel PANIC!!!!!!!\n");
+ printf("\nKernel PANIC!!!!!!!\n");
printf(
" _.-^^---....,,-- \n"
" _-- --_ \n"
@@ -24,31 +26,65 @@ void panic(int reason, int type) { // will fill with debugging info latter
printf("Kernel Panic!\n");
#endif
- printf("Reason:\n");
-
switch(reason) {
- case KERNEL_PANIC_PMAPSIZE :
- printf("\tThe physical map can't fit in the first memory zone.\n"
- "\tNote: If you have this issue, please contact me.\n"
- "\tIt's a fixable bug caused by an unlikely scenario.\n");
- break;
- case KERNEL_PANIC_RSDP_UNFOUND:
- printf("\tRSDP unfound!\n");
- break;
- case KERNEL_PANIC_KERNEL_RETURNED:
- printf("\tThe kernel (almost) reached its return!\n");
- break;
+ case KERNEL_PANIC_HW_EXCEPTION:
+ case KERNEL_PANIC_HW_EXCEPTION_ERR:
+ printf("\nHardware exception in kernel space!\n");
+ break;
+
+ case KERNEL_PANIC_RSDP_UNFOUND:
+ printf("\nRSDP unfound!\n");
+ break;
+ case KERNEL_PANIC_KERNEL_RETURNED:
+ printf("\nThe kernel (almost) reached its return!\n");
+ break;
+ case KERNEL_PANIC_INVALID_PFREE:
+ printf("\npfree was called with invalid paramaters.\n");
+ break;
+ case KERNEL_PANIC_INVALID_RSDT:
+ printf("\nInvalid RSDT or XSDT after RSDP verification.\nIf this happens, go buy some lottery tickets.\n");
+ break;
+ case KERNEL_PANIC_INVALID_IOAPIC_VEC:
+ printf("\nThe kernel tried to make a vector that was too high for the IOAPIC to handle.\n");
+ break;
+ case KERNEL_PANIC_HPET_REQUIRED:
+ printf("\nHPET is required. \nIf you get this error, let know;\nif enough people share this issue, I'll impliment PIT usage.\n");
+ default:
+ printf("\nUnknown panic code %i\n.", reason);
+ break;
}
- printf("\nStack trace:\n");
+ struct stack_frame *frame;
- asm("mov %%rbp,%0" : "=r"(frame) ::);
+ char reg_str[156];
+ if((reason == KERNEL_PANIC_HW_EXCEPTION) || (reason == KERNEL_PANIC_HW_EXCEPTION_ERR)) {
+ sprintf(reg_str, "rax:\t0x%lx\n"
+ "rbx:\t0x%lx\n"
+ "rcx:\t0x%lx\n"
+ "rdx:\t0x%lx\n"
+ "rsi:\t0x%lx\n"
+ "rdi:\t0x%lx\n", regs->rax, regs->rbx, regs->rcx, regs->rdx, regs->rsi, regs->rdi);
+ }
+ if(reason == KERNEL_PANIC_HW_EXCEPTION) {
+ struct int_frame *ex_frame = eframe_p;
+ printf("Offending instruction:\t0x%p\n", ex_frame->rip);
+ printf(reg_str);
+ }
+ else if (reason == KERNEL_PANIC_HW_EXCEPTION_ERR) {
+ struct exception_frame *ex_frame = eframe_p;
+ printf("Offending instruction: 0x%p\nError value: %x\n", ex_frame->frame.rip, ex_frame->err);
+ printf(reg_str);
+ }
+ asm("mov %0, rbp" : "=r"(frame) ::);
+ printf("\nCall trace:\n");
+
for(; frame->next != 0; frame = frame->next) {
- printf("\t%x\n", frame->function_base);
+ printf("\t0x%p\n", frame->function_base);
}
+
- //It's not public yet, but it will be
+ //It's not public yet, but if I ever get somewhere it will be
printf("\nAfter ensuring your computer meets the requirements specified, if you think this is a bug, please open an issue on the git repo or email me at %s.\n", DEV_EMAIL);
- for(;;);
+ asm("cli\nhlt");
}
diff --git a/src/kernel/printf.c b/src/kernel/printf.c
index 14c897d..8267755 100644
--- a/src/kernel/printf.c
+++ b/src/kernel/printf.c
@@ -39,10 +39,12 @@
#include <serial.h>
//and my options
+/**
#define PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_DISABLE_SUPPORT_PTRDIFF_T
+**/
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
@@ -159,7 +161,11 @@ static inline void _out_char(char character, void* buffer, size_t idx, size_t ma
{
(void)buffer; (void)idx; (void)maxlen;
if (character) {
+#ifdef SCREEN_OUTPUT
+ _putchar_screen(character);
+#else
_putchar_serial(COM1, character); // later we should figure out a way to not specifify exclusively com1
+#endif
}
}
diff --git a/src/kernel/random.c b/src/kernel/random.c
new file mode 100644
index 0000000..404223a
--- /dev/null
+++ b/src/kernel/random.c
@@ -0,0 +1,36 @@
+#include <stdbool.h>
+#include <cpuid.h>
+#include <printf.h>
+#include <stdint.h>
+
+static bool hw_random = false;
+static unsigned long int seed = -1;
+
+void randinit() {
+ unsigned int unused, eax, ecx;
+ eax = 0;
+ ecx = 0;
+ __get_cpuid(1, &eax, &unused, &ecx, &unused);
+ hw_random = (ecx >> 30) & 1;
+ printf("Kernel random source: %s.\n", (hw_random) ? "rdrand" : "pseudo");
+}
+
+//As of now, this function isn't nessesarily meant to be fast.
+unsigned int randint() {
+ uint64_t random_long = 0;
+ if(hw_random) {
+ asm("rand:\n"
+ "rdrand %0\n"
+ "jc finished\n"
+ "pause\n"
+ "jmp rand\n"
+ "finished:" :"=r"(random_long)::"rax" );
+ }
+ else {
+ //TODO FUCKING ENTROPY!!!!!!!111
+ seed = 1103515245 * seed + 12345;
+ return(unsigned int)(seed / 65536) % 32768;
+ }
+ return 0;
+}
+
diff --git a/src/kernel/smp.c b/src/kernel/smp.c
new file mode 100644
index 0000000..d3c74fe
--- /dev/null
+++ b/src/kernel/smp.c
@@ -0,0 +1,80 @@
+#include <kernel.h>
+#include <madt.h>
+#include <timer.h>
+#include <cpuid.h>
+#include <int.h>
+#include <libc.h>
+
+#define LAPIC_ICR_LOW 192
+#define LAPIC_ICR_HIGH 196
+
+extern lapic_t lapic;
+extern char __load_start_smp_bootloader, __load_stop_smp_bootloader;
+extern uint8_t *smp_bootstrap_corecount;
+
+struct icr_reg {
+ uint8_t vector;
+ unsigned int deliv_mode:3;
+ unsigned int dest_mode:1;
+ unsigned int deliv_status:1;
+ unsigned int reserved:1;
+ unsigned int level:1; //0 = de-assert
+ unsigned int trig_mode:1;
+ unsigned int reserved_1:2;
+ unsigned int dest_shorthand:2;
+ unsigned int reserved_2:12;
+}__attribute__((packed));
+
+//1: get bsp number 2
+//2: get list of lapics 3
+//3: copy code 1
+//4:
+
+
+static inline void write_icr(uint8_t dest, uint32_t message) {
+ lapic[LAPIC_ICR_HIGH] = (uint32_t)dest << 24;
+ lapic[LAPIC_ICR_LOW] = message;
+}
+
+void smp_boot() {
+ uint8_t cores_active = 0; //TODO change in asm
+ struct cores_info cores;
+ unsigned int ci;
+
+ struct icr_reg icr;
+ bzero(&icr, sizeof(icr));
+
+ memcpy(PHYS_TO_VIRT((void *)0x8000), PHYS_TO_VIRT(&__load_start_smp_bootloader),
+ &__load_stop_smp_bootloader - &__load_start_smp_bootloader);
+ *(uint8_t **)PHYS_TO_VIRT(&smp_bootstrap_corecount) = &cores_active;
+
+
+ get_coreinfo(&cores);
+
+ icr.deliv_mode = 0b101;
+ icr.dest_shorthand = 0b11;
+ icr.level = 1;
+ write_icr(0, *(uint32_t *)&icr);
+ usleep(10000);
+
+ icr.deliv_mode = 0b110;
+ icr.vector = 8;
+ write_icr(0, *(uint32_t *)&icr);
+ usleep(200);
+ write_icr(0, *(uint32_t *)&icr);
+
+ /**
+ if(cores_active != cores.corecount) {
+ write_icr(0, *(uint32_t *)&icr);
+ usleep(200);
+ }
+ **/
+ /**
+ for(ci = 0; ci < cores.corecount; ci++) {
+ if(ci == cores.bsp) continue;
+ //send init sipi
+ write_icr(ci, *(uint32_t *)&icr);
+ }
+ **/
+
+}
diff --git a/src/kernel/smp_trampoline.asm b/src/kernel/smp_trampoline.asm
new file mode 100644
index 0000000..f723aa6
--- /dev/null
+++ b/src/kernel/smp_trampoline.asm
@@ -0,0 +1,140 @@
+global smp_bootstrap_corecount;
+
+[bits 16]
+smp_trampoline:
+cli
+hlt
+hlt
+
+xor ax, ax
+mov ds, ax
+lgdt [.gdt_descriptor_p]
+mov eax, cr0
+or eax, 0x1
+mov cr0, eax ; now in long mode
+
+jmp 0x8:.smp_protected
+
+
+;________________________________________________________________________________________
+
+;TODO find how to use old gdt
+.gdt_start_p: ; we need to start with a null gdt
+dd 0
+dd 0
+
+.gdt_code_p:
+dw 0xffff
+dw 0x0000
+db 0x00
+db 10011010b
+db 11001111b
+db 0x0000
+
+.gdt_data_p:
+dw 0xffff
+dw 0x0000
+db 0x00
+db 10010010b
+db 11001111b
+db 0x0000
+
+.gdt_end_p:
+
+.gdt_descriptor_p:
+ dw .gdt_end_p - .gdt_start_p - 1
+dq .gdt_start_p
+
+SMP_PROTECTED_CODE_SEGMENT equ .gdt_code_p - .gdt_start_p
+SMP_PROTECTED_DATA_SEGMENT equ .gdt_data_p - .gdt_start_p
+
+;________________________________________________________________________________________
+
+.smp_protected
+
+[bits 32]
+mov ax, SMP_PROTECTED_DATA_SEGMENT
+mov ds, ax
+mov ss, ax
+mov es, ax
+mov fs, ax
+mov gs, ax
+
+mov eax, 0x10000 ;TODO clarify _why_ this is a thing
+mov cr3, eax
+
+;setting up misc features
+mov eax, cr4
+; PAE, OSFXSR, OSXMMEXCPT
+or eax, 1 << 5 | 1 << 9 | 1 << 10
+mov cr4, eax
+
+
+;set NX and LME
+mov eax, 0x80000001
+cpuid
+and edx, 1 << 20
+shr edx, 9
+
+mov ecx, 0xc0000080
+rdmsr
+or eax, 1 << 8 | 1 << 11
+or eax, edx
+wrmsr
+
+;enable paging
+mov eax, cr0
+or eax, 1 << 31 | 1 << 0;
+and ax, ~(1 << 2)
+mov cr0, eax
+
+jmp SMP_LONG_CODE_SEGMENT:.counter
+
+;________________________________________________________________________________________
+
+[bits 64]
+;TODO do we really need all this?
+.gdt_start_l:
+;and now we set up a temporary GDT creating a 1:1 mapping
+dw 0xffff
+dw 0
+db 0 ;this is the invalid GDT
+db 0
+db 1
+db 0
+
+;now for the code GDT:
+.gdt_code_l:
+dw 0 ; segment limit 15:00 (I don't think this matters in 64 bit mode!)
+dw 0 ; base address 15:00
+db 0 ; base address 23:16
+db 10011010b
+db 00100000b
+db 0
+
+.gdt_data_l:
+dw 0
+dw 0
+db 0
+db 10010010b
+db 00100000b
+db 0
+
+.gdt_end_l: ; later calculates offset in defs below
+
+
+.descriptor_l:
+ dw .gdt_end_l - .gdt_start_l - 1
+dq .gdt_start_l
+
+SMP_LONG_CODE_SEGMENT equ .gdt_code_l - .gdt_start_l
+SMP_LONG_DATA_SEGMENT equ .gdt_data_l - .gdt_start_l
+
+.counter:
+mov rax, [smp_bootstrap_corecount]
+inc QWORD [rax]
+cli
+hlt
+;TODO set up stack; enter kernel
+
+smp_bootstrap_corecount: db 0
diff --git a/src/kernel/testmalloc.c b/src/kernel/testmalloc.c
new file mode 100644
index 0000000..5733c7c
--- /dev/null
+++ b/src/kernel/testmalloc.c
@@ -0,0 +1,35 @@
+#define CHUNK_SIZE_FROM_INDEX(i) ((1 << ((i) + 5)))
+
+#include <printf.h>
+#include <heap.h>
+#include <libc.h>
+#include <random.h>
+
+//will delete later
+
+void test_malloc(unsigned int cnt) {
+ void *testchunks[cnt];
+ unsigned int rindex[cnt], testchunk_size, i, x;
+
+ bzero(rindex, cnt * sizeof(unsigned int));
+ for(x = 0; x < cnt; x++) {
+ testchunk_size = (CHUNK_SIZE_FROM_INDEX(randint() % 7) - 24);
+ testchunks[x] = malloc(testchunk_size);
+ //printf("ALLOCATING CHUNK %p SIZE %i\n", (void *)testchunks[x] - 24, testchunk_size);
+ }
+ for(x = 0; x < cnt;) {
+ i = randint() % cnt;
+ if(rindex[i]) continue;
+ rindex[i] = x;
+ x++;
+ }
+ for(x = 0; x < cnt; x++) {
+ //printf("FREEING CHUNK %p\n", (void *)testchunks[rindex[x]]);
+ free(testchunks[rindex[x]]);
+ }
+ printf("\nmalloc tester:\n");
+ printf("THIS NEEDS TO BE EMPTY______________\n");
+ debug_heap();
+ printf("____________________________________\n");
+
+}
diff --git a/src/kernel/timer.c b/src/kernel/timer.c
new file mode 100644
index 0000000..aed42ba
--- /dev/null
+++ b/src/kernel/timer.c
@@ -0,0 +1,296 @@
+#include <acpi.h>
+#include <stdbool.h>
+#include <io.h>
+#include <printf.h>
+#include <libc.h>
+#include <kernel.h>
+#include <cpuid.h>
+#include <panic.h>
+#include <int.h>
+#include <isv.h>
+
+
+#define PIT_COMMAND 0x43
+#define PIT_FREQ 1193182
+
+#define PIT_CHANNEL_0 0x40
+#define PIT_CHANNEL_2 0x42
+#define PIT_INPUT_2 0x61
+//you can move these if it makes more sense to put them in a lapic.h
+#define LAPIC_TIMER_LVT 200
+#define LAPIC_TIMER_INIT_COUNT 224
+#define LAPIC_TIMER_CURRENT_COUNT 228
+#define LAPIC_TIMER_DIVIDE 248
+
+#define LAPIC_TIMER_MODE_ONESHOT 0b00
+#define LAPIC_TIMER_MODE_PERIODIC 0b01
+#define LAPIC_TIMER_MODE_TSC_DEADLINE 0b10
+
+#define IA32_TSC_DEADLINE 0x6E0
+
+
+struct acpi_addr_fmt {
+ uint8_t addr_space; //0 is system memory, 1 is system io
+ uint8_t reg_bit_width;
+ uint8_t reg_bit_offset;
+ uint8_t resrved;
+ uint64_t addr;
+} __attribute__((packed));
+
+struct hpet_sdt {
+ sdt_head header;
+ uint8_t hw_rev_id;
+ unsigned int comparator_cnt:5;
+ unsigned int counter_size_64bit:1;
+ unsigned int reserved:1;
+ unsigned int legacy_capable:1;
+ uint16_t vendor_id;
+ struct acpi_addr_fmt acpi_addr;
+ uint8_t hpet_number;
+ uint16_t min_tick;
+ unsigned int protection:4; //0 = no protection, 1 = 4kb, 2 = 64kb
+ unsigned int oem_attribute:4;
+} __attribute__((packed));
+
+struct hpet_info_struct {
+ uint64_t *hpet_reg;
+ unsigned int hpet_period;
+ double hpet_freq_mhz; //improves speed with us quantum
+ unsigned int timer_cnt;
+ unsigned int irqs;
+ bool long_mode;
+} hpet_info;
+
+
+struct lapic_lvt {
+ uint8_t vector;
+ unsigned int reserved:4;
+ unsigned int delivery_status:1;
+ unsigned int reserved_1:3;
+ unsigned int mask:1;
+ unsigned int timer_mode:2;
+ unsigned int reserved_2:13;
+} __attribute__((packed));
+
+extern lapic_t lapic;
+
+#define TSC_TIME_TSC_EVENT 0
+#define TSC_TIME_LAPIC_EVENT 1
+#define LAPIC_TIME_HPET_EVENT 2
+
+static int clock_mode;
+
+//time quantum is 1us
+static double tsc_freq;
+static double apic_freq;
+
+static unsigned int early_event_vector;
+
+static struct lapic_lvt lapic_timer_lvt;
+
+uint64_t timestamp() {
+ if((clock_mode == TSC_TIME_TSC_EVENT) || (clock_mode == TSC_TIME_LAPIC_EVENT)) {
+ return read_tsc() / tsc_freq;
+ }
+ else {
+ return UINT32_MAX - (lapic[LAPIC_TIMER_CURRENT_COUNT] / apic_freq);
+ }
+ return 0;
+}
+
+//timer test code
+//there is a race condition here.
+//I'm leaving it unattended, as I'm only expecting this to be used for SMP booting.
+void usleep(unsigned int us) {
+ if(clock_mode == TSC_TIME_TSC_EVENT) {
+ write_msr(IA32_TSC_DEADLINE, ((uint64_t)((us * (double)tsc_freq) + 0.5)) + read_tsc());
+ }
+ else if(clock_mode == TSC_TIME_LAPIC_EVENT) {
+ lapic[LAPIC_TIMER_INIT_COUNT] = (uint32_t)((us * (double)apic_freq) + 0.5);
+ }
+ else {
+ hpet_info.hpet_reg[33] = hpet_info.hpet_reg[30] +
+ (uint32_t)((us * hpet_info.hpet_freq_mhz) + 0.5);
+ }
+ asm("hlt\n");
+}
+
+/**
+we either use:
+1: tsc
+2: tsc
+
+1: tsc
+2: lapic (no tsc deadline)
+
+1: lapic
+2: hpet
+
+PIT not implimented, I've yet to find a computer that doesn't have HPET
+**/
+
+void calibrate_lapic() {
+ unsigned int timer_idt = alloc_idt(&KERNEL_IDT_GATE(lapic_timer_racefixer));
+ uint32_t lapic_ticks;
+ uint64_t hpet_ticks = (100000000000000 * (1 / (double)hpet_info.hpet_period)) + 0.5;
+ uint64_t timer_loops = 0;
+ struct lapic_lvt timer_lvt = {
+ .vector = timer_idt,
+ .delivery_status = 0,
+ .mask = 0,
+ .timer_mode = LAPIC_TIMER_MODE_PERIODIC
+ };
+ printf("Starting LAPIC timer calibration...\n");
+
+ lapic[LAPIC_TIMER_LVT] = *(uint32_t *)&timer_lvt;
+ lapic[LAPIC_TIMER_DIVIDE] = 0b1011;
+ asm(".global calibrate_lapic_waiting\n"
+ "xor rbx, rbx\n"
+ "mov rax, %2\n"
+ "add rax, %3\n"
+ "mov [%4], rax\n" //hpet timer
+ "mov [%5], 0xffffffff\n" //lapic timer
+ "calibrate_lapic_waiting:\n"
+ "hlt\n"
+ "mov %0, %6\n" //save lapic time
+ "mov [%5], 0\n"
+ "mov %1, rbx\n"
+ :"=r"(lapic_ticks), "=r"(timer_loops)
+ :"r"(hpet_ticks), "m"(hpet_info.hpet_reg[30]), "m"(hpet_info.hpet_reg[33]),
+ "m"(lapic[LAPIC_TIMER_INIT_COUNT]), "m"(lapic[LAPIC_TIMER_CURRENT_COUNT])
+ :"rax","rbx" );
+ apic_freq = ((UINT32_MAX * timer_loops) + (UINT32_MAX - lapic_ticks)) / (double)100000;
+
+ printf("LAPIC timer frequency: %f MHz\n", apic_freq);
+ free_idt(timer_idt);
+}
+
+
+void init_timer() {
+ struct hpet_sdt *hpet_desc = find_sdt(SDT_HPET);
+ early_event_vector = alloc_idt(&KERNEL_IDT_GATE(kernel_block));
+ if(!hpet_desc) PANIC(KERNEL_PANIC_HPET_REQUIRED);
+
+ unsigned int first_irq;
+
+ struct apic_vt hpet_redirect;
+ bzero(&hpet_redirect, sizeof(hpet_redirect));
+ hpet_redirect.vector = early_event_vector;
+ hpet_redirect.polarity = 1;
+
+
+ hpet_info.hpet_reg = PHYS_TO_VIRT(hpet_desc->acpi_addr.addr);
+ hpet_info.hpet_period = (hpet_info.hpet_reg[0] >> 32) & UINT32_MAX;
+ hpet_info.long_mode = (hpet_info.hpet_reg[0] >> 13) & 1;
+ hpet_info.irqs = (hpet_info.hpet_reg[32] >> 32) & UINT32_MAX;
+ hpet_info.hpet_freq_mhz = (1 / (double)hpet_info.hpet_period) * 1000000000;
+ //get first irq available
+ first_irq = __builtin_ctzl(hpet_info.irqs) + 1;
+
+ printf("hpet frequency: %f MHz\n", hpet_info.hpet_freq_mhz);
+
+ //do we need to worry about bypassing irq remappings?
+ create_fixed_interrupt(first_irq, &hpet_redirect);
+
+ //set irq, enable triggering of interrupts
+ hpet_info.hpet_reg[32] = (first_irq << 9) | (1 << 2) | 1;
+
+ //enable main counter
+ hpet_info.hpet_reg[2] = 1;
+
+ asm("sti\n");
+
+ //detect consistent TSC
+ uint32_t unused, cpuid_reg;
+ __get_cpuid(0x80000007, &unused, &unused, &unused, &cpuid_reg);
+
+ //goto debug_tsc;
+ if((cpuid_reg >> 8) & 1) {
+ printf("Detected invariant TSC\n");
+ //.1 second to calibrate, TODO do we need to check if the register is big enough?
+ uint64_t hpet_ticks = (100000000000000 * (1 / (double)hpet_info.hpet_period)) + 0.5;
+ printf("Starting TSC calibration...\n");
+ uint64_t volatile start_tsc, end_tsc;
+ //this may not be the fastest, but I'll improve if needed further into development
+ asm volatile(
+ "xor rax, rax\n"
+ "rdtsc\n"
+ "shl rdx, 32\n"
+ "or rax, rdx\n"
+ "mov %0, rax\n"
+ "mov rbx, %4\n"
+ "add rbx, [%3]\n"
+ "mov [%2], rbx\n"
+ //if you're worried about a single instruction being a race condition, it's time for an upgrade
+ "xor rax, rax\n"
+ "hlt\n"
+ "rdtsc\n"
+ "shl rdx, 32\n"
+ "or rax, rdx\n"
+ "mov %1, rax\n"
+ :"=&r"(start_tsc), "=&r"(end_tsc)
+ :"m"(hpet_info.hpet_reg[33]), "m"(hpet_info.hpet_reg[30]),"r"(hpet_ticks)
+ :"rax","rbx","rdx");
+ tsc_freq = (end_tsc - start_tsc) / (double)100000;
+ printf("TSC: Detected frequency is %f MHz\n", tsc_freq);
+ __get_cpuid(0x1, &unused, &unused, &cpuid_reg, &unused);
+ if((cpuid_reg >> 24) & 1) {
+ clock_mode = TSC_TIME_TSC_EVENT;
+
+ lapic_timer_lvt.vector = early_event_vector;
+ lapic_timer_lvt.timer_mode = LAPIC_TIMER_MODE_TSC_DEADLINE;
+ lapic_timer_lvt.delivery_status = 0;
+ lapic_timer_lvt.mask = 0;
+ }
+ else {
+ clock_mode = TSC_TIME_LAPIC_EVENT;
+ calibrate_lapic();
+
+ lapic_timer_lvt.vector = early_event_vector;
+ lapic_timer_lvt.timer_mode = LAPIC_TIMER_MODE_ONESHOT;
+ lapic_timer_lvt.delivery_status = 0;
+ lapic_timer_lvt.mask = 0;
+ }
+ lapic[LAPIC_TIMER_LVT] = *(uint32_t *)&lapic_timer_lvt;
+ }
+ else {
+ uint32_t apic_div;
+ clock_mode = LAPIC_TIME_HPET_EVENT;
+ calibrate_lapic();
+
+ //because lapic is used as scheduler, we want to cause as little interrupts as possible
+ //while retaining 1 mhz accuracy
+
+ apic_div = __builtin_clz((uint32_t)apic_freq);
+ if(!apic_div) {
+ apic_div = 0b1011;
+ }
+ else if(apic_div >= 7) {
+ apic_div = 0b1010;
+ apic_freq /= 128;
+ }
+ else {
+ apic_freq /= (1 << --apic_div);
+ apic_div = (((apic_div & 0b100) << 1) | (apic_div * 0b1011));
+ }
+
+ lapic_timer_lvt.vector = SPURRIOUS_VECTOR; //TODO CHANGE ME
+ lapic_timer_lvt.timer_mode = LAPIC_TIMER_MODE_PERIODIC;
+ lapic_timer_lvt.delivery_status = 0;
+ lapic_timer_lvt.mask = 1;
+ lapic[LAPIC_TIMER_DIVIDE] = apic_div;
+ lapic[LAPIC_TIMER_LVT] = *(uint32_t *)&lapic_timer_lvt;
+ lapic[LAPIC_TIMER_INIT_COUNT] = UINT32_MAX;
+ }
+ switch(clock_mode) {
+ case TSC_TIME_TSC_EVENT:
+ printf("Clock source: tsc\nEvent source: tsc-deadline\n");
+ break;
+ case TSC_TIME_LAPIC_EVENT:
+ printf("Clock source: tsc\nEvent source: lapic\n");
+ break;
+ case LAPIC_TIME_HPET_EVENT:
+ printf("Clock source: lapic\nEvent source: hpet\n");
+ break;
+ }
+}
diff --git a/src/kernel/drivers/video.c b/src/kernel/video.c
index ab73bb0..0433ce2 100644
--- a/src/kernel/drivers/video.c
+++ b/src/kernel/video.c
@@ -5,5 +5,6 @@
void dump_video() {
struct mode_info *video = (struct mode_info *)0x600;
- printf("Video info:\nx:\t%u\ny:\t%u\nbbp:\t%u\nloc:\t0x%p\n", video->width, video->height, video->bpp, video->framebuffer);
+ printf("Video info:\nx:\t%u\ny:\t%u\nbbp:\t%u\nloc:\t0x%p\n",
+ video->width, video->height, video->bpp, video->framebuffer);
}
diff --git a/src/link.ld b/src/link.ld
index f45ddec..529d43f 100644
--- a/src/link.ld
+++ b/src/link.ld
@@ -1,38 +1,34 @@
SEARCH_DIR(objects)
-INPUT(
-bootloader.o
-libc.o
-serial.o
-video.o
-printf.o
-page.o
-acpi.o
-kernel.o
-panic.o
-)
-
-_kernel_stack_loc = 0x200000 - 8;
-_kernel_loc = 0x100000;
-_meminfo_loc = 0x7000;
+_kernel_s1_loc = 0xffffffff80000000;
+_meminfo = 0x7000;
_vbe_infoblock = 0x500;
-_stage2_pagetable = 0x200000;
-_stage1_pagetable = 0x4000;
SECTIONS
{
- . = 0x0;
- bootloader 0x7c00 :
+ bootloader 0x7c00 : AT(0)
{
- bootloader.o(.text)
+ bootloader.o(.text)
}
- kernel _kernel_loc :
- AT (ADDR(bootloader) + SIZEOF(bootloader))
- /*ALIGN(4096)*/
+ smp_bootloader 0x8000 :
+ AT(SIZEOF(bootloader))
{
- EXCLUDE_FILE (*bootloader.o) *(.text .data .bss .rodata .comment .eh_frame)
+ smp_trampoline.o(.text)
}
+ kernel _kernel_s1_loc :
+ AT (SIZEOF(bootloader))
+ {
+ EXCLUDE_FILE (*bootloader.o) *(.text .data .bss .rodata .comment .eh_frame)
+ }
}
-_kernel_size = ((SIZEOF(kernel) / 512) + (SIZEOF(bootloader) / 512)); /* there's a bug here I think!*/
-_bootloader_stage1_size = (SIZEOF(bootloader) / 512);
+_kernel_sector_size = ((SIZEOF(kernel) + SIZEOF(smp_bootloader) + 511) / 512);
+_kernel_page_size = ((SIZEOF(kernel) + SIZEOF(smp_bootloader) + 0xfff) / 0x1000);
+_bootloader_stage1_size = (SIZEOF(bootloader) + 511) / 512;
+
+__load_start_smp_bootloader = LOADADDR(smp_bootloader);
+__load_stop_smp_bootloader = LOADADDR(smp_bootloader) + SIZEOF(smp_bootloader);
+
+_kernel_stack_loc = (0x100000 + (_kernel_page_size * 0x1000) + 0x2000) - 8;
+_kernel_shared_zone_begin = 0x100000 + (_kernel_page_size * 0x1000) + 0x2000;
+
diff --git a/src/makefile b/src/makefile
index 2398509..83876c2 100644
--- a/src/makefile
+++ b/src/makefile
@@ -4,60 +4,98 @@ OBJCPY=../compiler/indigo_gcc/bin/x86_64-elf-objcopy
INC=-I./include
EMU_CORES=4
-EMU_RAM=4G
+EMU_RAM=5G
XRES=1024
YRES=768
-CCFLAGS=-g -ffreestanding -Wall
+CFLAGS=-g -ffreestanding -mcmodel=kernel -masm=intel -Wall -O0
-make:
- nasm -g -felf64 bootloader/bootloader.asm -o objects/bootloader.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/kernel.c -o objects/kernel.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/panic.c -o objects/panic.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/acpi.c -o objects/acpi.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/drivers/serial.c -o objects/serial.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/drivers/video.c -o objects/video.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/printf.c -o objects/printf.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/page.c -o objects/page.o
- $(CC) $(INC) $(CCFLAGS) -c kernel/libc.c -o objects/libc.o
- $(LD) -o indigo_os.elf --oformat=elf64-x86-64 -T link.ld
+C_SRCFILES := $(wildcard kernel/*.c)
+C_SRCFILES := $(filter-out kernel/isv.c, $(C_SRCFILES))
+C_OBJFILES := $(patsubst kernel/%.c,%.o,$(C_SRCFILES))
+
+ASM_SRCFILES := $(wildcard kernel/*.asm)
+ASM_SRCFILES := $(filter-out kernel/smp_trampoline.asm, $(ASM_SRCFILES))
+ASM_OBJFILES := $(patsubst kernel/%.asm,%.o,$(ASM_SRCFILES))
+
+
+MISC_OBJFILES := isv.o #this will probably expand over time for files that require special treatment
+OBJFILES_PATH := $(patsubst %,objects/%,$(C_OBJFILES) $(ASM_OBJFILES) $(MISC_OBJFILES))
+
+QEMU_OPTS=-smp $(EMU_CORES) -m $(EMU_RAM) -no-reboot -drive format=raw,file=./indigo_os
+
+QEMU_CPU=-cpu host,+invtsc,+tsc-deadline
+
+ifndef disable-kvm
+ QEMU_OPTS := $(QEMU_OPTS) -enable-kvm $(QEMU_CPU)
+endif
+
+QEMU_PRINTDEBUG=-d int,guest_errors
+
+
+
+all: $(ASM_OBJFILES) $(C_OBJFILES) $(MISC_OBJFILES) bootloader.o smp_trampoline.o
+ $(LD) -o indigo_os.elf --no-check-sections --oformat=elf64-x86-64 -T link.ld $(OBJFILES_PATH)
$(OBJCPY) --only-keep-debug indigo_os.elf debug/debug_syms.o
$(OBJCPY) -O binary --strip-all indigo_os.elf indigo_os
-ifneq ("$(wildcard $(./debug/serial.in))","")
- mkfifo debug/serial.in
+ compiledb make --dry-run > /dev/null
+
+
+isv.o: kernel/isv.c
+ $(CC) $(CFLAGS) $(INC) -mgeneral-regs-only -MMD -MP -c kernel/isv.c -o objects/$@
+
+printf.o: kernel/printf.c
+ifdef screen
+ $(CC) $(CFLAGS) $(INC) -MMD -MP -DSCREEN_OUTPUT -c kernel/printf.c -o objects/$@
+else
+ $(CC) $(CFLAGS) $(INC) -MMD -MP -c kernel/printf.c -o objects/$@
endif
-ifneq ("$(wildcard $(./debug/serial.out))","")
- mkfifo debug/serial.out
+
+kernel.o: kernel/kernel.c
+ifdef screen
+ $(CC) $(CFLAGS) $(INC) -MMD -MP -DSCREEN_OUTPUT -c kernel/kernel.c -o objects/$@
+else
+ $(CC) $(CFLAGS) $(INC) -MMD -MP -c kernel/kernel.c -o objects/$@
endif
-# rm -f indigo_os.elf
+%.o: kernel/%.c makefile
+ $(CC) $(CFLAGS) $(INC) -MMD -MP -c $< -o objects/$@
+
+%.o: kernel/%.asm makefile
+ nasm -g -felf64 $< -o objects/$@
+
+bootloader.o:
+ nasm -g -felf64 bootloader/bootloader.asm -o objects/bootloader.o
-preproc_debug:
- nasm -g -felf64 bootloader/bootloader.asm
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/kernel.c
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/acpi.c
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/drivers/serial.c
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/drivers/video.c
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/printf.c
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/page.c
- $(CC) $(INC) $(CCFLAGS) -E -c kernel/libc.c
+smp_trampoline.o:
+ nasm -g -felf64 kernel/smp_trampoline.asm -o objects/smp_trampoline.o
run:
- qemu-system-x86_64 -smp $(EMU_CORES) -m $(EMU_RAM) -nographic -no-reboot -drive format=raw,file=./indigo_os
-
+ qemu-system-x86_64 $(QEMU_OPTS) $(QEMU_PRINTDEBUG) -nographic
gdb: indigo_os
- tmux new-session -s os_gdb "qemu-system-x86_64 -smp $(EMU_CORES) -nographic -no-reboot -S -s -drive format=raw,file=./indigo_os -m $(EMU_RAM)"\;\
+ tmux new-session -s os_gdb "qemu-system-x86_64 -S -s $(QEMU_OPTS) -nographic"\;\
split-window -h "gdb -x debug/gdbinit.gdb; killall qemu-system-x86_64"
run-graphical:
- qemu-system-x86_64 -S -s -smp $(EMU_CORES) -m $(EMU_RAM) -no-reboot -serial pipe:debug/serial -device VGA,edid=on,xres=$(XRES),yres=$(YRES) -drive format=raw,file=./indigo_os &\
+ qemu-system-x86_64 -device VGA,edid=on,xres=$(XRES),yres=$(YRES) -S -s $(QEMU_OPTS) &\
gdb -x debug/gdbinit.gdb; killall qemu-system-x86_64
+
+install-sandisk: indigo_os
+ test -h /dev/disk/by-id/usb-SanDisk_Cruzer_Fit_4C531001351010112404-0:0 && \
+ sudo dd if=indigo_os of=/dev/disk/by-id/usb-SanDisk_Cruzer_Fit_4C531001351010112404-0:0 && \
+ sync
+
+install-trav: indigo_os
+ test -h /dev/disk/by-id/usb-Kingston_DataTraveler_3.0_E0D55EA573F1E3A11963008B-0:0 && \
+ sudo dd if=indigo_os of=/dev/disk/by-id/usb-Kingston_DataTraveler_3.0_E0D55EA573F1E3A11963008B-0:0 && \
+ sync
+
+
clean:
rm -f objects/*
rm -f indigo_os
+ rm -f indigo_os.elf
rm -f bin/*
rm -f debug/debug_syms.o
- rm -f debug/serial.in
- rm -f debug/serial.out