summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorBrett Weiland <brett_weiland@bpcspace.com>2021-04-18 16:00:17 -0500
committerBrett Weiland <brett_weiland@bpcspace.com>2021-04-18 16:00:17 -0500
commit774e3796b252383aafb8b3f30d51a19400c74516 (patch)
tree20ad93c125d4f6bad755e6a898ddb4259818b4fa /src/kernel
parentf0602964daa20ad9cd05f097b943c8edbf2df2e2 (diff)
modified: src/bootloader/bios_functions/bios_disk.asm
modified: src/bootloader/bootloader.asm new file: src/include/kernel.h modified: src/include/libc.h modified: src/include/paging.h new file: src/include/panic.h modified: src/kernel/kernel.c modified: src/kernel/libc.c modified: src/kernel/page.c new file: src/kernel/panic.c modified: src/link.ld modified: src/makefile modified: tools/page/page.py
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/kernel.c28
-rw-r--r--src/kernel/libc.c25
-rw-r--r--src/kernel/page.c220
-rw-r--r--src/kernel/panic.c54
4 files changed, 271 insertions, 56 deletions
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index d7fc3e0..025dcf3 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -4,14 +4,29 @@
#include <paging.h>
#include <video.h>
#include <acpi.h>
+#include <panic.h>
-void panic() { // will fill with debugging info latter
- printf("Kernel panic!\n");
- for(;;);
+
+void test4() {
+ char bruh[10];
+ panic(KERNEL_PANIC_KERNEL_RETURNED, KERNEL_PANIC_INVOKED);
+}
+void test3() {
+ char bruh[5];
+ test4();
+}
+void test2() {
+ int a = 1;
+ test3();
+}
+void test1() {
+ printf("fuck\n");
+ test2();
}
void main() {
+ test1();
if(!(init_serial(COM1))) {
printf("\nKernal started on CPU 1!\n"); // will detect cpu later
}
@@ -20,15 +35,16 @@ void main() {
rsdp = find_RSDP();
if(!(rsdp)) {
printf("Couldn't find the RSDP... not sure what to do now.\n");
- panic();
+ panic(KERNEL_PANIC_RSDP_UNFOUND, KERNEL_PANIC_INVOKED);
}
dump_video();
debug_print_memory();
- init_memory();
+ init_pmap();
+ debug_pmap();
- panic();
+ panic(KERNEL_PANIC_KERNEL_RETURNED, KERNEL_PANIC_INVOKED);
}
diff --git a/src/kernel/libc.c b/src/kernel/libc.c
index dc5c0ac..c786cd0 100644
--- a/src/kernel/libc.c
+++ b/src/kernel/libc.c
@@ -39,22 +39,33 @@ void strcpy(char *dest, char *src) {
}
}
-void memcpy(char *dest, char *src, size_t n) {
+void *memcpy(void *dest, char *src, size_t n) {
+ char *p = dest;
for(unsigned int i = 0; i <= n; i++) {
- dest[i] = src[i];
+ p[i] = src[i];
}
+ return(dest);
}
-void bzero(void *dest, size_t size) {
- unsigned char *p1 = dest;
+void *bzero(void *dest, size_t size) {
+ char *p = dest;
for(uint64_t i = 0; i < size; i++) {
- p1[i] = 0;
+ p[i] = 0;
}
+ return(dest);
}
//TODO move this function to a seperate math library
-int ceil(float n) {
+unsigned int ceil(double n) {
int low_n = (int)n;
- if(n == (float)low_n) return(low_n);
+ if(n == (double)low_n) return(low_n);
return(low_n + 1);
}
+
+void *memset(void *s, char c, size_t n) {
+ char *p = s;
+ for(size_t i = 0; i < n; i++) {
+ p[i] = c;
+ }
+ return(s);
+}
diff --git a/src/kernel/page.c b/src/kernel/page.c
index 6f1dd7c..de4f557 100644
--- a/src/kernel/page.c
+++ b/src/kernel/page.c
@@ -2,6 +2,8 @@
#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;
@@ -14,62 +16,194 @@ void debug_print_memory() {
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: %p\t is free\n",
+ pmap->buddy[order] + blong_i, bbit_i, (uint64_t)pmap->zone_paddr + (((blong_i * 64) + bbit_i) * buddy_chunksize));
+ }
+ omit_cnt++;
+ if(omit_cnt == 20) {
+ printf("\t\t\t[more entries ommited]\n");
+ }
+ }
+ }
+ }
+ }
+ pmap_i++;
+ }
+}
+
+void init_pmap() {
+ struct memory_table *zones = (struct memory_table *)&_meminfo_loc;
+ struct phys_map *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], *buddy_end;
+ uint64_t pmap_size, pmap_bbitsize, pmap_blongsize, buddy_size, buddy_bit, pmap_bit;
+ uint64_t threshold_bitsize, threshold_longsize = 0;
-//uses buddy system allocation
-void init_memory() {
- struct memory_table *memtable = (struct memory_table *)&_meminfo_loc;
- struct phys_map *map = (struct phys_map*)0x200000;
- uintptr_t onpage = 0x200000;
- unsigned int i, x, buddy_size, buddy_bitsize, prev_buddy_bsize;
- uint64_t *buddy_ptr;
-
- map_page((void*)0x200000, (void*)0x200000, PAGE_SIZE_2M);
- void *next_page = (void *)onpage + 0x200000;
- // at this point, we are declaring our header and kernel itself as free (so don't forget to fix that!)
- 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;
+ 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++) {
- for(x = 0; x < 8; x++) {
+ if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1)) {
- buddy_bitsize = memtable[i].length / (0x1000 * (1 << x));
- buddy_size = ceil(buddy_bitsize / (float)8);
+ //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((void *)buddy_ptr + buddy_size >= next_page) {
- map_page(next_page, next_page, PAGE_SIZE_2M);
- next_page += 0x200000;
- }
+ 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;
+ }
- bzero(buddy_ptr, buddy_size); //meant to be /8?
- if((buddy_bitsize * 2) != prev_buddy_bsize) {
- buddy_ptr[-1] |= (1 << ((prev_buddy_bsize % 8) - 1));
- }
+ 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;
+ }
- buddy_ptr += buddy_size;
+ pmap->buddy[0] = (void *)pmap + sizeof(*pmap);
- prev_buddy_bsize = buddy_bitsize;
+ 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]);
+ }
- }
- map->map_size = buddy_ptr - (uint64_t*)map;
- map = (struct phys_map *)map + map->map_size;
+ 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++;
- if((void *)map + 24 >= next_page) {
- map_page(next_page, next_page, PAGE_SIZE_2M);
- next_page += 0x200000;
+ //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_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;
+
+ 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;
+
+ threshold_longsize = threshold_bitsize / 64;
+ }
+ pmap_bit = pmap_bbitsize & 63;
+ buddy_bit = buddy_bitlen[pmap_i][budorder] & 63;
-//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) {
+
+ if((pmap_bbitsize >= BITLEN_FROM_LSIZE(buddy_size)) && (pmap == (void *)&_stage2_pagetable)) {
+ bzero(pmap->buddy[budorder], buddy_size * 8);
+ }
+ 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);
+
+ 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));
+ }
+ }
+ }
+ }
+ pmap_i++;
+ }
}
@@ -97,7 +231,7 @@ bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) {
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)
+ if(table->pdpe[pdpe_i].base_ptr == ((uintptr_t)pa_ptr >> 30 & 0x1ff))
return true;
goto error;
}
@@ -105,7 +239,7 @@ bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) {
if(table->pde[pde_i].present) {
if(size == PAGE_SIZE_2M) {
- if(table->pde[pde_i].base_ptr == (uintptr_t)pa_ptr >> 21 & 0x1ff)
+ if(table->pde[pde_i].base_ptr == ((uintptr_t)pa_ptr >> 21 & 0x1ff))
return true;
goto error;
}
diff --git a/src/kernel/panic.c b/src/kernel/panic.c
new file mode 100644
index 0000000..851684a
--- /dev/null
+++ b/src/kernel/panic.c
@@ -0,0 +1,54 @@
+#include <panic.h>
+#include <stdint.h>
+#include <printf.h>
+
+void panic(int reason, int type) { // will fill with debugging info latter
+
+ struct stack_frame *frame;
+
+#ifdef EASTEREGG_BLOATWARE
+ printf("Kernel PANIC!!!!!!!\n");
+ printf(
+" _.-^^---....,,-- \n"
+" _-- --_ \n"
+"< >)\n"
+"| BOOM | <------- your computer\n"
+" \\._ _./ \n"
+" ```--. . , ; .--''' \n"
+" | | | \n"
+" .-=|| | |=-. \n"
+" `-=#$%&%$#=-' \n"
+" | ; :| \n"
+" _____.,-#%&$@%#&#~,._____\n");
+#else
+ 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;
+ }
+ printf("\nStack trace:\n");
+
+ asm("mov %%rbp,%0" : "=r"(frame) ::);
+
+ for(; frame->next != 0; frame = frame->next) {
+ printf("\t%x\n", frame->function_base);
+ }
+
+ //It's not public yet, but 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(;;);
+
+}